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,619 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/content/operator'
5
+ require 'hexapdf/content/processor'
6
+ require 'hexapdf/serializer'
7
+
8
+ describe HexaPDF::Content::Operator::BaseOperator do
9
+ before do
10
+ @op = HexaPDF::Content::Operator::BaseOperator.new('name')
11
+ end
12
+
13
+ it "takes a name on initialization and can return it" do
14
+ assert_equal('name', @op.name)
15
+ assert(@op.name.frozen?)
16
+ end
17
+
18
+ it "responds to invoke" do
19
+ assert_respond_to(@op, :invoke)
20
+ end
21
+
22
+ it "can serialize any operator with its operands" do
23
+ serializer = HexaPDF::Serializer.new
24
+ assert_equal("5.0 5 /Name name\n", @op.serialize(serializer, 5.0, 5, :Name))
25
+ end
26
+ end
27
+
28
+ describe HexaPDF::Content::Operator::NoArgumentOperator do
29
+ it "provides a special serialize method" do
30
+ op = HexaPDF::Content::Operator::NoArgumentOperator.new('name')
31
+ assert_equal("name\n", op.serialize(nil))
32
+ end
33
+ end
34
+
35
+ describe HexaPDF::Content::Operator::SingleNumericArgumentOperator do
36
+ it "provides a special serialize method" do
37
+ op = HexaPDF::Content::Operator::SingleNumericArgumentOperator.new('name')
38
+ serializer = HexaPDF::Serializer.new
39
+ assert_equal("5 name\n", op.serialize(serializer, 5))
40
+ assert_equal("5.45 name\n", op.serialize(serializer, 5.45))
41
+ end
42
+ end
43
+
44
+
45
+ module CommonOperatorTests
46
+ extend Minitest::Spec::DSL
47
+
48
+ before do
49
+ resources = {}
50
+ resources.define_singleton_method(:color_space) do |name|
51
+ HexaPDF::GlobalConfiguration.constantize('color_space.map', name).new
52
+ end
53
+ resources.define_singleton_method(:ext_gstate) do |name|
54
+ self[:ExtGState] && self[:ExtGState][name] || raise(HexaPDF::Error, "missing")
55
+ end
56
+ @processor = HexaPDF::Content::Processor.new(resources)
57
+ @serializer = HexaPDF::Serializer.new
58
+ end
59
+
60
+ # calls the method of the operator with the operands
61
+ def call(method, *operands)
62
+ HexaPDF::Content::Operator::DEFAULT_OPERATORS[@name].send(method, *operands)
63
+ end
64
+
65
+ # calls the invoke method on the operator
66
+ def invoke(*operands)
67
+ call(:invoke, @processor, *operands)
68
+ end
69
+
70
+ it "is associated with the correct operator name in the default mapping" do
71
+ assert_equal(@name, call(:name).to_sym)
72
+ end
73
+
74
+ it "is not the base operator implementation" do
75
+ refute_equal(HexaPDF::Content::Operator::BaseOperator, call(:class))
76
+ end
77
+
78
+ def assert_serialized(*operands)
79
+ op = HexaPDF::Content::Operator::BaseOperator.new(@name.to_s)
80
+ assert_equal(op.serialize(@serializer, *operands), call(:serialize, @serializer, *operands))
81
+ end
82
+
83
+ end
84
+
85
+ def describe_operator(name, symbol, &block)
86
+ klass_name = "HexaPDF::Content::Operator::#{name}"
87
+ klass = describe(klass_name, &block)
88
+ klass.send(:include, CommonOperatorTests)
89
+ one_time_module = Module.new
90
+ one_time_module.send(:define_method, :setup) do
91
+ super()
92
+ @name = symbol
93
+ end
94
+ one_time_module.send(:define_method, :test_class_name) do
95
+ assert_equal(klass_name, call(:class).name)
96
+ end
97
+ klass.send(:include, one_time_module)
98
+ klass
99
+ end
100
+
101
+
102
+ describe_operator :SaveGraphicsState, :q do
103
+ it "saves the graphics state" do
104
+ width = @processor.graphics_state.line_width
105
+ invoke
106
+ @processor.graphics_state.line_width = 10
107
+ @processor.graphics_state.restore
108
+ assert_equal(width, @processor.graphics_state.line_width)
109
+ end
110
+ end
111
+
112
+ describe_operator :RestoreGraphicsState, :Q do
113
+ it "restores the graphics state" do
114
+ width = @processor.graphics_state.line_width
115
+ @processor.graphics_state.save
116
+ @processor.graphics_state.line_width = 10
117
+ invoke
118
+ assert_equal(width, @processor.graphics_state.line_width)
119
+ end
120
+ end
121
+
122
+ describe_operator :ConcatenateMatrix, :cm do
123
+ it "concatenates the ctm by pre-multiplication" do
124
+ invoke(1, 2, 3, 4, 5, 6)
125
+ invoke(6, 5, 4, 3, 2, 1)
126
+ assert_equal(21, @processor.graphics_state.ctm.a)
127
+ assert_equal(32, @processor.graphics_state.ctm.b)
128
+ assert_equal(13, @processor.graphics_state.ctm.c)
129
+ assert_equal(20, @processor.graphics_state.ctm.d)
130
+ assert_equal(10, @processor.graphics_state.ctm.e)
131
+ assert_equal(14, @processor.graphics_state.ctm.f)
132
+ end
133
+
134
+ it "serializes correctly" do
135
+ assert_serialized(1, 2, 3, 4, 5, 6)
136
+ end
137
+ end
138
+
139
+ describe_operator :SetLineWidth, :w do
140
+ it "sets the line width" do
141
+ invoke(10)
142
+ assert_equal(10, @processor.graphics_state.line_width)
143
+ end
144
+ end
145
+
146
+ describe_operator :SetLineCapStyle, :J do
147
+ it "sets the line cap" do
148
+ invoke(HexaPDF::Content::LineCapStyle::ROUND_CAP)
149
+ assert_equal(HexaPDF::Content::LineCapStyle::ROUND_CAP,
150
+ @processor.graphics_state.line_cap_style)
151
+ end
152
+ end
153
+
154
+ describe_operator :SetLineJoinStyle, :j do
155
+ it "sets the line join" do
156
+ invoke(HexaPDF::Content::LineJoinStyle::ROUND_JOIN)
157
+ assert_equal(HexaPDF::Content::LineJoinStyle::ROUND_JOIN,
158
+ @processor.graphics_state.line_join_style)
159
+ end
160
+ end
161
+
162
+ describe_operator :SetMiterLimit, :M do
163
+ it "sets the miter limit" do
164
+ invoke(100)
165
+ assert_equal(100, @processor.graphics_state.miter_limit)
166
+ end
167
+ end
168
+
169
+ describe_operator :SetLineDashPattern, :d do
170
+ it "sets the line dash pattern" do
171
+ invoke([3, 4], 5)
172
+ assert_equal(HexaPDF::Content::LineDashPattern.new([3, 4], 5),
173
+ @processor.graphics_state.line_dash_pattern)
174
+ end
175
+
176
+ it "serializes correctly" do
177
+ assert_serialized([3, 4], 5)
178
+ end
179
+ end
180
+
181
+ describe_operator :SetRenderingIntent, :ri do
182
+ it "sets the rendering intent" do
183
+ invoke(HexaPDF::Content::RenderingIntent::SATURATION)
184
+ assert_equal(HexaPDF::Content::RenderingIntent::SATURATION,
185
+ @processor.graphics_state.rendering_intent)
186
+ end
187
+
188
+ it "serializes correctly" do
189
+ assert_serialized(HexaPDF::Content::RenderingIntent::SATURATION)
190
+ end
191
+ end
192
+
193
+ describe_operator :SetGraphicsStateParameters, :gs do
194
+ it "applies parameters from an ExtGState dictionary" do
195
+ @processor.resources[:ExtGState] = {Name: {LW: 10, LC: 2, LJ: 2, ML: 2, D: [[3, 5], 2],
196
+ RI: 2, SA: true, BM: :Multiply, CA: 0.5, ca: 0.5,
197
+ AIS: true, TK: false, Font: [:Test, 10]}}
198
+ @processor.resources.define_singleton_method(:document) do
199
+ Object.new.tap {|obj| obj.define_singleton_method(:deref) {|o| o}}
200
+ end
201
+
202
+ invoke(:Name)
203
+ gs = @processor.graphics_state
204
+ assert_equal(10, gs.line_width)
205
+ assert_equal(2, gs.line_cap_style)
206
+ assert_equal(2, gs.line_join_style)
207
+ assert_equal(2, gs.miter_limit)
208
+ assert_equal(HexaPDF::Content::LineDashPattern.new([3, 5], 2), gs.line_dash_pattern)
209
+ assert_equal(2, gs.rendering_intent)
210
+ assert(gs.stroke_adjustment)
211
+ assert_equal(:Multiply, gs.blend_mode)
212
+ assert_equal(0.5, gs.stroke_alpha)
213
+ assert_equal(0.5, gs.fill_alpha)
214
+ assert(gs.alpha_source)
215
+ assert_equal(:Test, gs.font)
216
+ assert_equal(10, gs.font_size)
217
+ refute(gs.text_knockout)
218
+ end
219
+
220
+ it "fails if the resources dictionary doesn't have an ExtGState entry" do
221
+ assert_raises(HexaPDF::Error) { invoke(:Name) }
222
+ end
223
+
224
+ it "fails if the ExtGState resources doesn't have the specified dictionary" do
225
+ @processor.resources[:ExtGState] = {}
226
+ assert_raises(HexaPDF::Error) { invoke(:Name) }
227
+ end
228
+
229
+ it "serializes correctly" do
230
+ assert_serialized(:Name)
231
+ end
232
+ end
233
+
234
+ describe_operator :SetStrokingColorSpace, :CS do
235
+ it "sets the stroking color space" do
236
+ invoke(:DeviceRGB)
237
+ assert_equal(@processor.resources.color_space(:DeviceRGB), @processor.graphics_state.stroke_color_space)
238
+ end
239
+
240
+ it "serializes correctly" do
241
+ assert_serialized(:DeviceRGB)
242
+ end
243
+ end
244
+
245
+ describe_operator :SetNonStrokingColorSpace, :cs do
246
+ it "sets the non stroking color space" do
247
+ invoke(:DeviceRGB)
248
+ assert_equal(@processor.resources.color_space(:DeviceRGB),
249
+ @processor.graphics_state.fill_color_space)
250
+ end
251
+
252
+ it "serializes correctly" do
253
+ assert_serialized(:DeviceRGB)
254
+ end
255
+ end
256
+
257
+ describe_operator :SetStrokingColor, :SC do
258
+ it "sets the stroking color" do
259
+ invoke(128)
260
+ assert_equal(@processor.resources.color_space(:DeviceGray).color(128),
261
+ @processor.graphics_state.stroke_color)
262
+ end
263
+
264
+ it "serializes correctly" do
265
+ assert_serialized(128, 129, 130)
266
+ end
267
+ end
268
+
269
+ describe_operator :SetNonStrokingColor, :sc do
270
+ it "sets the non stroking color" do
271
+ invoke(128)
272
+ assert_equal(@processor.resources.color_space(:DeviceGray).color(128),
273
+ @processor.graphics_state.fill_color)
274
+ end
275
+
276
+ it "serializes correctly" do
277
+ assert_serialized(128, 129, 130)
278
+ end
279
+ end
280
+
281
+ describe_operator :SetDeviceGrayStrokingColor, :G do
282
+ it "sets the DeviceGray stroking color" do
283
+ invoke(128)
284
+ assert_equal(@processor.resources.color_space(:DeviceGray).color(128),
285
+ @processor.graphics_state.stroke_color)
286
+ end
287
+ end
288
+
289
+ describe_operator :SetDeviceGrayNonStrokingColor, :g do
290
+ it "sets the DeviceGray non stroking color" do
291
+ invoke(128)
292
+ assert_equal(@processor.resources.color_space(:DeviceGray).color(128),
293
+ @processor.graphics_state.fill_color)
294
+ end
295
+ end
296
+
297
+ describe_operator :SetDeviceRGBStrokingColor, :RG do
298
+ it "sets the DeviceRGB stroking color" do
299
+ invoke(128, 0, 128)
300
+ assert_equal(@processor.resources.color_space(:DeviceRGB).color(128, 0, 128),
301
+ @processor.graphics_state.stroke_color)
302
+ end
303
+
304
+ it "serializes correctly" do
305
+ assert_serialized(128, 129, 130)
306
+ end
307
+ end
308
+
309
+ describe_operator :SetDeviceRGBNonStrokingColor, :rg do
310
+ it "sets the DeviceRGB non stroking color" do
311
+ invoke(128, 0, 128)
312
+ assert_equal(@processor.resources.color_space(:DeviceRGB).color(128, 0, 128),
313
+ @processor.graphics_state.fill_color)
314
+ end
315
+
316
+ it "serializes correctly" do
317
+ assert_serialized(128, 129, 130)
318
+ end
319
+ end
320
+
321
+ describe_operator :SetDeviceCMYKStrokingColor, :K do
322
+ it "sets the DeviceCMYK stroking color" do
323
+ invoke(128, 0, 128, 128)
324
+ assert_equal(@processor.resources.color_space(:DeviceCMYK).color(128, 0, 128, 128),
325
+ @processor.graphics_state.stroke_color)
326
+ end
327
+
328
+ it "serializes correctly" do
329
+ assert_serialized(128, 129, 130, 131)
330
+ end
331
+ end
332
+
333
+ describe_operator :SetDeviceCMYKNonStrokingColor, :k do
334
+ it "sets the DeviceCMYK non stroking color" do
335
+ invoke(128, 0, 128, 128)
336
+ assert_equal(@processor.resources.color_space(:DeviceCMYK).color(128, 0, 128, 128),
337
+ @processor.graphics_state.fill_color)
338
+ end
339
+
340
+ it "serializes correctly" do
341
+ assert_serialized(128, 129, 130, 131)
342
+ end
343
+ end
344
+
345
+ describe_operator :MoveTo, :m do
346
+ it "changes the graphics object to path" do
347
+ refute_equal(:path, @processor.graphics_object)
348
+ invoke(128, 0)
349
+ assert_equal(:path, @processor.graphics_object)
350
+ end
351
+
352
+ it "serializes correctly" do
353
+ assert_serialized(1.54, 1.78)
354
+ end
355
+ end
356
+
357
+ describe_operator :AppendRectangle, :re do
358
+ it "changes the graphics object to path" do
359
+ refute_equal(:path, @processor.graphics_object)
360
+ invoke(128, 0, 10, 10)
361
+ assert_equal(:path, @processor.graphics_object)
362
+ end
363
+
364
+ it "serializes correctly" do
365
+ assert_serialized(10, 11, 1.54, 1.78)
366
+ end
367
+ end
368
+
369
+ describe_operator :LineTo, :l do
370
+ it "serializes correctly" do
371
+ assert_serialized(1.54, 1.78)
372
+ end
373
+ end
374
+
375
+ describe_operator :CurveTo, :c do
376
+ it "serializes correctly" do
377
+ assert_serialized(1.54, 1.78, 2, 3, 5, 6)
378
+ end
379
+ end
380
+
381
+ describe_operator :CurveToNoFirstControlPoint, :v do
382
+ it "serializes correctly" do
383
+ assert_serialized(2, 3, 5, 6)
384
+ end
385
+ end
386
+
387
+ describe_operator :CurveToNoSecondControlPoint, :y do
388
+ it "serializes correctly" do
389
+ assert_serialized(2, 3, 5, 6)
390
+ end
391
+ end
392
+
393
+ [:S, :s, :f, :F, 'f*'.intern, :B, 'B*'.intern, :b, 'b*'.intern, :n].each do |sym|
394
+ describe_operator :EndPath, sym do
395
+ it "changes the graphics object to none" do
396
+ @processor.graphics_object = :path
397
+ invoke
398
+ refute_equal(:path, @processor.graphics_object)
399
+ end
400
+ end
401
+ end
402
+
403
+ [:W, 'W*'.intern].each do |sym|
404
+ describe_operator :ClipPath, sym do
405
+ it "changes the graphics object to clipping_path for clip path operations" do
406
+ invoke
407
+ assert_equal(:clipping_path, @processor.graphics_object)
408
+ end
409
+ end
410
+ end
411
+
412
+ describe_operator :InlineImage, :BI do
413
+ it "serializes correctly" do
414
+ assert_equal("BI\n/Name 5 /OP 6 ID\nsome dataEI\n",
415
+ call(:serialize, @serializer, {Name: 5, OP: 6}, 'some data'))
416
+ end
417
+ end
418
+
419
+ describe_operator :SetCharacterSpacing, :Tc do
420
+ it "modifies the character spacing" do
421
+ invoke(127)
422
+ assert_equal(127, @processor.graphics_state.character_spacing)
423
+ end
424
+ end
425
+
426
+ describe_operator :SetWordSpacing, :Tw do
427
+ it "modifies the word spacing" do
428
+ invoke(127)
429
+ assert_equal(127, @processor.graphics_state.word_spacing)
430
+ end
431
+ end
432
+
433
+ describe_operator :SetHorizontalScaling, :Tz do
434
+ it "modifies the horizontal scaling parameter" do
435
+ invoke(127)
436
+ assert_equal(127, @processor.graphics_state.horizontal_scaling)
437
+ end
438
+ end
439
+
440
+ describe_operator :SetLeading, :TL do
441
+ it "modifies the leading parameter" do
442
+ invoke(127)
443
+ assert_equal(127, @processor.graphics_state.leading)
444
+ end
445
+ end
446
+
447
+ describe_operator :SetFontAndSize, :Tf do
448
+ it "sets the font and size correctly" do
449
+ @processor.resources.define_singleton_method(:font) do |name|
450
+ self[:Font] && self[:Font][name]
451
+ end
452
+
453
+ @processor.resources[:Font] = {F1: :test}
454
+ invoke(:F1, 10)
455
+ assert_equal(@processor.resources.font(:F1), @processor.graphics_state.font)
456
+ assert_equal(10, @processor.graphics_state.font_size)
457
+ end
458
+
459
+ it "serializes correctly" do
460
+ assert_serialized(:Font, 1.78)
461
+ end
462
+ end
463
+
464
+ describe_operator :SetTextRenderingMode, :Tr do
465
+ it "modifies the text rendering mode" do
466
+ invoke(127)
467
+ assert_equal(127, @processor.graphics_state.text_rendering_mode)
468
+ end
469
+ end
470
+
471
+ describe_operator :SetTextRise, :Ts do
472
+ it "modifies the text rise" do
473
+ invoke(127)
474
+ assert_equal(127, @processor.graphics_state.text_rise)
475
+ end
476
+ end
477
+
478
+ describe_operator :BeginText, :BT do
479
+ it "changes the graphics object to text and the tm/tlm to the identity matrix" do
480
+ @processor.graphics_object = :none
481
+ invoke
482
+ assert_equal(:text, @processor.graphics_object)
483
+ assert_equal(HexaPDF::Content::TransformationMatrix.new, @processor.graphics_state.tm)
484
+ assert_equal(HexaPDF::Content::TransformationMatrix.new, @processor.graphics_state.tlm)
485
+ end
486
+ end
487
+
488
+ describe_operator :EndText, :ET do
489
+ it "changes the graphics object to :none and undefines the text and text line matrices" do
490
+ @processor.graphics_object = :text
491
+ invoke
492
+ assert_equal(:none, @processor.graphics_object)
493
+ assert_nil(@processor.graphics_state.tm)
494
+ assert_nil(@processor.graphics_state.tlm)
495
+ end
496
+ end
497
+
498
+ describe_operator :MoveText, :Td do
499
+ it "correctly updates the text and text line matrices" do
500
+ @processor.graphics_state.tm = HexaPDF::Content::TransformationMatrix.new
501
+ @processor.graphics_state.tlm = HexaPDF::Content::TransformationMatrix.new
502
+ invoke(5, 10)
503
+ assert_equal(HexaPDF::Content::TransformationMatrix.new(1, 0, 0, 1, 5, 10),
504
+ @processor.graphics_state.tm)
505
+ assert_equal(HexaPDF::Content::TransformationMatrix.new(1, 0, 0, 1, 5, 10),
506
+ @processor.graphics_state.tlm)
507
+ end
508
+
509
+ it "serializes correctly" do
510
+ assert_serialized(1.54, 1.78)
511
+ end
512
+ end
513
+
514
+ describe_operator :MoveTextAndSetLeading, :TD do
515
+ it "invokes the TL and Td operators" do
516
+ tl = Minitest::Mock.new
517
+ tl.expect(:invoke, nil, [@processor, -1.78])
518
+ @processor.operators[:TL] = tl
519
+ td = Minitest::Mock.new
520
+ td.expect(:invoke, nil, [@processor, 1.56, 1.78])
521
+ @processor.operators[:Td] = td
522
+
523
+ invoke(1.56, 1.78)
524
+ tl.verify
525
+ td.verify
526
+ end
527
+
528
+ it "serializes correctly" do
529
+ assert_serialized(1.54, 1.78)
530
+ end
531
+ end
532
+
533
+ describe_operator :SetTextMatrix, :Tm do
534
+ it "correctly sets the text and text line matrices" do
535
+ @processor.graphics_state.tm = HexaPDF::Content::TransformationMatrix.new
536
+ @processor.graphics_state.tlm = HexaPDF::Content::TransformationMatrix.new
537
+ invoke(2, 3, 4, 5, 6, 7)
538
+ assert_equal(HexaPDF::Content::TransformationMatrix.new(2, 3, 4, 5, 6, 7),
539
+ @processor.graphics_state.tm)
540
+ assert_equal(HexaPDF::Content::TransformationMatrix.new(2, 3, 4, 5, 6, 7),
541
+ @processor.graphics_state.tlm)
542
+ end
543
+
544
+ it "serializes correctly" do
545
+ assert_serialized(1, 2, 3, 4, 5, 6)
546
+ end
547
+ end
548
+
549
+ describe_operator :MoveTextNextLine, :'T*' do
550
+ it "invokes the Td operator" do
551
+ td = Minitest::Mock.new
552
+ td.expect(:invoke, nil, [@processor, 0, -1.78])
553
+ @processor.operators[:Td] = td
554
+
555
+ @processor.graphics_state.leading = 1.78
556
+ invoke
557
+ td.verify
558
+ end
559
+ end
560
+
561
+ describe_operator :ShowText, :Tj do
562
+ it "serializes correctly" do
563
+ assert_serialized("Some Text")
564
+ end
565
+ end
566
+
567
+ describe_operator :MoveTextNextLineAndShowText, :"'" do
568
+ it "invokes the T* and Tj operators" do
569
+ text = "Some text"
570
+
571
+ tstar = Minitest::Mock.new
572
+ tstar.expect(:invoke, nil, [@processor])
573
+ @processor.operators[:'T*'] = tstar
574
+ tj = Minitest::Mock.new
575
+ tj.expect(:invoke, nil, [@processor, text])
576
+ @processor.operators[:Tj] = tj
577
+
578
+ invoke(text)
579
+ tstar.verify
580
+ tj.verify
581
+ end
582
+
583
+ it "serializes correctly" do
584
+ assert_serialized("Some Text")
585
+ end
586
+ end
587
+
588
+ describe_operator :SetSpacingMoveTextNextLineAndShowText, :'"' do
589
+ it "invokes the Tw, Tc and ' operators" do
590
+ word_spacing = 10
591
+ char_spacing = 15
592
+ text = "Some text"
593
+
594
+ tw = Minitest::Mock.new
595
+ tw.expect(:invoke, nil, [@processor, word_spacing])
596
+ @processor.operators[:Tw] = tw
597
+ tc = Minitest::Mock.new
598
+ tc.expect(:invoke, nil, [@processor, char_spacing])
599
+ @processor.operators[:Tc] = tc
600
+ tapos = Minitest::Mock.new
601
+ tapos.expect(:invoke, nil, [@processor, text])
602
+ @processor.operators[:"'"] = tapos
603
+
604
+ invoke(word_spacing, char_spacing, text)
605
+ tw.verify
606
+ tc.verify
607
+ tapos.verify
608
+ end
609
+
610
+ it "serializes correctly" do
611
+ assert_serialized(10, 15, "Some Text")
612
+ end
613
+ end
614
+
615
+ describe_operator :ShowTextWithPositioning, :TJ do
616
+ it "serializes correctly" do
617
+ assert_serialized(["Some Text", 15, "other text", 20, "final text"])
618
+ end
619
+ end
@@ -0,0 +1,66 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/content/parser'
5
+ require 'hexapdf/content/processor'
6
+ require_relative '../common_tokenizer_tests'
7
+ require_relative 'common'
8
+
9
+ describe HexaPDF::Content::Tokenizer do
10
+ include CommonTokenizerTests
11
+
12
+ def create_tokenizer(str)
13
+ @tokenizer = HexaPDF::Content::Tokenizer.new(str.b)
14
+ end
15
+ end
16
+
17
+ describe HexaPDF::Content::Parser do
18
+ before do
19
+ @processor = TestHelper::OperatorRecorder.new
20
+ @parser = HexaPDF::Content::Parser.new
21
+ end
22
+
23
+ describe "parse" do
24
+ it "parses a simple content stream without inline images" do
25
+ @parser.parse("0 0.500 m q Q /Name SCN", @processor)
26
+ assert_equal([[:move_to, [0, 0.5]], [:save_graphics_state],
27
+ [:restore_graphics_state],
28
+ [:set_stroking_color, [:Name]]], @processor.recorded_ops)
29
+ end
30
+
31
+ it "parses a content stream with inline images" do
32
+ @parser.parse("q BI /Name 0.5/Other 1 ID some dataEI Q", @processor)
33
+ assert_equal([[:save_graphics_state],
34
+ [:inline_image, [{Name: 0.5, Other: 1}, "some data"]],
35
+ [:restore_graphics_state]], @processor.recorded_ops)
36
+ end
37
+
38
+ it "fails parsing inline images if the dictionary keys are not PDF names" do
39
+ exp = assert_raises(HexaPDF::Error) do
40
+ @parser.parse("q BI /Name 0.5 Other 1 ID some dataEI Q", @processor)
41
+ end
42
+ assert_match(/keys.*PDF name/, exp.message)
43
+ end
44
+
45
+ it "fails parsing inline images when trying to read a dict key and EOS is encountered" do
46
+ exp = assert_raises(HexaPDF::Error) do
47
+ @parser.parse("q BI /Name 0.5", @processor)
48
+ end
49
+ assert_match(/EOS.*dictionary key/, exp.message)
50
+ end
51
+
52
+ it "fails parsing inline images when trying to read a dict value and EOS is encountered" do
53
+ exp = assert_raises(HexaPDF::Error) do
54
+ @parser.parse("q BI /Name 0.5 /Other", @processor)
55
+ end
56
+ assert_match(/EOS.*dictionary value/, exp.message)
57
+ end
58
+
59
+ it "fails parsing inline images if the EI is not found" do
60
+ exp = assert_raises(HexaPDF::Error) do
61
+ @parser.parse("q BI /Name 0.5 /Other 1 ID test", @processor)
62
+ end
63
+ assert_match(/EI not found/, exp.message)
64
+ end
65
+ end
66
+ end