hexapdf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,579 @@
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/error'
35
+ require 'hexapdf/configuration'
36
+ require 'hexapdf/content/color_space'
37
+ require 'hexapdf/content/transformation_matrix'
38
+
39
+ module HexaPDF
40
+ module Content
41
+
42
+ # Associates a name with a value, used by various graphics state parameters.
43
+ class NamedValue
44
+
45
+ # The value itself.
46
+ attr_reader :value
47
+
48
+ # The name for the value.
49
+ attr_reader :name
50
+
51
+ # Creates a new NamedValue object and freezes it.
52
+ def initialize(name, value)
53
+ @name = name
54
+ @value = value
55
+ freeze
56
+ end
57
+
58
+ # The object is equal to +other+ if either the name or the value is equal to +other+, or if
59
+ # the other object is a NamedValue object with the same name and value.
60
+ def ==(other)
61
+ @name == other || @value == other ||
62
+ (other.kind_of?(NamedValue) && @name == other.name && @value == other.value)
63
+ end
64
+
65
+ # Returns the value.
66
+ def to_operands
67
+ @value
68
+ end
69
+
70
+ end
71
+
72
+
73
+ # Defines all available line cap styles as constants. Each line cap style is an instance of
74
+ # NamedValue. For use with Content::GraphicsState#line_cap_style.
75
+ #
76
+ # See: PDF1.7 s8.4.3.3
77
+ module LineCapStyle
78
+
79
+ # Returns the argument normalized to a valid line cap style.
80
+ #
81
+ # * 0 or +:butt+ can be used for the BUTT_CAP style.
82
+ # * 1 or +:round+ can be used for the ROUND_CAP style.
83
+ # * 2 or +:projecting_square+ can be used for the PROJECTING_SQUARE_CAP style.
84
+ # * Otherwise an error is raised.
85
+ def self.normalize(style)
86
+ case style
87
+ when :butt, 0 then BUTT_CAP
88
+ when :round, 1 then ROUND_CAP
89
+ when :projecting_square, 2 then PROJECTING_SQUARE_CAP
90
+ else
91
+ raise ArgumentError, "Unknown line cap style: #{style}"
92
+ end
93
+ end
94
+
95
+ # Stroke is squared off at the endpoint of a path.
96
+ BUTT_CAP = NamedValue.new(:butt, 0)
97
+
98
+ # A semicircular arc is drawn at the endpoint of a path.
99
+ ROUND_CAP = NamedValue.new(:round, 1)
100
+
101
+ # The stroke continues half the line width beyond the endpoint of a path.
102
+ PROJECTING_SQUARE_CAP = NamedValue.new(:projecting_square, 2)
103
+
104
+ end
105
+
106
+
107
+ # Defines all available line join styles as constants. Each line join style is an instance of
108
+ # NamedValue. For use with Content::GraphicsState#line_join_style.
109
+ #
110
+ # See: PDF1.7 s8.4.3.4
111
+ module LineJoinStyle
112
+
113
+ # Returns the argument normalized to a valid line join style.
114
+ #
115
+ # * 0 or +:miter+ can be used for the MITER_JOIN style.
116
+ # * 1 or +:round+ can be used for the ROUND_JOIN style.
117
+ # * 2 or +:bevel+ can be used for the BEVEL_JOIN style.
118
+ # * Otherwise an error is raised.
119
+ def self.normalize(style)
120
+ case style
121
+ when :miter, 0 then MITER_JOIN
122
+ when :round, 1 then ROUND_JOIN
123
+ when :bevel, 2 then BEVEL_JOIN
124
+ else
125
+ raise ArgumentError, "Unknown line join style: #{style}"
126
+ end
127
+ end
128
+
129
+ # The outer lines of the two segments continue until the meet at an angle.
130
+ MITER_JOIN = NamedValue.new(:miter, 0)
131
+
132
+ # An arc of a circle is drawn around the point where the segments meet.
133
+ ROUND_JOIN = NamedValue.new(:round, 1)
134
+
135
+ # The two segments are finished with butt caps and the space between the ends is filled with
136
+ # a triangle.
137
+ BEVEL_JOIN = NamedValue.new(:bevel, 2)
138
+
139
+ end
140
+
141
+
142
+ # The line dash pattern defines how a line should be dashed. For use with
143
+ # Content::GraphicsState#line_dash_pattern.
144
+ #
145
+ # A dash pattern consists of two parts: the dash array and the dash phase. The dash array
146
+ # defines the length of alternating dashes and gaps (important: starting with dashes). And the
147
+ # dash phase defines the distance into the dash array at which to start.
148
+ #
149
+ # It is easier to show. Following are dash arrays and dash phases and how they would be
150
+ # interpreted:
151
+ #
152
+ # [] 0 No dash, one solid line
153
+ # [3] 0 3 unit dash, 3 unit gap, 3 unit dash, 3 unit gap, ...
154
+ # [3] 1 2 unit dash, 3 unit gap, 3 unit dash, 3 unit gap, ...
155
+ # [2 1] 0 2 unit dash, 1 unit gap, 2 unit dash, 1 unit gap, ...
156
+ # [3 5] 6 2 unit gap, 3 unit dash, 5 unit gap, 3 unit dash, ...
157
+ # [2 3] 6 1 unit dash, 3 unit gap, 2 unit dash, 3 unit gap, ...
158
+ #
159
+ # See: PDF1.7 s8.4.3.6
160
+ class LineDashPattern
161
+
162
+ # The dash array.
163
+ attr_reader :array
164
+
165
+ # The dash phase.
166
+ attr_reader :phase
167
+
168
+ # Inititalizes the line dash pattern with the given +array+ and +phase+.
169
+ #
170
+ # The argument +phase+ must be non-negative and the numbers in the +array+ must be
171
+ # non-negative and must not all be zero.
172
+ def initialize(array = [], phase = 0)
173
+ if phase < 0 || (!array.empty? &&
174
+ array.inject(0) {|m, n| m < 0 ? m : (n < 0 ? -1 : m + n)} <= 0)
175
+ raise ArgumentError, "Invalid line dash pattern: #{array.inspect} #{phase.inspect}"
176
+ end
177
+ @array = array.freeze
178
+ @phase = phase
179
+ end
180
+
181
+ # Returns +true+ if the other line dash pattern is the same as this one.
182
+ def ==(other)
183
+ other.kind_of?(self.class) && other.array == array && other.phase == phase
184
+ end
185
+
186
+ # Converts the LineDashPattern object to an array of operands for the associated PDF content
187
+ # operator.
188
+ def to_operands
189
+ [@array, @phase]
190
+ end
191
+
192
+ end
193
+
194
+
195
+ # Defines all available rendering intents as constants. For use with
196
+ # Content::GraphicsState#rendering_intent.
197
+ #
198
+ # See: PDF1.7 s8.6.5.8
199
+ module RenderingIntent
200
+
201
+ # Returns the argument normalized to a valid rendering intent.
202
+ #
203
+ # * If the argument is a valid symbol, it is just returned.
204
+ # * Otherwise an error is raised.
205
+ def self.normalize(intent)
206
+ case intent
207
+ when ABSOLUTE_COLORIMETRIC, RELATIVE_COLORIMETRIC, SATURATION, PERCEPTUAL
208
+ intent
209
+ else
210
+ raise ArgumentError, "Invalid rendering intent: #{intent}"
211
+ end
212
+ end
213
+
214
+ # Colors should be represented solely with respect to the light source.
215
+ ABSOLUTE_COLORIMETRIC = :AbsoluteColorimetric
216
+
217
+ # Colous should be represented with respect to the combination of the light source and the
218
+ # output medium's white point.
219
+ RELATIVE_COLORIMETRIC = :RelativeColorimetric
220
+
221
+ # Colors should be represented in a manner that preserves or emphasizes saturation.
222
+ SATURATION = :Saturation
223
+
224
+ # Colous should be represented in a manner that provides a pleasing perceptual appearance.
225
+ PERCEPTUAL = :Perceptual
226
+
227
+ end
228
+
229
+
230
+ # Defines all available text rendering modes as constants. Each text rendering mode is an
231
+ # instance of NamedValue. For use with Content::GraphicsState#text_rendering_mode.
232
+ #
233
+ # See: PDF1.7 s9.3.6
234
+ module TextRenderingMode
235
+
236
+ # Returns the argument normalized to a valid text rendering mode.
237
+ #
238
+ # * 0 or +:fill+ can be used for the FILL mode.
239
+ # * 1 or +:stroke+ can be used for the STROKE mode.
240
+ # * 2 or +:fill_stroke+ can be used for the FILL_STROKE mode.
241
+ # * 3 or +:invisible+ can be used for the INVISIBLE mode.
242
+ # * 4 or +:fill_clip+ can be used for the FILL_CLIP mode.
243
+ # * 5 or +:stroke_clip+ can be used for the STROKE_CLIP mode.
244
+ # * 6 or +:fill_stroke_clip+ can be used for the FILL_STROKE_CLIP mode.
245
+ # * 7 or +:clip+ can be used for the CLIP mode.
246
+ # * Otherwise an error is raised.
247
+ def self.normalize(style)
248
+ case style
249
+ when :fill, 0 then FILL
250
+ when :stroke, 1 then STROKE
251
+ when :fill_stroke, 2 then FILL_STROKE
252
+ when :invisible, 3 then INVISIBLE
253
+ when :fill_clip, 4 then FILL_CLIP
254
+ when :stroke_clip, 5 then STROKE_CLIP
255
+ when :fill_stroke_clip, 6 then FILL_STROKE_CLIP
256
+ when :clip, 7 then CLIP
257
+ else
258
+ raise ArgumentError, "Unknown text rendering mode: #{style}"
259
+ end
260
+ end
261
+
262
+ # Fill text
263
+ FILL = NamedValue.new(:fill, 0)
264
+
265
+ # Stroke text
266
+ STROKE = NamedValue.new(:stroke, 1)
267
+
268
+ # Fill, then stroke text
269
+ FILL_STROKE = NamedValue.new(:fill_stroke, 2)
270
+
271
+ # Neither fill nor stroke text (invisible)
272
+ INVISIBLE = NamedValue.new(:invisible, 3)
273
+
274
+ # Fill text and add to path for clipping
275
+ FILL_CLIP = NamedValue.new(:fill_clip, 4)
276
+
277
+ # Stroke text and add to path for clipping
278
+ STROKE_CLIP = NamedValue.new(:stroke_clip, 5)
279
+
280
+ # Fill, then stroke text and add to path for clipping
281
+ FILL_STROKE_CLIP = NamedValue.new(:fill_stroke_clip, 6)
282
+
283
+ # Add text to path for clipping
284
+ CLIP = NamedValue.new(:clip, 7)
285
+
286
+ end
287
+
288
+
289
+ # A GraphicsState object holds all the graphic control parameters needed for correct
290
+ # operation when parsing or creating a content stream with a Processor object.
291
+ #
292
+ # While a content stream is parsed/created, operations may use the current parameters or
293
+ # modify them.
294
+ #
295
+ # The device-dependent graphics state parameters have not been implemented!
296
+ #
297
+ # See: PDF1.7 s8.4.1
298
+ class GraphicsState
299
+
300
+ # The current transformation matrix.
301
+ attr_accessor :ctm
302
+
303
+ # The current color used for stroking operations during painting.
304
+ attr_accessor :stroke_color
305
+
306
+ # The current color used for all other (i.e. non-stroking) painting operations.
307
+ attr_accessor :fill_color
308
+
309
+ # The current line width in user space units.
310
+ attr_accessor :line_width
311
+
312
+ # The current line cap style (for the available values see LineCapStyle).
313
+ attr_accessor :line_cap_style
314
+
315
+ # The current line join style (for the available values see LineJoinStyle).
316
+ attr_accessor :line_join_style
317
+
318
+ # The maximum line length of mitered line joins for stroked paths.
319
+ attr_accessor :miter_limit
320
+
321
+ # The line dash pattern (see LineDashPattern).
322
+ attr_accessor :line_dash_pattern
323
+
324
+ # The rendering intent (only used for CIE-based colors; for the available values see
325
+ # RenderingIntent).
326
+ attr_accessor :rendering_intent
327
+
328
+ # The stroke adjustment for very small line width.
329
+ attr_accessor :stroke_adjustment
330
+
331
+ # The current blend mode for the transparent imaging model.
332
+ attr_accessor :blend_mode
333
+
334
+ # The soft mask specifying the mask shape or mask opacity value to be used in the
335
+ # transparent imaging model.
336
+ attr_accessor :soft_mask
337
+
338
+ # The alpha constant for stroking operations in the transparent imaging model.
339
+ attr_accessor :stroke_alpha
340
+
341
+ # The alpha constant for non-stroking operations in the transparent imaging model.
342
+ attr_accessor :fill_alpha
343
+
344
+ # A boolean specifying whether the current soft mask and alpha parameters should be
345
+ # interpreted as shape values or opacity values.
346
+ attr_accessor :alpha_source
347
+
348
+
349
+ # The text matrix.
350
+ #
351
+ # This attribute is non-nil only when inside a text object.
352
+ attr_accessor :tm
353
+
354
+ # The text line matrix which captures the state of the text matrix at the beginning of a line.
355
+ #
356
+ # As with the text matrix the text line matrix is non-nil only when inside a text object.
357
+ attr_accessor :tlm
358
+
359
+ # The character spacing in unscaled text units.
360
+ #
361
+ # It specifies the additional spacing used for the horizontal or vertical displacement of
362
+ # glyphs.
363
+ attr_reader :character_spacing
364
+
365
+ # The word spacing in unscaled text units.
366
+ #
367
+ # It works like the character spacing but is only applied to the ASCII space character.
368
+ attr_reader :word_spacing
369
+
370
+ # The horizontal text scaling.
371
+ #
372
+ # The value specifies the percentage of the normal width that should be used.
373
+ attr_reader :horizontal_scaling
374
+
375
+ # The leading in unscaled text units.
376
+ #
377
+ # It specifies the distance between the baselines of adjacent lines of text.
378
+ attr_accessor :leading
379
+
380
+ # The font for the text.
381
+ attr_accessor :font
382
+
383
+ # The font size.
384
+ attr_reader :font_size
385
+
386
+ # The text rendering mode.
387
+ #
388
+ # It determines if and how the glyphs of a text should be shown (for all available values
389
+ # see TextRenderingMode).
390
+ attr_accessor :text_rendering_mode
391
+
392
+ # The text rise distance in unscaled text units.
393
+ #
394
+ # It specifies the distance that the baseline should be moved up or down from its default
395
+ # location.
396
+ attr_accessor :text_rise
397
+
398
+ # The text knockout, a boolean value.
399
+ #
400
+ # It specifies whether each glyph should be treated as separate elementary object for the
401
+ # purpose of color compositing in the transparent imaging model (knockout = +false+) or if
402
+ # all glyphs together are treated as one elementary object (knockout = +true+).
403
+ attr_accessor :text_knockout
404
+
405
+
406
+ # The scaled character spacing used in glyph displacement calculations.
407
+ #
408
+ # This returns the value T_c multiplied by #scaled_horizontal_scaling.
409
+ #
410
+ # See PDF1.7 s9.4.4
411
+ attr_reader :scaled_character_spacing
412
+
413
+ # The scaled word spacing used in glyph displacement calculations.
414
+ #
415
+ # This returns the value T_w multiplied by #scaled_horizontal_scaling.
416
+ #
417
+ # See PDF1.7 s9.4.4
418
+ attr_reader :scaled_word_spacing
419
+
420
+ # The scaled font size used in glyph displacement calculations.
421
+ #
422
+ # This returns the value T_fs / 1000 multiplied by #scaled_horizontal_scaling.
423
+ #
424
+ # See PDF1.7 s9.4.4
425
+ attr_reader :scaled_font_size
426
+
427
+ # The scaled horizontal scaling used in glyph displacement calculations.
428
+ #
429
+ # Since the horizontal scaling attribute is stored in percent of 100, this method returns the
430
+ # correct value for calculations.
431
+ #
432
+ # See PDF1.7 s9.4.4
433
+ attr_reader :scaled_horizontal_scaling
434
+
435
+
436
+ # Initializes the graphics state parameters to their default values.
437
+ def initialize
438
+ @ctm = TransformationMatrix.new
439
+ @stroke_color = @fill_color =
440
+ GlobalConfiguration.constantize('color_space.map'.freeze, :DeviceGray).new.default_color
441
+ @line_width = 1.0
442
+ @line_cap_style = LineCapStyle::BUTT_CAP
443
+ @line_join_style = LineJoinStyle::MITER_JOIN
444
+ @miter_limit = 10.0
445
+ @line_dash_pattern = LineDashPattern.new
446
+ @rendering_intent = RenderingIntent::RELATIVE_COLORIMETRIC
447
+ @stroke_adjustment = false
448
+ @blend_mode = :Normal
449
+ @soft_mask = :None
450
+ @stroke_alpha = @fill_alpha = 1.0
451
+ @alpha_source = false
452
+
453
+ @tm = nil
454
+ @tlm = nil
455
+ @character_spacing = 0
456
+ @word_spacing = 0
457
+ @horizontal_scaling = 100
458
+ @leading = 0
459
+ @font = nil
460
+ @font_size = 0
461
+ @text_rendering_mode = TextRenderingMode::FILL
462
+ @text_rise = 0
463
+ @text_knockout = true
464
+
465
+ @scaled_character_spacing = 0
466
+ @scaled_word_spacing = 0
467
+ @scaled_font_size = 0
468
+ @scaled_horizontal_scaling = 1
469
+
470
+ @stack = []
471
+ end
472
+
473
+ # Saves the current graphics state on the internal stack.
474
+ def save
475
+ @stack.push([@ctm, @stroke_color, @fill_color,
476
+ @line_width, @line_cap_style, @line_join_style, @miter_limit,
477
+ @line_dash_pattern, @rendering_intent, @stroke_adjustment, @blend_mode,
478
+ @soft_mask, @stroke_alpha, @fill_alpha, @alpha_source,
479
+ @character_spacing, @word_spacing, @horizontal_scaling, @leading,
480
+ @font, @font_size, @text_rendering_mode, @text_rise, @text_knockout,
481
+ @scaled_character_spacing, @scaled_word_spacing, @scaled_font_size,
482
+ @scaled_horizontal_scaling])
483
+ @ctm = @ctm.dup
484
+ end
485
+
486
+ # Restores the graphics state from the internal stack.
487
+ #
488
+ # Raises an error if the stack is empty.
489
+ def restore
490
+ if @stack.empty?
491
+ raise HexaPDF::Error, "Can't restore graphics state because the stack is empty"
492
+ end
493
+ @ctm, @stroke_color, @fill_color,
494
+ @line_width, @line_cap_style, @line_join_style, @miter_limit, @line_dash_pattern,
495
+ @rendering_intent, @stroke_adjustment, @blend_mode,
496
+ @soft_mask, @stroke_alpha, @fill_alpha, @alpha_source,
497
+ @character_spacing, @word_spacing, @horizontal_scaling, @leading,
498
+ @font, @font_size, @text_rendering_mode, @text_rise, @text_knockout,
499
+ @scaled_character_spacing, @scaled_word_spacing, @scaled_font_size,
500
+ @scaled_horizontal_scaling = @stack.pop
501
+ end
502
+
503
+ # Returns +true+ if the internal stack of saved graphic states contains entries.
504
+ def saved_states?
505
+ !@stack.empty?
506
+ end
507
+
508
+ ##
509
+ # :attr_accessor: stroke_color_space
510
+ #
511
+ # The current color space for stroking operations during painting.
512
+
513
+ # :nodoc:
514
+ def stroke_color_space
515
+ @stroke_color.color_space
516
+ end
517
+
518
+ def stroke_color_space=(color_space) # :nodoc:
519
+ self.stroke_color = color_space.default_color
520
+ end
521
+
522
+ ##
523
+ # :attr_accessor: fill_color_space
524
+ #
525
+ # The current color space for non-stroking operations during painting.
526
+
527
+ # :nodoc:
528
+ def fill_color_space
529
+ @fill_color.color_space
530
+ end
531
+
532
+ def fill_color_space=(color_space) #:nodoc:
533
+ self.fill_color = color_space.default_color
534
+ end
535
+
536
+ ##
537
+ # :attr_writer: character_spacing
538
+ #
539
+ # Sets the character spacing and updates the scaled character spacing.
540
+ def character_spacing=(space)
541
+ @character_spacing = space
542
+ @scaled_character_spacing = space * @scaled_horizontal_scaling
543
+ end
544
+
545
+ ##
546
+ # :attr_writer: word_spacing
547
+ #
548
+ # Sets the word spacing and updates the scaled word spacing.
549
+ def word_spacing=(space)
550
+ @word_spacing = space
551
+ @scaled_word_spacing = space * @scaled_horizontal_scaling
552
+ end
553
+
554
+ ##
555
+ # :attr_writer: font_size
556
+ #
557
+ # Sets the font size and updates the scaled font size.
558
+ def font_size=(size)
559
+ @font_size = size
560
+ @scaled_font_size = size / 1000.0 * @scaled_horizontal_scaling
561
+ end
562
+
563
+ ##
564
+ # :attr_writer: horizontal_scaling
565
+ #
566
+ # Sets the horizontal scaling and updates the scaled character spacing, scaled word spacing
567
+ # and scaled font size.
568
+ def horizontal_scaling=(scaling)
569
+ @horizontal_scaling = scaling
570
+ @scaled_horizontal_scaling = scaling / 100.0
571
+ @scaled_character_spacing = @character_spacing * @scaled_horizontal_scaling
572
+ @scaled_word_spacing = @word_spacing * @scaled_horizontal_scaling
573
+ @scaled_font_size = @font_size / 1000.0 * @scaled_horizontal_scaling
574
+ end
575
+
576
+ end
577
+
578
+ end
579
+ end