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,148 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'tempfile'
5
+ require 'stringio'
6
+ require 'hexapdf/type/file_specification'
7
+ require 'hexapdf/document'
8
+
9
+ describe HexaPDF::Type::FileSpecification::EFDictionary do
10
+ it "uses a custom type" do
11
+ obj = HexaPDF::Type::FileSpecification::EFDictionary.new({})
12
+ assert_equal(:XXFilespecEFDictionary, obj.type)
13
+ end
14
+ end
15
+
16
+ describe HexaPDF::Type::FileSpecification do
17
+ before do
18
+ @doc = HexaPDF::Document.new
19
+ @obj = HexaPDF::Type::FileSpecification.new({}, document: @doc)
20
+ end
21
+
22
+ it "can be asked whether it is a URL or a file" do
23
+ refute(@obj.url?)
24
+ @obj[:FS] = :URL
25
+ assert(@obj.url?)
26
+ end
27
+
28
+ describe "path" do
29
+ it "returns the first useable file spec string" do
30
+ @obj[:DOS] = 'hälo'.b
31
+ assert_equal('hälo'.b, @obj.path)
32
+
33
+ @obj[:UF] = 'hälo'
34
+ assert_equal('hälo', @obj.path)
35
+ end
36
+
37
+ it "unescapes the path string according to the PDF spec" do
38
+ @obj[:F] = "dir/in\\/out\\too"
39
+ assert_equal('dir/in/out/too', @obj.path)
40
+ end
41
+ end
42
+
43
+ describe "path=" do
44
+ it "only sets /UF and /F, deleting /Mac, /Unix, /DOS entries if they exist" do
45
+ @obj[:Unix] = @obj[:Mac] = @obj[:DOS] = 'a'
46
+ @obj.path = 'file/test'
47
+ assert_equal('file/test', @obj[:UF])
48
+ assert_equal('file/test', @obj[:F])
49
+ refute(@obj.key?(:Unix))
50
+ refute(@obj.key?(:Mac))
51
+ refute(@obj.key?(:DOS))
52
+ end
53
+
54
+ it 'resets the /FS value' do
55
+ @obj[:FS] = :Something
56
+ @obj.path = 'file'
57
+ refute(@obj.key?(:FS))
58
+ end
59
+ end
60
+
61
+ describe "url=" do
62
+ it "sets the path and the file system entry" do
63
+ url = 'http://example.com/some?test=ing#done'
64
+ @obj.url = url
65
+ assert_equal(url, @obj.path)
66
+ assert(@obj.url?)
67
+ end
68
+
69
+ it "fails if the provided string is not a valid URL" do
70
+ assert_raises(HexaPDF::Error) { @obj.url = "a false \\ URL" }
71
+ end
72
+ end
73
+
74
+ describe "embedded_file?" do
75
+ it "checks whether the specification has an embedded file" do
76
+ refute(@obj.embedded_file?)
77
+ @obj[:EF] = {UF: {}}
78
+ assert(@obj.embedded_file?)
79
+ end
80
+ end
81
+
82
+ describe "embedded_file_stream" do
83
+ it "returns the associated embedded file stream" do
84
+ assert_nil(@obj.embedded_file_stream)
85
+ @obj[:EF] = {F: 'data'}
86
+ assert_equal('data', @obj.embedded_file_stream)
87
+ end
88
+ end
89
+
90
+ describe "embed/unembed" do
91
+ before do
92
+ @file = Tempfile.new('file-embed-test')
93
+ @file.write("embed-test")
94
+ @file.close
95
+ end
96
+
97
+ after do
98
+ @file.unlink
99
+ end
100
+
101
+ it "requires the name argument when given an IO object" do
102
+ assert_raises(ArgumentError) { @obj.embed(StringIO.new) }
103
+ end
104
+
105
+ it "embeds the given file and registers it with the global name registry" do
106
+ stream = @obj.embed(@file.path)
107
+ assert_equal(stream, @obj[:EF][:UF])
108
+ assert_equal(stream, @obj[:EF][:F])
109
+ assert_equal(File.basename(@file.path), @obj.path)
110
+ assert_equal(@obj, @doc.catalog[:Names][:EmbeddedFiles].find_entry(@obj.path))
111
+ assert_equal(:FlateDecode, stream[:Filter])
112
+ assert_equal('embed-test', stream.stream)
113
+ end
114
+
115
+ it "embeds the given IO object" do
116
+ @file.open
117
+ stream = @obj.embed(@file, name: 'test')
118
+ assert_equal('embed-test', stream.stream)
119
+
120
+ stream = @obj.embed(StringIO.new('test'), name: 'test')
121
+ assert_equal('test', stream.stream)
122
+ end
123
+
124
+ it "allows overriding the name" do
125
+ @obj.embed(@file.path, name: 'test')
126
+ assert_equal('test', @obj.path)
127
+ assert_equal(@obj, @doc.catalog[:Names][:EmbeddedFiles].find_entry('test'))
128
+ end
129
+
130
+ it "doesn't register the embedded file if instructed to do so" do
131
+ @obj.embed(@file.path, name: 'test', register: false)
132
+ assert_nil(@doc.catalog[:Names])
133
+ end
134
+
135
+ it "replaces the value of an already registered name" do
136
+ (@doc.catalog[:Names] ||= {})[:EmbeddedFiles] = {}
137
+ @doc.catalog[:Names][:EmbeddedFiles].add_entry('test', 'data')
138
+ @obj.embed(@file.path, name: 'test')
139
+ assert_equal(@obj, @doc.catalog[:Names][:EmbeddedFiles].find_entry('test'))
140
+ end
141
+
142
+ it "unembeds an already embedded file before embedding the new one" do
143
+ @obj.embed(@file.path, name: 'test1')
144
+ @obj.embed(@file.path, name: 'test2')
145
+ assert_equal([['test2', @obj]], @doc.catalog[:Names][:EmbeddedFiles].each_entry.to_a)
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/font'
6
+
7
+ describe HexaPDF::Type::Font do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ cmap = @doc.add({}, stream: <<-EOF)
11
+ 2 beginbfchar
12
+ <20> <0041>
13
+ <22> <0042>
14
+ endbfchar
15
+ EOF
16
+ @font = @doc.add({Type: :Font, BaseFont: :TestFont, ToUnicode: cmap})
17
+ end
18
+
19
+ it "must always be an indirect" do
20
+ assert(@font.must_be_indirect?)
21
+ end
22
+
23
+ describe "to_utf" do
24
+ it "uses the /ToUnicode CMap if it is available" do
25
+ assert_equal("A", @font.to_utf8(32))
26
+ assert_equal("B", @font.to_utf8(34))
27
+ assert_equal("", @font.to_utf8(0))
28
+ end
29
+
30
+ it "returns an empty string if no /ToUnicode CMap is available" do
31
+ @font.delete(:ToUnicode)
32
+ assert_equal("", @font.to_utf8(32))
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,51 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/font_descriptor'
6
+
7
+ describe HexaPDF::Type::FontDescriptor do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @font_desc = @doc.add(Type: :FontDescriptor, FontName: :Test, Flags: 0b1001001, ItalicAngle: 10)
11
+ end
12
+
13
+ describe "flags" do
14
+ it "returns all flags" do
15
+ assert_equal([:fixed_pitch, :script, :italic], @font_desc.flags)
16
+ end
17
+ end
18
+
19
+ describe "flagged?" do
20
+ it "returns true if the given flag is set" do
21
+ assert(@font_desc.flagged?(:fixed_pitch))
22
+ refute(@font_desc.flagged?(:serif))
23
+ end
24
+
25
+ it "raises an error if an unknown flag name is provided" do
26
+ assert_raises(ArgumentError) { @font_desc.flagged?(:unknown) }
27
+ end
28
+ end
29
+
30
+ describe "flag" do
31
+ it "sets the given flag bits" do
32
+ @font_desc.flag(:serif)
33
+ assert_equal([:fixed_pitch, :serif, :script, :italic], @font_desc.flags)
34
+ @font_desc.flag(:symbolic, clear_existing: true)
35
+ assert_equal([:symbolic], @font_desc.flags)
36
+ end
37
+ end
38
+
39
+ describe "validation" do
40
+ it "fails if more than one of /FontFile{,2,3} are set" do
41
+ assert(@font_desc.validate {|*args| p args})
42
+ @font_desc[:FontFile] = @font_desc[:FontFile2] = @doc.add({}, stream: 'test')
43
+ refute(@font_desc.validate)
44
+ end
45
+
46
+ it "fails if /Descent is not a negative number" do
47
+ @font_desc[:Descent] = 5
48
+ refute(@font_desc.validate)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,190 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/font_simple'
6
+
7
+ describe HexaPDF::Type::FontSimple do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ cmap = @doc.add({}, stream: <<-EOF)
11
+ 2 beginbfchar
12
+ <20> <0041>
13
+ <22> <0042>
14
+ endbfchar
15
+ EOF
16
+ font_descriptor = @doc.add(Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
17
+ FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
18
+ Descent: -100, CapHeight: 800, StemV: 20)
19
+ @font = @doc.add({Type: :Font, Encoding: :WinAnsiEncoding,
20
+ BaseFont: :Embedded, FontDescriptor: font_descriptor, ToUnicode: cmap,
21
+ FirstChar: 32, LastChar: 34, Widths: [600, 0, 700]
22
+ }, type: HexaPDF::Type::FontSimple)
23
+ end
24
+
25
+ describe "encoding" do
26
+ it "fails if /Encoding is absent because encoding_from_font is not implemented" do
27
+ @font.delete(:Encoding)
28
+ assert_raises(NotImplementedError) { @font.encoding }
29
+ end
30
+
31
+ describe "/Encoding is a name" do
32
+ it "returns a predefined encoding if /Encoding specifies one" do
33
+ assert_equal(HexaPDF::Font::Encoding.for_name(:WinAnsiEncoding), @font.encoding)
34
+ end
35
+
36
+ it "fails if /Encoding is an invalid name because encoding_from_font is not implemented" do
37
+ @font[:Encoding] = :SomethingUnknown
38
+ assert_raises(NotImplementedError) { @font.encoding }
39
+ end
40
+ end
41
+
42
+ describe "/Encoding is a dictionary" do
43
+ before do
44
+ @font[:Encoding] = {}
45
+ end
46
+
47
+ describe "no /BaseEncoding is specified" do
48
+ it "fails if the font is embedded because encoding_from_font is not implemented" do
49
+ @font[:FontDescriptor][:FontFile] = 5
50
+ assert_raises(NotImplementedError) { @font.encoding }
51
+ end
52
+
53
+ it "fails for a symbolic non-embedded font because encoding_from_font is not implemented" do
54
+ @font[:FontDescriptor].flag(:symbolic, clear_existing: true)
55
+ assert_raises(NotImplementedError) { @font.encoding }
56
+ end
57
+
58
+ it "returns the StandardEncoding for a non-symbolic non-embedded font" do
59
+ @font[:FontDescriptor].flag(clear_existing: true)
60
+ assert_equal(HexaPDF::Font::Encoding.for_name(:StandardEncoding), @font.encoding)
61
+ end
62
+ end
63
+
64
+ it "returns the encoding specified by /BaseEncoding" do
65
+ @font[:Encoding] = {BaseEncoding: :WinAnsiEncoding}
66
+ assert_equal(HexaPDF::Font::Encoding.for_name(:WinAnsiEncoding), @font.encoding)
67
+ end
68
+
69
+ it "fails if /BaseEncoding is invalid because encoding_from_font is not implemented" do
70
+ @font[:Encoding] = {BaseEncoding: :SomethingUnknown}
71
+ assert_raises(NotImplementedError) { @font.encoding }
72
+ end
73
+
74
+ it "returns a difference encoding if /Differences is specified" do
75
+ @font[:FontDescriptor].flag(clear_existing: true)
76
+ @font[:Encoding][:Differences] = [32, :A, :B, 34, :Z]
77
+ refute_equal(HexaPDF::Font::Encoding.for_name(:StandardEncoding), @font.encoding)
78
+ assert_equal(:A, @font.encoding.name(32))
79
+ assert_equal(:B, @font.encoding.name(33))
80
+ assert_equal(:Z, @font.encoding.name(34))
81
+ end
82
+
83
+ it "fails if the /Differences array contains invalid data" do
84
+ @font[:Encoding][:BaseEncoding] = :WinAnsiEncoding
85
+ @font[:Encoding][:Differences] = [:B, 32, :A, :B, 34, :Z]
86
+ assert_raises(HexaPDF::Error) { @font.encoding }
87
+
88
+ @font[:Encoding][:Differences] = [32, "data", :A, :B, 34, :Z]
89
+ assert_raises(HexaPDF::Error) { @font.encoding }
90
+ end
91
+ end
92
+
93
+ it "fails if /Encoding contains an invalid value" do
94
+ @font[:Encoding] = 5
95
+ assert_raises(HexaPDF::Error) { @font.encoding }
96
+ end
97
+ end
98
+
99
+ describe "decode" do
100
+ it "just returns the bytes of the string since this is a simple 1-byte-per-code font" do
101
+ assert_equal([65, 66], @font.decode("AB"))
102
+ end
103
+ end
104
+
105
+ describe "to_utf" do
106
+ it "uses a /ToUnicode CMap if it is available" do
107
+ assert_equal("A", @font.to_utf8(32))
108
+ end
109
+
110
+ it "uses the font's encoding to map the code to an UTF-8 string if the /ToUnicode is missing" do
111
+ @font.delete(:ToUnicode)
112
+ assert_equal(" ", @font.to_utf8(32))
113
+ end
114
+
115
+ it "returns an empty string if no correct mapping could be found" do
116
+ @font.delete(:ToUnicode)
117
+ assert_equal("", @font.to_utf8(0))
118
+ end
119
+ end
120
+
121
+ describe "writing_mode" do
122
+ it "is always horizontal" do
123
+ assert_equal(:horizontal, @font.writing_mode)
124
+ end
125
+ end
126
+
127
+ describe "width" do
128
+ it "returns the glyph width for a valid code point" do
129
+ assert_equal(600, @font.width(32))
130
+ end
131
+
132
+ it "returns the /MissingWidth of a /FontDescriptor if available and the width was not found" do
133
+ assert_equal(0, @font.width(0))
134
+ @font[:FontDescriptor][:MissingWidth] = 99
135
+ assert_equal(99, @font.width(0))
136
+ end
137
+
138
+ it "returns 0 for a missing code point when FontDescriptor is not available" do
139
+ @font.delete(:FontDescriptor)
140
+ assert_equal(0, @font.width(0))
141
+ end
142
+ end
143
+
144
+ describe "bounding_box" do
145
+ it "returns the bounding box" do
146
+ assert_equal([0, 1, 2, 3], @font.bounding_box)
147
+ end
148
+
149
+ it "returns nil if no bounding box information can be found" do
150
+ @font[:FontDescriptor].delete(:FontBBox)
151
+ assert_nil(@font.bounding_box)
152
+ end
153
+ end
154
+
155
+ describe "embedded" do
156
+ it "returns true if the font is embedded" do
157
+ refute(@font.embedded?)
158
+ @font[:FontDescriptor][:FontFile] = 5
159
+ assert(@font.embedded?)
160
+ end
161
+ end
162
+
163
+ describe "symbolic?" do
164
+ it "return true if the font is symbolic" do
165
+ @font[:FontDescriptor].flag(clear_existing: true)
166
+ refute(@font.symbolic?)
167
+
168
+ @font[:FontDescriptor].flag(:symbolic)
169
+ assert(@font.symbolic?)
170
+ end
171
+
172
+ it "returns nil if it cannot be determined whether the font is symbolic" do
173
+ @font.delete(:FontDescriptor)
174
+ assert_nil(@font.symbolic?)
175
+ end
176
+ end
177
+
178
+ describe "validation" do
179
+ it "validates the existence of required keys" do
180
+ assert(@font.validate)
181
+ @font.delete(:FirstChar)
182
+ refute(@font.validate)
183
+ end
184
+
185
+ it "validates the lengths of the /Widths field" do
186
+ @font[:Widths] = [65]
187
+ refute(@font.validate)
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,128 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/font_type1'
6
+
7
+ describe HexaPDF::Type::FontType1::StandardFonts do
8
+ before do
9
+ @obj = HexaPDF::Type::FontType1::StandardFonts
10
+ end
11
+
12
+ it "checks whether a given name corresponds to a standard font via #standard_font?" do
13
+ assert(@obj.standard_font?(:"Times-Roman"))
14
+ assert(@obj.standard_font?(:TimesNewRoman))
15
+ refute(@obj.standard_font?(:LibreSans))
16
+ end
17
+
18
+ it "returns the standard PDF name for an alias via #standard_name" do
19
+ assert_equal(:"Times-Roman", @obj.standard_name(:TimesNewRoman))
20
+ end
21
+
22
+ describe "font" do
23
+ it "returns the Type1 font object for a given standard name" do
24
+ font = @obj.font(:"Times-Roman")
25
+ assert_equal("Times Roman", font.full_name)
26
+ end
27
+
28
+ it "caches the font for reuse" do
29
+ font = @obj.font(:"Times-Roman")
30
+ assert_same(font, @obj.font(:"Times-Roman"))
31
+ end
32
+
33
+ it "returns nil if the given name doesn't belong to a standard font" do
34
+ refute_nil(@obj.font(:TimesNewRoman))
35
+ end
36
+ end
37
+ end
38
+
39
+ describe HexaPDF::Type::FontType1 do
40
+ before do
41
+ @doc = HexaPDF::Document.new
42
+ @font = @doc.add(Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
43
+ BaseFont: :"Times-Roman")
44
+
45
+ font_file = @doc.add({}, stream: <<-EOF)
46
+ /Encoding 256 array
47
+ 0 1 255 {1 index exch /.notdef put} for
48
+ dup 32 /A put
49
+ dup 34 /B put
50
+ readonly def
51
+ EOF
52
+ font_descriptor = @doc.add(Type: :FontDescriptor, FontName: :Embedded, Flags: 0b100,
53
+ FontBBox: [0, 1, 2, 3], ItalicAngle: 0, Ascent: 900,
54
+ Descent: -100, CapHeight: 800, StemV: 20, FontFile: font_file)
55
+ @embedded_font = @doc.add(Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
56
+ BaseFont: :Embedded, FontDescriptor: font_descriptor,
57
+ FirstChar: 32, LastChar: 34, Widths: [600, 0, 700])
58
+ end
59
+
60
+ describe "encoding" do
61
+ it "returns the the standard font's encoding" do
62
+ @font.delete(:Encoding)
63
+ assert_equal(HexaPDF::Font::Encoding.for_name(:StandardEncoding), @font.encoding)
64
+ end
65
+
66
+ it "uses the encoding of the embedded font when necessary" do
67
+ @embedded_font.delete(:Encoding)
68
+ assert_equal({32 => :A, 34 => :B}, @embedded_font.encoding.code_to_name)
69
+ end
70
+
71
+ it "fails if the encoding needs to be read from the font but is is not embedded" do
72
+ @embedded_font.delete(:Encoding)
73
+ @embedded_font[:FontDescriptor].delete(:FontFile)
74
+ assert_raises(HexaPDF::Error) { @embedded_font.encoding }
75
+ end
76
+ end
77
+
78
+ describe "width" do
79
+ it "returns the glyph width when using a standard font" do
80
+ assert_equal(250, @font.width(32))
81
+ end
82
+
83
+ it "defers to its superclass for all other cases" do
84
+ assert_equal(600, @embedded_font.width(32))
85
+ end
86
+ end
87
+
88
+ describe "bounding_box" do
89
+ it "returns the bounding box for a standard font" do
90
+ font = HexaPDF::Type::FontType1::StandardFonts.font(:"Times-Roman")
91
+ assert_equal(font.bounding_box, @font.bounding_box)
92
+ end
93
+
94
+ it "defers to its superclass for all other cases" do
95
+ assert_equal([0, 1, 2, 3], @embedded_font.bounding_box)
96
+ end
97
+
98
+ it "returns nil for non-standard fonts without bounding box information" do
99
+ @embedded_font[:FontDescriptor].delete(:FontBBox)
100
+ assert_nil(@embedded_font.bounding_box)
101
+ end
102
+ end
103
+
104
+ describe "symbolic?" do
105
+ it "return true for the standard fonts Symbol and ZapfDingbats" do
106
+ @font[:BaseFont] = :Symbol
107
+ assert(@font.symbolic?)
108
+
109
+ @font[:BaseFont] = :ZapfDingbats
110
+ assert(@font.symbolic?)
111
+ end
112
+
113
+ it "defers to its superclass for all other cases" do
114
+ assert(@embedded_font.symbolic?)
115
+ end
116
+
117
+ it "returns nil if it cannot be determined whether the font is symbolic" do
118
+ @embedded_font.delete(:FontDescriptor)
119
+ assert_nil(@embedded_font.symbolic?)
120
+ end
121
+ end
122
+
123
+ describe "validation" do
124
+ it "allows empty fields for standard fonts" do
125
+ assert(@font.validate)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,60 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require_relative '../content/common'
5
+ require 'hexapdf/document'
6
+ require 'hexapdf/type/form'
7
+
8
+ describe HexaPDF::Type::Form do
9
+ before do
10
+ @doc = HexaPDF::Document.new
11
+ @form = @doc.wrap({}, subtype: :Form)
12
+ end
13
+
14
+ describe "box" do
15
+ it "returns the /BBox entry" do
16
+ @form[:BBox] = :media
17
+ assert_equal(:media, @form.box)
18
+ end
19
+ end
20
+
21
+ describe "contents" do
22
+ it "returns a duplicate of the stream" do
23
+ @form.stream = 'test'
24
+ assert_equal(@form.stream, @form.contents)
25
+ @form.contents.gsub!(/test/, 'other')
26
+ assert_equal(@form.stream, @form.contents)
27
+ end
28
+ end
29
+
30
+ describe "contents=" do
31
+ it "set the stream contents" do
32
+ @form.contents = 'test'
33
+ assert_equal('test', @form.stream)
34
+ end
35
+ end
36
+
37
+ describe "resources" do
38
+ it "creates the resource dictionary if it is not found" do
39
+ resources = @form.resources
40
+ assert_equal(:XXResources, resources.type)
41
+ assert_equal({}, resources.value)
42
+ end
43
+
44
+ it "returns the already used resource dictionary" do
45
+ @form[:Resources] = {Font: nil}
46
+ resources = @form.resources
47
+ assert_equal(:XXResources, resources.type)
48
+ assert_equal(@form[:Resources], resources)
49
+ end
50
+ end
51
+
52
+ describe "process_contents" do
53
+ it "parses the contents and processes it" do
54
+ @form.stream = '10 w'
55
+ processor = TestHelper::OperatorRecorder.new
56
+ @form.process_contents(processor)
57
+ assert_equal([[:set_line_width, [10]]], processor.recorded_ops)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+ require 'hexapdf/type/info'
3
+
4
+ describe HexaPDF::Type::Info do
5
+ it "must always be indirect" do
6
+ obj = HexaPDF::Type::Info.new({})
7
+ assert(obj.must_be_indirect?)
8
+ end
9
+
10
+ it "uses a custom type" do
11
+ obj = HexaPDF::Type::Info.new({})
12
+ assert_equal(:XXInfo, obj.type)
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+ require 'hexapdf/type/names'
3
+
4
+ describe HexaPDF::Type::Names do
5
+ it "uses a custom type" do
6
+ obj = HexaPDF::Type::Names.new({})
7
+ assert_equal(:XXNames, obj.type)
8
+ end
9
+ end