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,1072 @@
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/content/graphics_state'
36
+ require 'hexapdf/content/transformation_matrix'
37
+
38
+ module HexaPDF
39
+ module Content
40
+
41
+ # This module contains the content operator implementations.
42
+ #
43
+ # == General Information
44
+ #
45
+ # A PDF content streams consists of a series of instructions, operands followed by an operator
46
+ # name. Each operator has a specific function, for example, the 'G' operator sets the stroke
47
+ # color to the specified gray value.
48
+ #
49
+ # Since HexaPDF doesn't have a content stream rendering facility, it is only interested in the
50
+ # effects an operator has on the graphics state. By calling the #invoke method with a
51
+ # Content::Processor as first argument and the operands as the rest of the arguments, the
52
+ # operator can modify the graphics state as needed. This ensures internal consistency and
53
+ # correct operation.
54
+ #
55
+ # Operator objects are designed to be state-less. This means that the operands have to be
56
+ # passed as arguments to the methods that need them.
57
+ #
58
+ #
59
+ # == Operator Implementations
60
+ #
61
+ # HexaPDF comes with operator implementations for all PDF operations. These operator
62
+ # implementations are derived from the Operator::BaseOperator class which provides all needed
63
+ # methods.
64
+ #
65
+ # In general, an operator implementation is an object that responds to the following methods:
66
+ #
67
+ # #invoke(processor, *operands)::
68
+ # When an operator is invoked, it performs its job, e.g. changing the graphics state.
69
+ #
70
+ # #serialize(serializer, *operands)::
71
+ # Returns the operator together with its operands in serialized form.
72
+ #
73
+ # #name::
74
+ # Returns the name of the operator as String.
75
+ #
76
+ # See: PDF1.7 s8, s9
77
+ module Operator
78
+
79
+ # A base class for operator implementations.
80
+ #
81
+ # A default implementation for the #serialize method is provided. However, for performance
82
+ # reasons each operator should provide a custom #serialize method.
83
+ class BaseOperator
84
+
85
+ # The name of the operator.
86
+ attr_reader :name
87
+
88
+ # Initialize the operator called +name+.
89
+ def initialize(name)
90
+ @name = name.freeze
91
+ end
92
+
93
+ # Invokes the operator so that it performs its job.
94
+ #
95
+ # This base version does nothing!
96
+ def invoke(*)
97
+ end
98
+
99
+ # Returns the string representation of the operator, i.e.
100
+ #
101
+ # operand1 operand2 operand3 name
102
+ def serialize(serializer, *operands)
103
+ result = ''.b
104
+ operands.each do |operand|
105
+ result << serializer.serialize(operand) << " ".freeze
106
+ end
107
+ result << name << "\n".freeze
108
+ end
109
+
110
+ end
111
+
112
+ # A specialized operator class for operators that take no arguments. Provides an optimized
113
+ # #serialize method.
114
+ class NoArgumentOperator < BaseOperator
115
+
116
+ def initialize(name) #:nodoc:
117
+ super(name)
118
+ @serialized = "#{name}\n".freeze
119
+ end
120
+
121
+ def invoke(_processor) # :nodoc:
122
+ end
123
+
124
+ # An optimized version of the serialization algorithm.
125
+ #
126
+ # See: BaseOperator#serialize
127
+ def serialize(_serializer)
128
+ @serialized
129
+ end
130
+
131
+ end
132
+
133
+ # A specialized operator class for operators that take a single numeric argument. Provides
134
+ # an optimized #serialize method.
135
+ class SingleNumericArgumentOperator < BaseOperator
136
+
137
+ # An optimized version of the serialization algorithm.
138
+ #
139
+ # See: BaseOperator#serialize
140
+ def serialize(serializer, arg)
141
+ "#{serializer.serialize_numeric(arg)} #{name}\n"
142
+ end
143
+
144
+ end
145
+
146
+ # Implementation of the 'q' operator.
147
+ #
148
+ # See: PDF1.7 s8.4.4
149
+ class SaveGraphicsState < NoArgumentOperator
150
+
151
+ # Creates the operator.
152
+ def initialize
153
+ super('q')
154
+ end
155
+
156
+ def invoke(processor) #:nodoc:
157
+ processor.graphics_state.save
158
+ end
159
+
160
+ end
161
+
162
+ # Implementation of the 'Q' operator.
163
+ #
164
+ # See: PDF1.7 s8.4.4
165
+ class RestoreGraphicsState < NoArgumentOperator
166
+
167
+ # Creates the operator.
168
+ def initialize
169
+ super('Q')
170
+ end
171
+
172
+ def invoke(processor) #:nodoc:
173
+ processor.graphics_state.restore
174
+ end
175
+
176
+ end
177
+
178
+ # Implementation of the 'cm' operator.
179
+ #
180
+ # See: PDF1.7 s8.4.4
181
+ class ConcatenateMatrix < BaseOperator
182
+
183
+ # Creates the operator.
184
+ def initialize
185
+ super('cm')
186
+ end
187
+
188
+ def invoke(processor, a, b, c, d, e, f) #:nodoc:
189
+ processor.graphics_state.ctm.premultiply(a, b, c, d, e, f)
190
+ end
191
+
192
+ def serialize(serializer, a, b, c, d, e, f) #:nodoc:
193
+ "#{serializer.serialize_numeric(a)} #{serializer.serialize_numeric(b)} " \
194
+ "#{serializer.serialize_numeric(c)} #{serializer.serialize_numeric(d)} " \
195
+ "#{serializer.serialize_numeric(e)} #{serializer.serialize_numeric(f)} cm\n"
196
+ end
197
+
198
+ end
199
+
200
+ # Implementation of the 'w' operator.
201
+ #
202
+ # See: PDF1.7 s8.4.4
203
+ class SetLineWidth < SingleNumericArgumentOperator
204
+
205
+ # Creates the operator.
206
+ def initialize
207
+ super('w')
208
+ end
209
+
210
+ def invoke(processor, width) #:nodoc:
211
+ processor.graphics_state.line_width = width
212
+ end
213
+
214
+ end
215
+
216
+ # Implementation of the 'J' operator.
217
+ #
218
+ # See: PDF1.7 s8.4.4
219
+ class SetLineCapStyle < SingleNumericArgumentOperator
220
+
221
+ # Creates the operator.
222
+ def initialize
223
+ super('J')
224
+ end
225
+
226
+ def invoke(processor, cap_style) #:nodoc:
227
+ processor.graphics_state.line_cap_style = LineCapStyle.normalize(cap_style)
228
+ end
229
+
230
+ end
231
+
232
+ # Implementation of the 'j' operator.
233
+ #
234
+ # See: PDF1.7 s8.4.4
235
+ class SetLineJoinStyle < SingleNumericArgumentOperator
236
+
237
+ # Creates the operator.
238
+ def initialize
239
+ super('j')
240
+ end
241
+
242
+ def invoke(processor, join_style) #:nodoc:
243
+ processor.graphics_state.line_join_style = LineJoinStyle.normalize(join_style)
244
+ end
245
+
246
+ end
247
+
248
+ # Implementation of the 'M' operator.
249
+ #
250
+ # See: PDF1.7 s8.4.4
251
+ class SetMiterLimit < SingleNumericArgumentOperator
252
+
253
+ # Creates the operator.
254
+ def initialize
255
+ super('M')
256
+ end
257
+
258
+ def invoke(processor, miter_limit) #:nodoc:
259
+ processor.graphics_state.miter_limit = miter_limit
260
+ end
261
+
262
+ end
263
+
264
+ # Implementation of the 'd' operator.
265
+ #
266
+ # See: PDF1.7 s8.4.4
267
+ class SetLineDashPattern < BaseOperator
268
+
269
+ # Creates the operator.
270
+ def initialize
271
+ super('d')
272
+ end
273
+
274
+ def invoke(processor, dash_array, dash_phase) #:nodoc:
275
+ processor.graphics_state.line_dash_pattern = LineDashPattern.new(dash_array, dash_phase)
276
+ end
277
+
278
+ def serialize(serializer, dash_array, dash_phase) #:nodoc:
279
+ "#{serializer.serialize_array(dash_array)} " \
280
+ "#{serializer.serialize_integer(dash_phase)} d\n".freeze
281
+ end
282
+
283
+ end
284
+
285
+ # Implementation of the 'ri' operator.
286
+ #
287
+ # See: PDF1.7 s8.4.4
288
+ class SetRenderingIntent < BaseOperator
289
+
290
+ # Creates the operator.
291
+ def initialize
292
+ super('ri')
293
+ end
294
+
295
+ def invoke(processor, intent) #:nodoc:
296
+ processor.graphics_state.rendering_intent = intent
297
+ end
298
+
299
+ def serialize(serializer, intent) #:nodoc:
300
+ "#{serializer.serialize_symbol(intent)} ri\n".freeze
301
+ end
302
+
303
+ end
304
+
305
+ # Implementation of the 'gs' operator.
306
+ #
307
+ # Note: Only parameters supported by the GraphicsState/TextState classes are assigned, the
308
+ # rest are ignored!
309
+ #
310
+ # See: PDF1.7 s8.4.4
311
+ class SetGraphicsStateParameters < BaseOperator
312
+
313
+ # Creates the operator.
314
+ def initialize
315
+ super('gs')
316
+ end
317
+
318
+ def invoke(processor, name) #:nodoc:
319
+ dict = processor.resources.ext_gstate(name)
320
+
321
+ ops = processor.operators
322
+ ops[:w].invoke(processor, dict[:LW]) if dict.key?(:LW)
323
+ ops[:J].invoke(processor, dict[:LC]) if dict.key?(:LC)
324
+ ops[:j].invoke(processor, dict[:LJ]) if dict.key?(:LJ)
325
+ ops[:M].invoke(processor, dict[:ML]) if dict.key?(:ML)
326
+ ops[:d].invoke(processor, *dict[:D]) if dict.key?(:D)
327
+ ops[:ri].invoke(processor, dict[:RI]) if dict.key?(:RI)
328
+ # TODO: dict[:SMask] works differently than operator!
329
+
330
+ # No content operator exists for the following parameters
331
+ gs = processor.graphics_state
332
+ gs.stroke_adjustment = dict[:SA] if dict.key?(:SA)
333
+ gs.blend_mode = dict[:BM] if dict.key?(:BM)
334
+ gs.stroke_alpha = dict[:CA] if dict.key?(:CA)
335
+ gs.fill_alpha = dict[:ca] if dict.key?(:ca)
336
+ gs.alpha_source = dict[:AIS] if dict.key?(:AIS)
337
+ gs.text_knockout = dict[:TK] if dict.key?(:TK)
338
+ if dict.key?(:Font)
339
+ gs.font = processor.resources.document.deref(dict[:Font][0])
340
+ gs.font_size = processor.resources.document.deref(dict[:Font][1])
341
+ end
342
+ end
343
+
344
+ def serialize(serializer, name) #:nodoc:
345
+ "#{serializer.serialize_symbol(name)} gs\n".freeze
346
+ end
347
+
348
+ end
349
+
350
+ # Implementation of the 'CS' operator.
351
+ #
352
+ # See: PDF1.7 s8.6.8
353
+ class SetStrokingColorSpace < BaseOperator
354
+
355
+ # Creates the operator.
356
+ def initialize
357
+ super('CS')
358
+ end
359
+
360
+ def invoke(processor, name) #:nodoc:
361
+ processor.graphics_state.stroke_color_space = processor.resources.color_space(name)
362
+ end
363
+
364
+ def serialize(serializer, name) #:nodoc:
365
+ "#{serializer.serialize_symbol(name)} CS\n".freeze
366
+ end
367
+
368
+ end
369
+
370
+ # Implementation of the 'cs' operator.
371
+ #
372
+ # See: PDF1.7 s8.6.8
373
+ class SetNonStrokingColorSpace < BaseOperator
374
+
375
+ # Creates the operator.
376
+ def initialize
377
+ super('cs')
378
+ end
379
+
380
+ def invoke(processor, name) #:nodoc:
381
+ processor.graphics_state.fill_color_space = processor.resources.color_space(name)
382
+ end
383
+
384
+ def serialize(serializer, name) #:nodoc:
385
+ "#{serializer.serialize_symbol(name)} cs\n".freeze
386
+ end
387
+
388
+ end
389
+
390
+ # Implementation of the 'SC' and 'SCN' operator.
391
+ #
392
+ # See: PDF1.7 s8.6.8
393
+ class SetStrokingColor < BaseOperator
394
+
395
+ def invoke(processor, *operands) #:nodoc:
396
+ processor.graphics_state.stroke_color =
397
+ processor.graphics_state.stroke_color.color_space.color(*operands)
398
+ end
399
+
400
+ end
401
+
402
+ # Implementation of the 'sc' and 'scn' operator.
403
+ #
404
+ # See: PDF1.7 s8.6.8
405
+ class SetNonStrokingColor < BaseOperator
406
+
407
+ def invoke(processor, *operands) #:nodoc:
408
+ processor.graphics_state.fill_color =
409
+ processor.graphics_state.fill_color.color_space.color(*operands)
410
+ end
411
+
412
+ end
413
+
414
+ # Implementation of the 'G' operator.
415
+ #
416
+ # See: PDF1.7 s8.6.8
417
+ class SetDeviceGrayStrokingColor < SingleNumericArgumentOperator
418
+
419
+ def initialize #:nodoc:
420
+ super('G')
421
+ end
422
+
423
+ def invoke(processor, gray) #:nodoc:
424
+ processor.graphics_state.stroke_color =
425
+ processor.resources.color_space(:DeviceGray).color(gray)
426
+ end
427
+
428
+ end
429
+
430
+ # Implementation of the 'g' operator.
431
+ #
432
+ # See: PDF1.7 s8.6.8
433
+ class SetDeviceGrayNonStrokingColor < SingleNumericArgumentOperator
434
+
435
+ # Creates the operator.
436
+ def initialize
437
+ super('g')
438
+ end
439
+
440
+ def invoke(processor, gray) #:nodoc:
441
+ processor.graphics_state.fill_color =
442
+ processor.resources.color_space(:DeviceGray).color(gray)
443
+ end
444
+
445
+ end
446
+
447
+ # Implementation of the 'RG' operator.
448
+ #
449
+ # See: PDF1.7 s8.6.8
450
+ class SetDeviceRGBStrokingColor < BaseOperator
451
+
452
+ # Creates the operator.
453
+ def initialize
454
+ super('RG')
455
+ end
456
+
457
+ def invoke(processor, r, g, b) #:nodoc:
458
+ processor.graphics_state.stroke_color =
459
+ processor.resources.color_space(:DeviceRGB).color(r, g, b)
460
+ end
461
+
462
+ def serialize(serializer, r, g, b) #:nodoc:
463
+ "#{serializer.serialize_numeric(r)} #{serializer.serialize_numeric(g)} " \
464
+ "#{serializer.serialize_numeric(b)} RG\n".freeze
465
+ end
466
+
467
+ end
468
+
469
+ # Implementation of the 'rg' operator.
470
+ #
471
+ # See: PDF1.7 s8.6.8
472
+ class SetDeviceRGBNonStrokingColor < BaseOperator
473
+
474
+ # Creates the operator.
475
+ def initialize
476
+ super('rg')
477
+ end
478
+
479
+ def invoke(processor, r, g, b) #:nodoc:
480
+ processor.graphics_state.fill_color =
481
+ processor.resources.color_space(:DeviceRGB).color(r, g, b)
482
+ end
483
+
484
+ def serialize(serializer, r, g, b) #:nodoc:
485
+ "#{serializer.serialize_numeric(r)} #{serializer.serialize_numeric(g)} " \
486
+ "#{serializer.serialize_numeric(b)} rg\n".freeze
487
+ end
488
+
489
+ end
490
+
491
+ # Implementation of the 'K' operator.
492
+ #
493
+ # See: PDF1.7 s8.6.8
494
+ class SetDeviceCMYKStrokingColor < BaseOperator
495
+
496
+ # Creates the operator.
497
+ def initialize
498
+ super('K')
499
+ end
500
+
501
+ def invoke(processor, c, m, y, k) #:nodoc:
502
+ processor.graphics_state.stroke_color =
503
+ processor.resources.color_space(:DeviceCMYK).color(c, m, y, k)
504
+ end
505
+
506
+ def serialize(serializer, c, m, y, k) #:nodoc:
507
+ "#{serializer.serialize_numeric(c)} #{serializer.serialize_numeric(m)} " \
508
+ "#{serializer.serialize_numeric(y)} #{serializer.serialize_numeric(k)} K\n".freeze
509
+ end
510
+
511
+ end
512
+
513
+ # Implementation of the 'k' operator.
514
+ #
515
+ # See: PDF1.7 s8.6.8
516
+ class SetDeviceCMYKNonStrokingColor < BaseOperator
517
+
518
+ # Creates the operator.
519
+ def initialize
520
+ super('k')
521
+ end
522
+
523
+ def invoke(processor, c, m, y, k) #:nodoc:
524
+ processor.graphics_state.fill_color =
525
+ processor.resources.color_space(:DeviceCMYK).color(c, m, y, k)
526
+ end
527
+
528
+ def serialize(serializer, c, m, y, k) #:nodoc:
529
+ "#{serializer.serialize_numeric(c)} #{serializer.serialize_numeric(m)} " \
530
+ "#{serializer.serialize_numeric(y)} #{serializer.serialize_numeric(k)} k\n".freeze
531
+ end
532
+
533
+ end
534
+
535
+ # Implementation of the 'm' operator.
536
+ #
537
+ # See: PDF1.7 s8.5.2.1
538
+ class MoveTo < BaseOperator
539
+
540
+ # Creates the operator.
541
+ def initialize
542
+ super('m')
543
+ end
544
+
545
+ def invoke(processor, _x, _y) #:nodoc:
546
+ processor.graphics_object = :path
547
+ end
548
+
549
+ def serialize(serializer, x, y) #:nodoc:
550
+ "#{serializer.serialize_numeric(x)} #{serializer.serialize_numeric(y)} m\n".freeze
551
+ end
552
+
553
+ end
554
+
555
+ # Implementation of the 're' operator.
556
+ #
557
+ # See: PDF1.7 s8.5.2.1
558
+ class AppendRectangle < BaseOperator
559
+
560
+ # Creates the operator.
561
+ def initialize
562
+ super('re')
563
+ end
564
+
565
+ def invoke(processor, _x, _y, _w, _h) #:nodoc:
566
+ processor.graphics_object = :path
567
+ end
568
+
569
+ def serialize(serializer, x, y, w, h) #:nodoc:
570
+ "#{serializer.serialize_numeric(x)} #{serializer.serialize_numeric(y)} " \
571
+ "#{serializer.serialize_numeric(w)} #{serializer.serialize_numeric(h)} re\n".freeze
572
+ end
573
+
574
+ end
575
+
576
+ # Implementation of the 'l' operator.
577
+ #
578
+ # See: PDF1.7 s8.5.2.1
579
+ class LineTo < BaseOperator
580
+
581
+ # Creates the operator.
582
+ def initialize
583
+ super('l')
584
+ end
585
+
586
+ def invoke(_processor, _x, _y) #:nodoc:
587
+ end
588
+
589
+ def serialize(serializer, x, y) #:nodoc:
590
+ "#{serializer.serialize_numeric(x)} #{serializer.serialize_numeric(y)} l\n".freeze
591
+ end
592
+
593
+ end
594
+
595
+ # Implementation of the 'c' operators.
596
+ #
597
+ # See: PDF1.7 s8.5.2.1
598
+ class CurveTo < BaseOperator
599
+
600
+ # Creates the operator.
601
+ def initialize
602
+ super('c')
603
+ end
604
+
605
+ def serialize(serializer, x1, y1, x2, y2, x3, y3) #:nodoc:
606
+ "#{serializer.serialize_numeric(x1)} #{serializer.serialize_numeric(y1)} " \
607
+ "#{serializer.serialize_numeric(x2)} #{serializer.serialize_numeric(y2)} " \
608
+ "#{serializer.serialize_numeric(x3)} #{serializer.serialize_numeric(y3)} c\n".freeze
609
+ end
610
+
611
+ end
612
+
613
+ # Implementation of the 'v' operators.
614
+ #
615
+ # See: PDF1.7 s8.5.2.1
616
+ class CurveToNoFirstControlPoint < BaseOperator
617
+
618
+ # Creates the operator.
619
+ def initialize
620
+ super('v')
621
+ end
622
+
623
+ def serialize(serializer, x2, y2, x3, y3) #:nodoc:
624
+ "#{serializer.serialize_numeric(x2)} #{serializer.serialize_numeric(y2)} " \
625
+ "#{serializer.serialize_numeric(x3)} #{serializer.serialize_numeric(y3)} v\n".freeze
626
+ end
627
+
628
+ end
629
+
630
+ # Implementation of the 'y' operators.
631
+ #
632
+ # See: PDF1.7 s8.5.2.1
633
+ class CurveToNoSecondControlPoint < BaseOperator
634
+
635
+ # Creates the operator.
636
+ def initialize
637
+ super('y')
638
+ end
639
+
640
+ def serialize(serializer, x1, y1, x3, y3) #:nodoc:
641
+ "#{serializer.serialize_numeric(x1)} #{serializer.serialize_numeric(y1)} " \
642
+ "#{serializer.serialize_numeric(x3)} #{serializer.serialize_numeric(y3)} y\n".freeze
643
+ end
644
+
645
+ end
646
+
647
+ # Implementation of the 'S', 's', 'f', 'F', 'f*', 'B', 'B*', 'b', 'b*' and 'n' operators.
648
+ #
649
+ # See: PDF1.7 s8.5.3.1
650
+ class EndPath < NoArgumentOperator
651
+
652
+ def invoke(processor) #:nodoc:
653
+ processor.graphics_object = :none
654
+ end
655
+
656
+ end
657
+
658
+ # Implementation of the 'W' and 'W*' operators.
659
+ #
660
+ # See: PDF1.7 s8.5.4
661
+ class ClipPath < NoArgumentOperator
662
+
663
+ def invoke(processor) #:nodoc:
664
+ processor.graphics_object = :clipping_path
665
+ end
666
+
667
+ end
668
+
669
+ # Implementation of the 'BI' operator which handles the *complete* inline image, i.e. the
670
+ # 'ID' and 'EI' operators are never encountered.
671
+ #
672
+ # See: PDF1.7 s8.9.7
673
+ class InlineImage < BaseOperator
674
+
675
+ # Creates the operator.
676
+ def initialize
677
+ super('BI')
678
+ end
679
+
680
+ def serialize(serializer, dict, data) #:nodoc:
681
+ result = "BI\n"
682
+ dict.each do |k, v|
683
+ result << serializer.serialize_symbol(k) << ' '.freeze
684
+ result << serializer.serialize(v) << ' '.freeze
685
+ end
686
+ result << "ID\n".freeze << data << "EI\n"
687
+ end
688
+
689
+ end
690
+
691
+ # Implementation of the 'Tc' operator.
692
+ #
693
+ # See: PDF1.7 s9.3.1
694
+ class SetCharacterSpacing < SingleNumericArgumentOperator
695
+
696
+ # Creates the operator.
697
+ def initialize
698
+ super('Tc')
699
+ end
700
+
701
+ def invoke(processor, char_space) #:nodoc:
702
+ processor.graphics_state.character_spacing = char_space
703
+ end
704
+
705
+ end
706
+
707
+ # Implementation of the 'Tw' operator.
708
+ #
709
+ # See: PDF1.7 s9.3.1
710
+ class SetWordSpacing < SingleNumericArgumentOperator
711
+
712
+ # Creates the operator.
713
+ def initialize
714
+ super('Tw')
715
+ end
716
+
717
+ def invoke(processor, word_space) #:nodoc:
718
+ processor.graphics_state.word_spacing = word_space
719
+ end
720
+
721
+ end
722
+
723
+ # Implementation of the 'Tz' operator.
724
+ #
725
+ # See: PDF1.7 s9.3.1
726
+ class SetHorizontalScaling < SingleNumericArgumentOperator
727
+
728
+ # Creates the operator.
729
+ def initialize
730
+ super('Tz')
731
+ end
732
+
733
+ def invoke(processor, scale) #:nodoc:
734
+ processor.graphics_state.horizontal_scaling = scale
735
+ end
736
+
737
+ end
738
+
739
+ # Implementation of the 'TL' operator.
740
+ #
741
+ # See: PDF1.7 s9.3.1
742
+ class SetLeading < SingleNumericArgumentOperator
743
+
744
+ # Creates the operator.
745
+ def initialize
746
+ super('TL')
747
+ end
748
+
749
+ def invoke(processor, leading) #:nodoc:
750
+ processor.graphics_state.leading = leading
751
+ end
752
+
753
+ end
754
+
755
+ # Implementation of the 'Tf' operator.
756
+ #
757
+ # See: PDF1.7 s9.3.1
758
+ class SetFontAndSize < BaseOperator
759
+
760
+ # Creates the operator.
761
+ def initialize
762
+ super('Tf')
763
+ end
764
+
765
+ def invoke(processor, font, size) #:nodoc:
766
+ processor.graphics_state.font = processor.resources.font(font)
767
+ processor.graphics_state.font_size = size
768
+ end
769
+
770
+ def serialize(serializer, font, size) #:nodoc:
771
+ "#{serializer.serialize_symbol(font)} #{serializer.serialize_numeric(size)} Tf\n".freeze
772
+ end
773
+
774
+ end
775
+
776
+ # Implementation of the 'Tr' operator.
777
+ #
778
+ # See: PDF1.7 s9.3.1
779
+ class SetTextRenderingMode < SingleNumericArgumentOperator
780
+
781
+ # Creates the operator.
782
+ def initialize
783
+ super('Tr')
784
+ end
785
+
786
+ def invoke(processor, rendering_mode) #:nodoc:
787
+ processor.graphics_state.text_rendering_mode = rendering_mode
788
+ end
789
+
790
+ end
791
+
792
+ # Implementation of the 'Ts' operator.
793
+ #
794
+ # See: PDF1.7 s9.3.1
795
+ class SetTextRise < SingleNumericArgumentOperator
796
+
797
+ # Creates the operator.
798
+ def initialize
799
+ super('Ts')
800
+ end
801
+
802
+ def invoke(processor, rise) #:nodoc:
803
+ processor.graphics_state.text_rise = rise
804
+ end
805
+
806
+ end
807
+
808
+ # Implementation of the 'BT' operator.
809
+ #
810
+ # See: PDF1.7 s9.4.1
811
+ class BeginText < NoArgumentOperator
812
+
813
+ def initialize #:nodoc:
814
+ super('BT')
815
+ end
816
+
817
+ def invoke(processor) #:nodoc:
818
+ processor.graphics_object = :text
819
+ processor.graphics_state.tm = TransformationMatrix.new
820
+ processor.graphics_state.tlm = TransformationMatrix.new
821
+ end
822
+
823
+ end
824
+
825
+ # Implementation of the 'ET' operator.
826
+ #
827
+ # See: PDF1.7 s9.4.1
828
+ class EndText < NoArgumentOperator
829
+
830
+ # Creates the operator.
831
+ def initialize
832
+ super('ET')
833
+ end
834
+
835
+ def invoke(processor) #:nodoc:
836
+ processor.graphics_object = :none
837
+ processor.graphics_state.tm = nil
838
+ processor.graphics_state.tlm = nil
839
+ end
840
+
841
+ end
842
+
843
+ # Implementation of the 'Td' operator.
844
+ #
845
+ # See: PDF1.7 s9.4.2
846
+ class MoveText < BaseOperator
847
+
848
+ # Creates the operator.
849
+ def initialize
850
+ super('Td')
851
+ end
852
+
853
+ def invoke(processor, tx, ty) #:nodoc:
854
+ processor.graphics_state.tlm.translate(tx, ty)
855
+ processor.graphics_state.tm = processor.graphics_state.tlm.dup
856
+ end
857
+
858
+ def serialize(serializer, tx, ty) #:nodoc:
859
+ "#{serializer.serialize_numeric(tx)} #{serializer.serialize_numeric(ty)} Td\n".freeze
860
+ end
861
+
862
+ end
863
+
864
+ # Implementation of the 'TD' operator.
865
+ #
866
+ # See: PDF1.7 s9.4.2
867
+ class MoveTextAndSetLeading < BaseOperator
868
+
869
+ # Creates the operator.
870
+ def initialize
871
+ super('TD')
872
+ end
873
+
874
+ def invoke(processor, tx, ty) #:nodoc:
875
+ processor.operators[:TL].invoke(processor, -ty)
876
+ processor.operators[:Td].invoke(processor, tx, ty)
877
+ end
878
+
879
+ def serialize(serializer, tx, ty) #:nodoc:
880
+ "#{serializer.serialize_numeric(tx)} #{serializer.serialize_numeric(ty)} TD\n".freeze
881
+ end
882
+
883
+ end
884
+
885
+ # Implementation of the 'Tm' operator.
886
+ #
887
+ # See: PDF1.7 s9.4.2
888
+ class SetTextMatrix < BaseOperator
889
+
890
+ # Creates the operator.
891
+ def initialize
892
+ super('Tm')
893
+ end
894
+
895
+ def invoke(processor, a, b, c, d, e, f) #:nodoc:
896
+ processor.graphics_state.tm = TransformationMatrix.new(a, b, c, d, e, f)
897
+ processor.graphics_state.tlm = processor.graphics_state.tm.dup
898
+ end
899
+
900
+ def serialize(serializer, a, b, c, d, e, f) #:nodoc:
901
+ "#{serializer.serialize_numeric(a)} #{serializer.serialize_numeric(b)} " \
902
+ "#{serializer.serialize_numeric(c)} #{serializer.serialize_numeric(d)} " \
903
+ "#{serializer.serialize_numeric(e)} #{serializer.serialize_numeric(f)} Tm\n".freeze
904
+ end
905
+
906
+ end
907
+
908
+ # Implementation of the 'T*' operator.
909
+ #
910
+ # See: PDF1.7 s9.4.2
911
+ class MoveTextNextLine < NoArgumentOperator
912
+
913
+ # Creates the operator.
914
+ def initialize
915
+ super('T*')
916
+ end
917
+
918
+ def invoke(processor) #:nodoc:
919
+ leading = processor.graphics_state.leading
920
+ processor.operators[:Td].invoke(processor, 0, -leading)
921
+ end
922
+
923
+ end
924
+
925
+ # Implementation of the 'Tj' operator.
926
+ #
927
+ # See: PDF1.7 s9.4.3
928
+ class ShowText < BaseOperator
929
+
930
+ # Creates the operator.
931
+ def initialize
932
+ super('Tj')
933
+ end
934
+
935
+ def serialize(serializer, text) #:nodoc:
936
+ "#{serializer.serialize_string(text)} Tj\n".freeze
937
+ end
938
+
939
+ end
940
+
941
+ # Implementation of the ' operator.
942
+ #
943
+ # See: PDF1.7 s9.4.3
944
+ class MoveTextNextLineAndShowText < BaseOperator
945
+
946
+ def initialize #:nodoc:
947
+ super("'")
948
+ end
949
+
950
+ def invoke(processor, text) #:nodoc:
951
+ processor.operators[:'T*'].invoke(processor)
952
+ processor.operators[:Tj].invoke(processor, text)
953
+ end
954
+
955
+ def serialize(serializer, text)
956
+ "#{serializer.serialize_string(text)} '\n".freeze
957
+ end
958
+
959
+ end
960
+
961
+ # Implementation of the " operator.
962
+ #
963
+ # See: PDF1.7 s9.4.3
964
+ class SetSpacingMoveTextNextLineAndShowText < BaseOperator
965
+
966
+ # Creates the operator.
967
+ def initialize
968
+ super('"')
969
+ end
970
+
971
+ def invoke(processor, word_space, char_space, text) #:nodoc:
972
+ processor.operators[:Tw].invoke(processor, word_space)
973
+ processor.operators[:Tc].invoke(processor, char_space)
974
+ processor.operators[:"'"].invoke(processor, text)
975
+ end
976
+
977
+ def serialize(serializer, word_space, char_space, text) #:nodoc:
978
+ "#{serializer.serialize_numeric(word_space)} " \
979
+ "#{serializer.serialize_numeric(char_space)} " \
980
+ "#{serializer.serialize_string(text)} \"\n".freeze
981
+ end
982
+
983
+ end
984
+
985
+
986
+ # Implementation of the 'TJ' operator.
987
+ #
988
+ # See: PDF1.7 s9.4.3
989
+ class ShowTextWithPositioning < BaseOperator
990
+
991
+ # Creates the operator.
992
+ def initialize
993
+ super('TJ')
994
+ end
995
+
996
+ def serialize(serializer, array) #:nodoc:
997
+ "#{serializer.serialize_array(array)} TJ\n".freeze
998
+ end
999
+
1000
+ end
1001
+
1002
+
1003
+ # Mapping of operator names to their default operator implementations.
1004
+ DEFAULT_OPERATORS = {
1005
+ q: SaveGraphicsState.new,
1006
+ Q: RestoreGraphicsState.new,
1007
+ cm: ConcatenateMatrix.new,
1008
+ w: SetLineWidth.new,
1009
+ J: SetLineCapStyle.new,
1010
+ j: SetLineJoinStyle.new,
1011
+ M: SetMiterLimit.new,
1012
+ d: SetLineDashPattern.new,
1013
+ ri: SetRenderingIntent.new,
1014
+ gs: SetGraphicsStateParameters.new,
1015
+ CS: SetStrokingColorSpace.new,
1016
+ cs: SetNonStrokingColorSpace.new,
1017
+ SC: SetStrokingColor.new('SC'),
1018
+ SCN: SetStrokingColor.new('SCN'),
1019
+ sc: SetNonStrokingColor.new('sc'),
1020
+ scn: SetNonStrokingColor.new('scn'),
1021
+ G: SetDeviceGrayStrokingColor.new,
1022
+ g: SetDeviceGrayNonStrokingColor.new,
1023
+ RG: SetDeviceRGBStrokingColor.new,
1024
+ rg: SetDeviceRGBNonStrokingColor.new,
1025
+ K: SetDeviceCMYKStrokingColor.new,
1026
+ k: SetDeviceCMYKNonStrokingColor.new,
1027
+ m: MoveTo.new,
1028
+ re: AppendRectangle.new,
1029
+ l: LineTo.new,
1030
+ c: CurveTo.new,
1031
+ v: CurveToNoFirstControlPoint.new,
1032
+ y: CurveToNoSecondControlPoint.new,
1033
+ h: NoArgumentOperator.new('h'),
1034
+ S: EndPath.new('S'),
1035
+ s: EndPath.new('s'),
1036
+ f: EndPath.new('f'),
1037
+ F: EndPath.new('F'),
1038
+ 'f*'.to_sym => EndPath.new('f*'),
1039
+ B: EndPath.new('B'),
1040
+ 'B*'.to_sym => EndPath.new('B*'),
1041
+ b: EndPath.new('b'),
1042
+ 'b*'.to_sym => EndPath.new('b*'),
1043
+ n: EndPath.new('n'),
1044
+ W: ClipPath.new('W'),
1045
+ 'W*'.to_sym => ClipPath.new('W*'),
1046
+
1047
+ BI: InlineImage.new,
1048
+
1049
+ BT: BeginText.new,
1050
+ ET: EndText.new,
1051
+ Tc: SetCharacterSpacing.new,
1052
+ Tw: SetWordSpacing.new,
1053
+ Tz: SetHorizontalScaling.new,
1054
+ TL: SetLeading.new,
1055
+ Tf: SetFontAndSize.new,
1056
+ Tr: SetTextRenderingMode.new,
1057
+ Ts: SetTextRise.new,
1058
+ Td: MoveText.new,
1059
+ TD: MoveTextAndSetLeading.new,
1060
+ Tm: SetTextMatrix.new,
1061
+ 'T*'.to_sym => MoveTextNextLine.new,
1062
+ Tj: ShowText.new,
1063
+ '\''.to_sym => MoveTextNextLineAndShowText.new,
1064
+ '"'.to_sym => SetSpacingMoveTextNextLineAndShowText.new,
1065
+ TJ: ShowTextWithPositioning.new,
1066
+ }
1067
+ DEFAULT_OPERATORS.default_proc = proc {|h, k| h[k] = BaseOperator.new(k.to_s)}
1068
+
1069
+ end
1070
+
1071
+ end
1072
+ end