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,92 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2016 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #++
33
+
34
+ require 'hexapdf/font/true_type/table'
35
+
36
+ module HexaPDF
37
+ module Font
38
+ module TrueType
39
+ class Table
40
+
41
+ # The main table of an sfnt-housed font file, providing the table directory which contains
42
+ # information for loading all other tables.
43
+ #
44
+ # See: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html
45
+ class Directory < Table
46
+
47
+ # A single entry in the table directory.
48
+ #
49
+ # Accessors:
50
+ #
51
+ # tag:: The 4 byte name of the table as binary string.
52
+ # checksum:: Checksum of the table.
53
+ # offset:: Offset from the beginning of the file where the table can be found.
54
+ # length:: The length of the table in bytes (without the padding).
55
+ Entry = Struct.new(:tag, :checksum, :offset, :length)
56
+
57
+ # The fixed entry that represents the table directory itself.
58
+ SELF_ENTRY = Entry.new('DUMMY', 0, 0, 12)
59
+
60
+ # The type of file housed by the snft wrapper as a binary string. Two possible values are
61
+ # 'true' or 0x00010000 for a TrueType font and 'OTTO' for an OpenType font.
62
+ attr_reader :tag
63
+
64
+ # Returns the directory entry for the given tag or +nil+ if no such table exists.
65
+ def entry(tag)
66
+ @tables[tag]
67
+ end
68
+
69
+ private
70
+
71
+ def load_from_io #:nodoc:
72
+ with_io_pos(0) do
73
+ @tag, num_tables = read_formatted(12, "a4n".freeze) # ignore 3 fields
74
+ @tables = {}
75
+ num_tables.times do
76
+ entry = Entry.new(*read_formatted(16, "a4NNN".freeze))
77
+ @tables[entry.tag] = entry
78
+ end
79
+ end
80
+ end
81
+
82
+ def load_default #:nodoc:
83
+ @tag = 'true'.b
84
+ @tables = {}
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,166 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2016 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #++
33
+
34
+ require 'hexapdf/font/true_type/table'
35
+
36
+ module HexaPDF
37
+ module Font
38
+ module TrueType
39
+ class Table
40
+
41
+ # The 'glyf' table contains the instructions for rendering glyphs and some additional glyph
42
+ # information.
43
+ #
44
+ # This is probably always the largest table in a TrueType font, so care is taken to perform
45
+ # operations lazily.
46
+ #
47
+ # See: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html
48
+ class Glyf < Table
49
+
50
+ # Represents the definition of a glyph. Since the purpose of this implementation is not
51
+ # editing or rendering glyphs, the raw glyph data is only decoded so far as to get general
52
+ # information about the glyph.
53
+ class Glyph
54
+
55
+ # Contains the raw byte data of the glyph.
56
+ attr_reader :raw_data
57
+
58
+ # The number of contours in the glyph. A zero or positive number implies a simple glyph,
59
+ # a negative number a glyph made up from multiple components
60
+ attr_reader :number_of_contours
61
+
62
+ # The minimum x value for coordinate data.
63
+ attr_reader :x_min
64
+
65
+ # The minimum y value for coordinate data.
66
+ attr_reader :y_min
67
+
68
+ # The maximum x value for coordinate data.
69
+ attr_reader :x_max
70
+
71
+ # The maximum y value for coordinate data.
72
+ attr_reader :y_max
73
+
74
+ # The array with the component glyph IDs, or +nil+ if this is not a compound glyph.
75
+ attr_reader :components
76
+
77
+ # Creates a new glyph from the given raw data.
78
+ def initialize(raw_data)
79
+ @raw_data = raw_data
80
+ @number_of_contours, @x_min, @y_min, @x_max, @y_max = @raw_data.unpack('s>5')
81
+ @number_of_contours ||= 0
82
+ @components = nil
83
+ parse_compound_glyph if compound?
84
+ end
85
+
86
+ # Returns +true+ if this a compound glyph.
87
+ def compound?
88
+ number_of_contours < 0
89
+ end
90
+
91
+ private
92
+
93
+ FLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0 #:nodoc:
94
+ FLAG_MORE_COMPONENTS = 1 << 5 #:nodoc:
95
+ FLAG_WE_HAVE_A_SCALE = 1 << 3 #:nodoc:
96
+ FLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6 #:nodoc:
97
+ FLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7 #:nodoc:
98
+
99
+ # Parses the raw data to get the component glyphs.
100
+ #
101
+ # This is needed because the component glyphs are referenced by their glyph IDs and
102
+ # those may change when subsetting the font.
103
+ def parse_compound_glyph
104
+ @components = []
105
+ @component_offsets = []
106
+ index = 10
107
+ while true
108
+ flags, glyph_id = raw_data[index, 4].unpack('n2')
109
+ @components << glyph_id
110
+ @component_offsets << index
111
+ break if flags & FLAG_MORE_COMPONENTS == 0
112
+
113
+ index += 4 # fields flags and glyphIndex
114
+ index += (flags & FLAG_ARG_1_AND_2_ARE_WORDS == 0 ? 2 : 4) # arguments
115
+ if flags & FLAG_WE_HAVE_A_TWO_BY_TWO != 0 # transformation
116
+ index += 8
117
+ elsif flags & FLAG_WE_HAVE_AN_X_AND_Y_SCALE != 0
118
+ index += 4
119
+ elsif flags & FLAG_WE_HAVE_A_SCALE != 0
120
+ index += 2
121
+ end
122
+ end
123
+ end
124
+
125
+ end
126
+
127
+ # The mapping from glyph ID to Glyph object or +nil+ (if the glyph has no outline).
128
+ attr_accessor :glyphs
129
+
130
+ # Returns the Glyph object for the given glyph ID, or +nil+ if it has no outline (e.g. the
131
+ # space character).
132
+ def [](glyph_id)
133
+ if @glyphs.key?(glyph_id)
134
+ return @glyphs[glyph_id]
135
+ elsif !directory_entry
136
+ return nil
137
+ end
138
+
139
+ offset = font[:loca].offset(glyph_id)
140
+ length = font[:loca].length(glyph_id)
141
+
142
+ if length == 0
143
+ @glyphs[glyph_id] = Glyph.new('')
144
+ else
145
+ raw_data = with_io_pos(directory_entry.offset + offset) { io.read(length) }
146
+ @glyphs[glyph_id] = Glyph.new(raw_data)
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ # Nothing to parse here since we lazily parse glyphs.
153
+ def parse_table
154
+ @glyphs = {}
155
+ end
156
+
157
+ def load_default #:nodoc:
158
+ @glyphs = {}
159
+ end
160
+
161
+ end
162
+
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,143 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2016 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #++
33
+
34
+ require 'hexapdf/font/true_type/table'
35
+ require 'hexapdf/utils/bit_field'
36
+
37
+ module HexaPDF
38
+ module Font
39
+ module TrueType
40
+ class Table
41
+
42
+ # The 'head' table contains global information about the font.
43
+ #
44
+ # See: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6head.html
45
+ class Head < Table
46
+ extend HexaPDF::Utils::BitField
47
+
48
+ # The version of the font (a Rational).
49
+ attr_accessor :version
50
+
51
+ # The revision of the font as set by the manufacturer (a Rational).
52
+ attr_accessor :font_revision
53
+
54
+ # The adjustment value for the checksum.
55
+ attr_accessor :checksum_adjustment
56
+
57
+ # Various font flags. See Flags.
58
+ attr_accessor :flags
59
+
60
+ # The number of units per em for the font. Should be a power of 2 in the range from 64
61
+ # through 16384.
62
+ attr_accessor :units_per_em
63
+
64
+ # The creation time of the font.
65
+ attr_accessor :created
66
+
67
+ # The modification time of the font.
68
+ attr_accessor :modified
69
+
70
+ # The bounding box for all glyphs of the font in the form [xmin, ymin, xmax, ymax].
71
+ attr_accessor :bbox
72
+
73
+ # Apple Mac style information.
74
+ attr_accessor :mac_style
75
+ bit_field(:mac_style, bold: 0, italic: 1, underline: 2, outline: 3, shadow: 4,
76
+ condensed: 5, extended: 6)
77
+
78
+ # The smallest readable size in pixels per em for this font.
79
+ attr_accessor :smallest_readable_size
80
+
81
+ # Represents an indication of the direction of the glyphs of the font.
82
+ #
83
+ # 0:: Mixed directional font
84
+ # 1:: Font with only left-to-right glyphs
85
+ # -1:: Font with only right-to-left glyphs
86
+ # 2:: Font with left-to-right and neutral (e.g. punctuation) glyphs
87
+ # -2:: Font with right-to-left and neutral (e.g. punctuation) glyphs
88
+ attr_accessor :font_direction_hint
89
+
90
+ # Indicates the type of offset format used in the 'loca' table, 0 for short offsets, 1 for
91
+ # long offsets.
92
+ #
93
+ # See: Loca
94
+ attr_accessor :index_to_loc_format
95
+
96
+ # The checksum for the head table is calculated differently because the
97
+ # checksum_adjustment value is not used during the calculation.
98
+ #
99
+ # See: Table#checksum_valid?
100
+ def checksum_valid?
101
+ super unless directory_entry
102
+
103
+ data = with_io_pos(directory_entry.offset) { io.read(directory_entry.length) }
104
+ data[8, 4] = 0.chr * 4
105
+ directory_entry.checksum == self.class.calculate_checksum(data)
106
+ end
107
+
108
+ private
109
+
110
+ def parse_table #:nodoc:
111
+ @version = read_fixed
112
+ @font_revision = read_fixed
113
+ data = read_formatted(46, 'N2n2q>2s>4n2s>3')
114
+ @checksum_adjustment = data[0]
115
+ if data[1] != 0x5F0F3CF5 # the magic number
116
+ raise HexaPDF::Error, "Invalid magic number in 'head' table: #{data[1].to_s(16)}"
117
+ end
118
+ @flags, @units_per_em = data[2], data[3]
119
+ @created, @modified = TIME_EPOCH + data[4], TIME_EPOCH + data[5]
120
+ @bbox = data[6..9]
121
+ @mac_style, @smallest_readable_size, @font_direction_hint, @index_to_loc_format =
122
+ *data[10..13]
123
+ if data[14] != 0 # glyphDataFormat
124
+ raise HexaPDF::Error, "Invalid glyph data format value (should be 0): #{data[14]}"
125
+ end
126
+ end
127
+
128
+ def load_default #:nodoc:
129
+ @version = 1.to_r
130
+ @font_revision = 1.to_r
131
+ @checksum_adjustment = @flags = @mac_style = @smallest_readable_size =
132
+ @font_direction_hint = @index_to_loc_format = 0
133
+ @units_per_em = 64
134
+ @created = @modified = Time.now
135
+ @bbox = [0, 0, 0, 0]
136
+ end
137
+
138
+ end
139
+
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,109 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2016 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #++
33
+
34
+ require 'hexapdf/font/true_type/table'
35
+
36
+ module HexaPDF
37
+ module Font
38
+ module TrueType
39
+ class Table
40
+
41
+ # The 'hhea' (horizontal header) table contains information for layouting fonts whose
42
+ # characters are written horizontally.
43
+ #
44
+ # See: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6hhea.html
45
+ class Hhea < Table
46
+
47
+ # The version of the table (a Rational).
48
+ attr_accessor :version
49
+
50
+ # The distance from the baseline of the highest ascender (as intended by the font
51
+ # designer).
52
+ attr_accessor :ascent
53
+
54
+ # The distance from the baseline of the lowest descender (as intended by the font
55
+ # designer).
56
+ attr_accessor :descent
57
+
58
+ # The typographic line gap (as intended by the font designer).
59
+ attr_accessor :line_gap
60
+
61
+ # The maxium advance width (computed value).
62
+ attr_accessor :advance_width_max
63
+
64
+ # The minimum left side bearing (computed value).
65
+ attr_accessor :min_left_side_bearing
66
+
67
+ # The minimum right side bearing (computed value).
68
+ attr_accessor :min_right_side_bearing
69
+
70
+ # The maximum horizontal glyph extent.
71
+ attr_accessor :x_max_extent
72
+
73
+ # Defines together with #caret_slope_run the mathematical slope of the angle for the
74
+ # caret.
75
+ #
76
+ # The slope is actually the ratio caret_slope_rise/caret_slope_run
77
+ attr_accessor :caret_slope_rise
78
+
79
+ # See #caret_slope_rise.
80
+ attr_accessor :caret_slope_run
81
+
82
+ # The amount by which a slanted highlight on a glyph needs (0 for non-slanted fonts).
83
+ attr_accessor :caret_offset
84
+
85
+ # The number of horizontal metrics defined in the 'hmtx' table.
86
+ attr_accessor :num_of_long_hor_metrics
87
+
88
+ private
89
+
90
+ def parse_table #:nodoc:
91
+ @version = read_fixed
92
+ @ascent, @descent, @line_gap, @advance_width_max, @min_left_side_bearing,
93
+ @min_right_side_bearing, @x_max_extent, @caret_slope_rise, @caret_slope_run,
94
+ @caret_offset, @num_of_long_hor_metrics = read_formatted(32, 's>3ns>6x10n')
95
+ end
96
+
97
+ def load_default #:nodoc:
98
+ @version = 1.to_r
99
+ @ascent = @descent = @line_gap = @advance_width_max = @min_left_side_bearing =
100
+ @min_right_side_bearing = @x_max_extent = @caret_slope_rise = @caret_slope_run =
101
+ @caret_offset = @num_of_long_hor_metrics = 0
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,79 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2016 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #++
33
+
34
+ require 'hexapdf/font/true_type/table'
35
+
36
+ module HexaPDF
37
+ module Font
38
+ module TrueType
39
+ class Table
40
+
41
+ # The 'hmtx' (horizontal metrics) table contains information for the horizontal layout
42
+ # of each glyph in the font.
43
+ #
44
+ # See: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6hmtx.html
45
+ class Hmtx < Table
46
+
47
+ # Contains the horizontal layout information for one glyph, namely the :advance_width and
48
+ # the :left_side_bearing.
49
+ Metric = Struct.new(:advance_width, :left_side_bearing)
50
+
51
+ # An array of Metric objects, one for each glyph in the font.
52
+ attr_accessor :horizontal_metrics
53
+
54
+ # Returns the Metric object for the give glyph ID.
55
+ def [](glyph_id)
56
+ @horizontal_metrics[glyph_id]
57
+ end
58
+
59
+ private
60
+
61
+ def parse_table #:nodoc:
62
+ nr_entries = font[:hhea].num_of_long_hor_metrics
63
+ @horizontal_metrics = nr_entries.times.map { Metric.new(*read_formatted(4, 'ns>')) }
64
+ last_advance_width = @horizontal_metrics[-1].advance_width
65
+ read_formatted(directory_entry.length - 4 * nr_entries, 's>*').map do |lsb|
66
+ @horizontal_metrics << Metric.new(last_advance_width, lsb)
67
+ end
68
+ end
69
+
70
+ def load_default #:nodoc:
71
+ @horizontal_metrics = []
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,79 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ #--
4
+ # This file is part of HexaPDF.
5
+ #
6
+ # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
+ # Copyright (C) 2016 Thomas Leitner
8
+ #
9
+ # HexaPDF is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU Affero General Public License version 3 as
11
+ # published by the Free Software Foundation with the addition of the
12
+ # following permission added to Section 15 as permitted in Section 7(a):
13
+ # FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
14
+ # THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
15
+ # INFRINGEMENT OF THIRD PARTY RIGHTS.
16
+ #
17
+ # HexaPDF is distributed in the hope that it will be useful, but WITHOUT
18
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
20
+ # License for more details.
21
+ #
22
+ # You should have received a copy of the GNU Affero General Public License
23
+ # along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
24
+ #
25
+ # The interactive user interfaces in modified source and object code
26
+ # versions of HexaPDF must display Appropriate Legal Notices, as required
27
+ # under Section 5 of the GNU Affero General Public License version 3.
28
+ #
29
+ # In accordance with Section 7(b) of the GNU Affero General Public
30
+ # License, a covered work must retain the producer line in every PDF that
31
+ # is created or manipulated using HexaPDF.
32
+ #++
33
+
34
+ require 'hexapdf/font/true_type/table'
35
+
36
+ module HexaPDF
37
+ module Font
38
+ module TrueType
39
+ class Table
40
+
41
+ # The 'loca' (location) table contains the offsets of the glyphs relative to the start of
42
+ # the 'glyf' table.
43
+ #
44
+ # See: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6loca.html
45
+ class Loca < Table
46
+
47
+ # The array containing the byte offsets for each glyph relative to the start of the 'glyf'
48
+ # table.
49
+ attr_accessor :offsets
50
+
51
+ # Returns the byte offset for the given glyph ID relative to the start of the 'glyf'
52
+ # table.
53
+ def offset(glyph_id)
54
+ @offsets[glyph_id]
55
+ end
56
+
57
+ # Returns the length of the 'glyf' entry for the given glyph ID.
58
+ def length(glyph_id)
59
+ @offsets[glyph_id + 1] - @offsets[glyph_id]
60
+ end
61
+
62
+ private
63
+
64
+ def parse_table #:nodoc:
65
+ entry_size = font[:head].index_to_loc_format
66
+ @offsets = read_formatted(directory_entry.length, (entry_size == 0 ? 'n*' : 'N*'))
67
+ @offsets.map! {|offset| offset * 2} if entry_size == 0
68
+ end
69
+
70
+ def load_default #:nodoc:
71
+ @offsets = []
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end