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,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/table/head'
6
+ require 'hexapdf/font/true_type/table/loca'
7
+
8
+ describe HexaPDF::Font::TrueType::Table::Loca do
9
+ before do
10
+ @file = Object.new
11
+ @file.define_singleton_method(:io) { @io ||= StringIO.new('') }
12
+ head = HexaPDF::Font::TrueType::Table::Head.new(@file)
13
+ head.index_to_loc_format = 0
14
+ @file.define_singleton_method(:[]) {|_arg| head }
15
+ @entry = HexaPDF::Font::TrueType::Table::Directory::Entry.new('loca', 0, 0, @file.io.length)
16
+ end
17
+
18
+ describe "initialize" do
19
+ it "reads the data in short format from the associated file" do
20
+ @file.io.string = [0, 10, 30, 50, 90].pack('n*')
21
+ @entry.length = @file.io.length
22
+ table = HexaPDF::Font::TrueType::Table::Loca.new(@file, @entry)
23
+ assert_equal([0, 20, 60, 100, 180], table.offsets)
24
+ assert_equal(0, table.offset(0))
25
+ assert_equal(100, table.offset(3))
26
+ assert_equal(20, table.length(0))
27
+ assert_equal(80, table.length(3))
28
+ end
29
+
30
+ it "reads the data in long format from the associated file" do
31
+ @file.io.string = [0, 10, 30, 50, 90].pack('N*')
32
+ @file[:head].index_to_loc_format = 1
33
+ @entry.length = @file.io.length
34
+ table = HexaPDF::Font::TrueType::Table::Loca.new(@file, @entry)
35
+ assert_equal([0, 10, 30, 50, 90], table.offsets)
36
+ end
37
+
38
+ it "loads some default values if no entry is given" do
39
+ table = HexaPDF::Font::TrueType::Table::Loca.new(@file)
40
+ assert_equal([], table.offsets)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,62 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/table/maxp'
6
+
7
+ describe HexaPDF::Font::TrueType::Table::Maxp do
8
+ before do
9
+ data = [1, 0, 10, 11, 12, 13, 14, 2, 15, 16, 17, 18, 19, 20, 21, 22].pack('n*')
10
+ io = StringIO.new(data)
11
+ @file = Object.new
12
+ @file.define_singleton_method(:io) { io }
13
+ @entry = HexaPDF::Font::TrueType::Table::Directory::Entry.new('hhea', 0, 0, io.length)
14
+ end
15
+
16
+ describe "initialize" do
17
+ it "reads the version 1.0 data from the associated file" do
18
+ table = HexaPDF::Font::TrueType::Table::Maxp.new(@file, @entry)
19
+ assert_equal(1, table.version)
20
+ assert_equal(10, table.num_glyphs)
21
+ assert_equal(11, table.max_points)
22
+ assert_equal(12, table.max_contours)
23
+ assert_equal(13, table.max_component_points)
24
+ assert_equal(14, table.max_component_contours)
25
+ assert_equal(15, table.max_twilight_points)
26
+ assert_equal(16, table.max_storage)
27
+ assert_equal(17, table.max_function_defs)
28
+ assert_equal(18, table.max_instruction_defs)
29
+ assert_equal(19, table.max_stack_elements)
30
+ assert_equal(20, table.max_size_of_instructions)
31
+ assert_equal(21, table.max_component_elements)
32
+ assert_equal(22, table.max_component_depth)
33
+ end
34
+
35
+ it "reads the version 0.5 data from the associated file" do
36
+ @file.io.string = [0, 0x5000, 10].pack('n*')
37
+ @entry.length = @file.io.length
38
+ table = HexaPDF::Font::TrueType::Table::Maxp.new(@file, @entry)
39
+ assert_equal(0.3125, table.version)
40
+ assert_equal(10, table.num_glyphs)
41
+ assert_nil(table.max_points)
42
+ assert_nil(table.max_contours)
43
+ assert_nil(table.max_component_points)
44
+ assert_nil(table.max_component_contours)
45
+ assert_nil(table.max_twilight_points)
46
+ assert_nil(table.max_storage)
47
+ assert_nil(table.max_function_defs)
48
+ assert_nil(table.max_instruction_defs)
49
+ assert_nil(table.max_stack_elements)
50
+ assert_nil(table.max_size_of_instructions)
51
+ assert_nil(table.max_component_elements)
52
+ assert_nil(table.max_component_depth)
53
+ end
54
+
55
+ it "loads some default values if no entry is given" do
56
+ table = HexaPDF::Font::TrueType::Table::Maxp.new(@file)
57
+ assert_equal(1, table.version)
58
+ assert_equal(0, table.num_glyphs)
59
+ assert_equal(0, table.max_points)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,95 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/table/name'
6
+
7
+ describe HexaPDF::Font::TrueType::Table::Name do
8
+ before do
9
+ @file = Object.new
10
+ @file.define_singleton_method(:io) { @io ||= StringIO.new(''.b) }
11
+
12
+ @file.io.string = [0, 3, 42].pack('n3')
13
+ @file.io.string << [1, 0, 0, 0, 4, 0].pack('n6')
14
+ @file.io.string << [0, 3, 1, 0, 8, 4].pack('n6')
15
+ @file.io.string << [0, 3, 2, 1, 14, 12].pack('n6')
16
+ @file.io.string << 'hexa'.encode('MACROMAN').b << 'hexa'.encode('UTF-16BE').b <<
17
+ 'hexapdf'.encode('UTF-16BE').b
18
+
19
+ @entry = HexaPDF::Font::TrueType::Table::Directory::Entry.new('name', 0, 0, @file.io.length)
20
+ end
21
+
22
+ describe "initialize" do
23
+ it "reads the data in format 0 from the associated file" do
24
+ table = HexaPDF::Font::TrueType::Table::Name.new(@file, @entry)
25
+ assert_equal(0, table.format)
26
+ assert_equal({}, table.language_tags)
27
+ assert_equal('hexa', table[:copyright][0])
28
+ assert_equal(1, table[:copyright][0].platform_id)
29
+ assert_equal(0, table[:copyright][0].encoding_id)
30
+ assert_equal(0, table[:copyright][0].language_id)
31
+ assert_equal('hexa', table[:copyright][1])
32
+ assert_equal(0, table[:copyright][1].platform_id)
33
+ assert_equal(3, table[:copyright][1].encoding_id)
34
+ assert_equal(1, table[:copyright][1].language_id)
35
+ assert_equal('hexapdf', table[:font_family][0])
36
+ assert_equal(0, table[:font_family][0].platform_id)
37
+ assert_equal(3, table[:font_family][0].encoding_id)
38
+ assert_equal(2, table[:font_family][0].language_id)
39
+ assert_equal(table[:copyright][0], table[:copyright].preferred_record)
40
+ end
41
+
42
+ it "reads the data in format 1 from the associated file" do
43
+ @file.io.string[0, 6] = [1, 3, 52].pack('n3')
44
+ @file.io.string[42, 0] = [2, 4, 26, 4, 30].pack('n*')
45
+ @file.io.string << 'ende'.encode('UTF-16BE').b
46
+ table = HexaPDF::Font::TrueType::Table::Name.new(@file, @entry)
47
+ assert_equal(1, table.format)
48
+ assert_equal({0x8000 => 'en', 0x8001 => 'de'}, table.language_tags)
49
+ end
50
+
51
+ it "loads some default values if no entry is given" do
52
+ table = HexaPDF::Font::TrueType::Table::Name.new(@file)
53
+ assert_equal(0, table.format)
54
+ assert_equal({}, table.records)
55
+ assert_equal({}, table.language_tags)
56
+ end
57
+ end
58
+
59
+ describe "add" do
60
+ it "adds a new record for a name" do
61
+ table = HexaPDF::Font::TrueType::Table::Name.new(@file)
62
+ table.add(:postscript_name, "test")
63
+ record = table[:postscript_name][0]
64
+ assert_equal("test", record)
65
+ assert_equal(HexaPDF::Font::TrueType::Table::Name::Record::PLATFORM_MACINTOSH, record.platform_id)
66
+ assert_equal(0, record.encoding_id)
67
+ assert_equal(0, record.language_id)
68
+ end
69
+ end
70
+
71
+ describe "NameRecord" do
72
+ before do
73
+ @table = HexaPDF::Font::TrueType::Table::Name.new(@file, @entry)
74
+ end
75
+
76
+ describe "platform?" do
77
+ it "returns the correct value" do
78
+ assert(@table[:copyright][0].platform?(:macintosh))
79
+ assert(@table[:copyright][1].platform?(:unicode))
80
+ refute(@table[:copyright][0].platform?(:microsoft))
81
+ end
82
+
83
+ it "raises an error when called with an unknown identifier" do
84
+ assert_raises(ArgumentError) { @table[:copyright][0].platform?(:testing) }
85
+ end
86
+ end
87
+
88
+ describe "preferred?" do
89
+ it "returns true for names in US English that had been converted to UTF-8" do
90
+ assert(@table[:copyright][0].preferred?)
91
+ refute(@table[:copyright][1].preferred?)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,65 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/table/os2'
6
+
7
+ describe HexaPDF::Font::TrueType::Table::OS2 do
8
+ before do
9
+ data = [5, -1, 2, 3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15,
10
+ 'PANOSPANOS', 16, 17, 'VEND', 16, 17, 18, -19, -20, -21, 22, 23, 24, -25, -26,
11
+ 27, 28, 29, 30, 31].pack('ns>n2s>12a10Q>2a4n3s>3n2Q>s>2n5')
12
+ @file = Object.new
13
+ @file.define_singleton_method(:io) { @io ||= StringIO.new(data) }
14
+ @entry = HexaPDF::Font::TrueType::Table::Directory::Entry.new('OS/2', 0, 0, @file.io.length)
15
+ end
16
+
17
+ describe "initialize" do
18
+ it "reads the data from the associated file" do
19
+ table = HexaPDF::Font::TrueType::Table::OS2.new(@file, @entry)
20
+ assert_equal(5, table.version)
21
+ assert_equal(-1, table.x_avg_char_width)
22
+ assert_equal(200, table.weight_class)
23
+ assert_equal(3, table.width_class)
24
+ assert_equal(-4, table.type)
25
+ assert_equal(-5, table.subscript_x_size)
26
+ assert_equal(-6, table.subscript_y_size)
27
+ assert_equal(-7, table.subscript_x_offset)
28
+ assert_equal(-8, table.subscript_y_offset)
29
+ assert_equal(-9, table.superscript_x_size)
30
+ assert_equal(-10, table.superscript_y_size)
31
+ assert_equal(-11, table.superscript_x_offset)
32
+ assert_equal(-12, table.superscript_y_offset)
33
+ assert_equal(-13, table.strikeout_size)
34
+ assert_equal(-14, table.strikeout_position)
35
+ assert_equal(-15, table.family_class)
36
+ assert_equal('PANOSPANOS'.b, table.panose)
37
+ assert_equal(16 << 64 & 17, table.unicode_range)
38
+ assert_equal('VEND'.b, table.vendor_id)
39
+ assert_equal(16, table.selection)
40
+ assert_equal(17, table.first_char_index)
41
+ assert_equal(18, table.last_char_index)
42
+ assert_equal(-19, table.typo_ascender)
43
+ assert_equal(-20, table.typo_descender)
44
+ assert_equal(-21, table.typo_line_gap)
45
+ assert_equal(22, table.win_ascent)
46
+ assert_equal(23, table.win_descent)
47
+ assert_equal(24, table.code_page_range)
48
+ assert_equal(-25, table.x_height)
49
+ assert_equal(-26, table.cap_height)
50
+ assert_equal(27, table.default_char)
51
+ assert_equal(28, table.break_char)
52
+ assert_equal(29, table.max_context)
53
+ assert_equal(30, table.lower_point_size)
54
+ assert_equal(31, table.upper_point_size)
55
+ end
56
+
57
+ it "loads some default values if no entry is given" do
58
+ table = HexaPDF::Font::TrueType::Table::OS2.new(@file)
59
+ assert_equal(5, table.version)
60
+ assert_equal(''.b, table.panose)
61
+ assert_equal(' '.b, table.vendor_id)
62
+ assert_equal(0, table.default_char)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,89 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/table/post'
6
+
7
+ describe HexaPDF::Font::TrueType::Table::Post do
8
+ before do
9
+ data = [1, 0, 1, 0, -142, 15, 0, 0, 0, 0, 0].pack('n4s>2N5')
10
+ @file = Object.new
11
+ @file.define_singleton_method(:io) { @io ||= StringIO.new(data) }
12
+ @entry = HexaPDF::Font::TrueType::Table::Directory::Entry.new('post', 0, 0, @file.io.length)
13
+ end
14
+
15
+ describe "initialize" do
16
+ it "reads the format 1 data from the associated file" do
17
+ table = HexaPDF::Font::TrueType::Table::Post.new(@file, @entry)
18
+ assert_equal(1, table.format)
19
+ assert_equal(1, table.italic_angle)
20
+ assert_equal(-142, table.underline_position)
21
+ assert_equal(15, table.underline_thickness)
22
+ assert_equal(0, table.is_fixed_pitch)
23
+ refute(table.is_fixed_pitch?)
24
+ assert_equal(0, table.min_mem_type42)
25
+ assert_equal(0, table.max_mem_type42)
26
+ assert_equal(0, table.min_mem_type1)
27
+ assert_equal(0, table.max_mem_type1)
28
+ assert_equal('.notdef', table[0])
29
+ assert_equal('A', table[36])
30
+ assert_equal('Delta', table[168])
31
+ assert_equal('.notdef', table[1000])
32
+ end
33
+
34
+ it "reads the format 2 data from the associated file" do
35
+ @file.io.string[0, 2] = [2].pack('n')
36
+ @file.io.string << ([260, 0] + (1..257).to_a.reverse + [258, 259]).pack('n*')
37
+ @file.io.string << [4, "hexa", 3, "pdf"].pack('CA4CA3')
38
+ @entry.length = @file.io.length
39
+ table = HexaPDF::Font::TrueType::Table::Post.new(@file, @entry)
40
+ assert_equal(2, table.format)
41
+ assert_equal('.notdef', table[0])
42
+ assert_equal('A', table[258 - 36])
43
+ assert_equal('Delta', table[258 - 168])
44
+ assert_equal('hexa', table[258])
45
+ assert_equal('pdf', table[259])
46
+ assert_equal('.notdef', table[1000])
47
+ end
48
+
49
+ it "reads the format 3 data from the associated file" do
50
+ @file.io.string[0, 2] = [3].pack('n')
51
+ table = HexaPDF::Font::TrueType::Table::Post.new(@file, @entry)
52
+ assert_equal(3, table.format)
53
+ assert_equal('.notdef', table[0])
54
+ assert_equal('.notdef', table[36])
55
+ assert_equal('.notdef', table[1000])
56
+ end
57
+
58
+ it "reads the format 4 data from the associated file" do
59
+ @file.io.string[0, 2] = [4].pack('n')
60
+ @file.io.string << [0x1234, 0x5678].pack('n*')
61
+ @entry.length = @file.io.length
62
+ table = HexaPDF::Font::TrueType::Table::Post.new(@file, @entry)
63
+ assert_equal(4, table.format)
64
+ assert_equal(0x1234, table[0])
65
+ assert_equal(0x5678, table[1])
66
+ assert_equal(0xFFFF, table[2])
67
+ assert_equal(0xFFFF, table[36])
68
+ assert_equal(0xFFFF, table[1_000_000])
69
+ end
70
+
71
+ it "loads some default values if no entry is given" do
72
+ table = HexaPDF::Font::TrueType::Table::Post.new(@file)
73
+ assert_equal(1, table.format)
74
+ assert_equal(0, table.italic_angle)
75
+ assert_equal(0, table.underline_position)
76
+ assert_equal(0, table.underline_thickness)
77
+ assert_equal(0, table.is_fixed_pitch)
78
+ assert_equal(0, table.min_mem_type42)
79
+ assert_equal(0, table.max_mem_type42)
80
+ assert_equal(0, table.min_mem_type1)
81
+ assert_equal(0, table.max_mem_type1)
82
+ end
83
+
84
+ it "raises an error if an unsupported format is given" do
85
+ @file.io.string[0, 2] = [5].pack('n')
86
+ assert_raises(HexaPDF::Error) { HexaPDF::Font::TrueType::Table::Post.new(@file, @entry) }
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,120 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/font'
6
+ require_relative 'common'
7
+
8
+ describe HexaPDF::Font::TrueType::Font do
9
+ before do
10
+ @io = StringIO.new("TEST\x00\x01\x00\x00\x00\x00\x00\x00" \
11
+ "TEST----\x00\x00\x00\x1C\x00\x00\x00\x05ENTRY".b)
12
+ @font = HexaPDF::Font::TrueType::Font.new(io: @io)
13
+ @font.config['font.true_type.table_mapping'][:TEST] = TestHelper::TrueTypeTestTable.name
14
+ end
15
+
16
+ describe "[]" do
17
+ it "returns a named table" do
18
+ table = @font[:TEST]
19
+ assert_equal('ENTRY', table.data)
20
+ end
21
+
22
+ it "always returns the same table instance" do
23
+ assert_same(@font[:TEST], @font[:TEST])
24
+ end
25
+
26
+ it "returns a generic table if no mapping exists" do
27
+ @font.config['font.true_type.table_mapping'].delete(:TEST)
28
+ assert_kind_of(HexaPDF::Font::TrueType::Table, @font[:TEST])
29
+ end
30
+
31
+ it "returns nil if the named table doesn't exist in the file" do
32
+ assert_nil(@font[:OTHE])
33
+ end
34
+ end
35
+
36
+ describe "add_table" do
37
+ it "returns the existing table if one exists" do
38
+ assert_same(@font[:TEST], @font.add_table(:TEST))
39
+ end
40
+
41
+ it "creates a new table instance if needed" do
42
+ assert_kind_of(HexaPDF::Font::TrueType::Table::Head, @font.add_table(:head))
43
+ end
44
+ end
45
+
46
+ describe "getter methods" do
47
+ before do
48
+ @font.add_table(:name)
49
+ @font.add_table(:post)
50
+ @font.add_table(:head)
51
+ @font.add_table(:hhea)
52
+ @font.add_table(:"OS/2")
53
+ end
54
+
55
+ it "returns the postscript name" do
56
+ @font[:name].add(:postscript_name, "name")
57
+ assert_equal("name", @font.font_name)
58
+ end
59
+
60
+ it "returns the full name" do
61
+ @font[:name].add(:font_name, "name")
62
+ assert_equal("name", @font.full_name)
63
+ end
64
+
65
+ it "returns the family name" do
66
+ @font[:name].add(:font_family, "name")
67
+ assert_equal("name", @font.family_name)
68
+ end
69
+
70
+ it "returns the font's weight" do
71
+ @font[:"OS/2"].weight_class = 400
72
+ assert_equal(400, @font.weight)
73
+ end
74
+
75
+ it "returns the font's bounding box" do
76
+ @font[:head].bbox = [0, 1, 2, 3]
77
+ assert_equal([0, 1, 2, 3], @font.bounding_box)
78
+ end
79
+
80
+ it "returns the font's cap height" do
81
+ @font[:"OS/2"].cap_height = 832
82
+ assert_equal(832, @font.cap_height)
83
+ end
84
+
85
+ it "returns the font's x height" do
86
+ @font[:"OS/2"].x_height = 642
87
+ assert_equal(642, @font.x_height)
88
+ end
89
+
90
+ it "returns the font's ascender" do
91
+ @font[:"OS/2"].typo_ascender = 800
92
+ @font[:hhea].ascent = 790
93
+ assert_equal(800, @font.ascender)
94
+ @font.instance_eval { @tables.delete(:"OS/2") }
95
+ assert_equal(790, @font.ascender)
96
+ end
97
+
98
+ it "returns the font's descender" do
99
+ @font[:"OS/2"].typo_descender = -200
100
+ @font[:hhea].descent = -180
101
+ assert_equal(-200, @font.descender)
102
+ @font.instance_eval { @tables.delete(:"OS/2") }
103
+ assert_equal(-180, @font.descender)
104
+ end
105
+
106
+ it "returns the font's italic angle" do
107
+ @font[:post].italic_angle = Rational(325, 10)
108
+ assert_equal(32.5, @font.italic_angle)
109
+ end
110
+
111
+ it "returns the font's dominant vertical stem width" do
112
+ @font[:"OS/2"].weight_class = 400
113
+ assert_equal(80, @font.dominant_vertical_stem_width)
114
+ end
115
+ end
116
+
117
+ it "is able to return the ID of the missing glyph" do
118
+ assert_equal(0, @font.missing_glyph_id)
119
+ end
120
+ end
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'hexapdf/font/true_type/table'
6
+ require_relative 'common'
7
+
8
+ describe HexaPDF::Font::TrueType::Table do
9
+ before do
10
+ io = StringIO.new('some string')
11
+ @file = Object.new
12
+ @file.define_singleton_method(:io) { io }
13
+ @entry = HexaPDF::Font::TrueType::Table::Directory::Entry.new('tagg', 0, 0, @file.io.string.length)
14
+ end
15
+
16
+ describe "initialize" do
17
+ it "reads the data from the associated file" do
18
+ table = TestHelper::TrueTypeTestTable.new(@file, @entry)
19
+ assert_equal(@file.io.string, table.data)
20
+ end
21
+
22
+ it "loads some default values if no entry is given" do
23
+ table = TestHelper::TrueTypeTestTable.new(@file)
24
+ assert_equal('default', table.data)
25
+ end
26
+ end
27
+
28
+ describe "checksum_valid?" do
29
+ it "checks whether an entry's checksum is valid" do
30
+ @file.io.string = 254.chr * 17 + 0.chr * 3
31
+ @entry.checksum = (0xfefefefe * 4 + 0xfe000000) % 2**32
32
+ @entry.length = @file.io.string.length
33
+ table = TestHelper::TrueTypeTestTable.new(@file, @entry)
34
+ assert(table.checksum_valid?)
35
+ end
36
+
37
+ it "raises an error if the checksum can't be verified because none is available" do
38
+ assert_raises(HexaPDF::Error) { TestHelper::TrueTypeTestTable.new(@file).checksum_valid? }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,51 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/font/type1'
5
+ require 'hexapdf/data_dir'
6
+ require 'tempfile'
7
+ require 'stringio'
8
+
9
+ describe HexaPDF::Font::Type1::AFMParser do
10
+ describe "::parse" do
11
+ before do
12
+ @file = Tempfile.new('hexapdf-afm')
13
+ @file.write("StartFontMetrics 4.1\nFontName Test\nEndFontMetrics\n")
14
+ @file.close
15
+ end
16
+
17
+ after do
18
+ @file.unlink
19
+ end
20
+
21
+ it "can work with file names" do
22
+ assert_equal('Test', HexaPDF::Font::Type1::AFMParser.parse(@file.path).font_name)
23
+ end
24
+
25
+ it "can work with IO streams" do
26
+ @file.open
27
+ assert_equal('Test', HexaPDF::Font::Type1::AFMParser.parse(@file).font_name)
28
+ end
29
+ end
30
+
31
+ it "can parse the 14 core PDF font files" do
32
+ Dir[File.join(HexaPDF.data_dir, 'afm', '*.afm')].each do |file|
33
+ metrics = HexaPDF::Font::Type1::AFMParser.parse(file)
34
+ basename = File.basename(file, '.*')
35
+ assert_equal(basename, metrics.font_name, basename)
36
+ assert_equal(basename.sub(/-.*/, ''), metrics.family_name, basename)
37
+ assert(metrics.character_metrics.size > 0, basename)
38
+ end
39
+ end
40
+
41
+ it "calculates an ascender and descender value from the font bounding box if necessary" do
42
+ metrics = HexaPDF::Font::Type1::AFMParser.parse(File.join(HexaPDF.data_dir, 'afm/Symbol.afm'))
43
+ assert_equal(metrics.bounding_box[1], metrics.descender)
44
+ assert_equal(metrics.bounding_box[3], metrics.ascender)
45
+ end
46
+
47
+ it "fails if the file doesn't start with the correct line" do
48
+ file = StringIO.new("some\nthing")
49
+ assert_raises(HexaPDF::Error) { HexaPDF::Font::Type1::AFMParser.parse(file) }
50
+ end
51
+ end
@@ -0,0 +1,68 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/font/type1'
5
+
6
+ describe HexaPDF::Font::Type1::Font do
7
+ before do
8
+ metrics = HexaPDF::Font::Type1::FontMetrics.new
9
+ @font = HexaPDF::Font::Type1::Font.new(metrics)
10
+ end
11
+
12
+ describe "::from_afm" do
13
+ it "can load the Font object from an AFM file" do
14
+ font = HexaPDF::Font::Type1::Font.from_afm(File.join(HexaPDF.data_dir, 'afm/Symbol.afm'))
15
+ assert_equal('Symbol', font.family_name)
16
+ end
17
+ end
18
+
19
+ describe "encoding" do
20
+ it "uses the StandardEncoding if possible" do
21
+ @font.metrics.encoding_scheme = 'AdobeStandardEncoding'
22
+ assert_equal(HexaPDF::Font::Encoding.for_name(:StandardEncoding), @font.encoding)
23
+ end
24
+
25
+ it "handles the special case of the ZapfDingbats font" do
26
+ @font.metrics.font_name = "ZapfDingbats"
27
+ assert_equal(HexaPDF::Font::Encoding.for_name(:ZapfDingbatsEncoding), @font.encoding)
28
+ end
29
+
30
+ it "handles the special case of the Symbol font" do
31
+ @font.metrics.font_name = "Symbol"
32
+ assert_equal(HexaPDF::Font::Encoding.for_name(:SymbolEncoding), @font.encoding)
33
+ end
34
+
35
+ it "generates an encoding object if necessary" do
36
+ char_metrics = HexaPDF::Font::Type1::CharacterMetrics.new
37
+ char_metrics.code = 5
38
+ char_metrics.name = :A
39
+ @font.metrics.character_metrics[5] = char_metrics.dup
40
+ char_metrics.code = 6
41
+ char_metrics.name = :Z
42
+ @font.metrics.character_metrics[6] = char_metrics.dup
43
+
44
+ assert_equal({5 => :A, 6 => :Z}, @font.encoding.code_to_name)
45
+ end
46
+ end
47
+
48
+ describe "width" do
49
+ before do
50
+ @char_metrics = HexaPDF::Font::Type1::CharacterMetrics.new
51
+ @char_metrics.width = 100
52
+ end
53
+
54
+ it "returns the width for a code point in the built-in encoding" do
55
+ @font.metrics.character_metrics[5] = @char_metrics
56
+ assert_equal(100, @font.width(5))
57
+ end
58
+
59
+ it "returns the width for a named glyph" do
60
+ @font.metrics.character_metrics[:A] = @char_metrics
61
+ assert_equal(100, @font.width(:A))
62
+ end
63
+ end
64
+
65
+ it "is able to return the ID of the missing glyph" do
66
+ assert_equal(:'.notdef', @font.missing_glyph_id)
67
+ end
68
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/font/type1'
5
+
6
+ describe HexaPDF::Font::Type1::PFBParser do
7
+ describe "::encoding" do
8
+ it "can extract the encoding specified as StandardEncoding" do
9
+ data = "bla bla bla /Encoding StandardEncoding def bla bla"
10
+ assert_same(HexaPDF::Font::Encoding.for_name(:StandardEncoding),
11
+ HexaPDF::Font::Type1::PFBParser.encoding(data))
12
+ end
13
+
14
+ it "can extract the encoding specified as array" do
15
+ data = <<-EOF
16
+ bla bla bla
17
+ /Encoding 256 array
18
+ 0 1 255 {1 index exch /.notdef put} for
19
+ dup 32 /space put
20
+ dup 33 /exclam put
21
+ dup 34 /universal put
22
+ dup 35 /numbersign put
23
+ dup 36 /existential put
24
+ readonly def
25
+ bla bla bla
26
+ EOF
27
+ enc = HexaPDF::Font::Type1::PFBParser.encoding(data)
28
+ assert_equal(:space, enc.name(32))
29
+ assert_equal(:existential, enc.name(36))
30
+ end
31
+
32
+ it "fails if the encoding can't be extracted" do
33
+ data = "something without an encoding"
34
+ assert_raises(HexaPDF::Error) { HexaPDF::Font::Type1::PFBParser.encoding(data) }
35
+ end
36
+ end
37
+ end