hexapdf 0.15.8 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (446) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hexapdf/cli/batch.rb +1 -1
  3. data/lib/hexapdf/cli/command.rb +10 -1
  4. data/lib/hexapdf/cli/files.rb +1 -1
  5. data/lib/hexapdf/cli/fonts.rb +145 -0
  6. data/lib/hexapdf/cli/form.rb +27 -26
  7. data/lib/hexapdf/cli/image2pdf.rb +1 -1
  8. data/lib/hexapdf/cli/images.rb +1 -10
  9. data/lib/hexapdf/cli/info.rb +1 -1
  10. data/lib/hexapdf/cli/inspect.rb +1 -1
  11. data/lib/hexapdf/cli/merge.rb +1 -1
  12. data/lib/hexapdf/cli/modify.rb +1 -1
  13. data/lib/hexapdf/cli/optimize.rb +1 -1
  14. data/lib/hexapdf/cli/split.rb +1 -1
  15. data/lib/hexapdf/cli/watermark.rb +1 -1
  16. data/lib/hexapdf/cli.rb +3 -1
  17. data/lib/hexapdf/composer.rb +1 -1
  18. data/lib/hexapdf/configuration.rb +11 -2
  19. data/lib/hexapdf/content/canvas.rb +658 -167
  20. data/lib/hexapdf/content/color_space.rb +185 -3
  21. data/lib/hexapdf/content/graphic_object/arc.rb +111 -12
  22. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  23. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  24. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  25. data/lib/hexapdf/content/graphic_object.rb +1 -1
  26. data/lib/hexapdf/content/graphics_state.rb +1 -1
  27. data/lib/hexapdf/content/operator.rb +1 -1
  28. data/lib/hexapdf/content/parser.rb +1 -1
  29. data/lib/hexapdf/content/processor.rb +1 -1
  30. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  31. data/lib/hexapdf/content.rb +1 -1
  32. data/lib/hexapdf/data_dir.rb +1 -1
  33. data/lib/hexapdf/dictionary.rb +1 -1
  34. data/lib/hexapdf/dictionary_fields.rb +30 -4
  35. data/lib/hexapdf/document/files.rb +3 -3
  36. data/lib/hexapdf/document/fonts.rb +1 -1
  37. data/lib/hexapdf/document/images.rb +1 -1
  38. data/lib/hexapdf/document/pages.rb +1 -1
  39. data/lib/hexapdf/document.rb +1 -1
  40. data/lib/hexapdf/encryption/aes.rb +1 -1
  41. data/lib/hexapdf/encryption/arc4.rb +1 -1
  42. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  43. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  44. data/lib/hexapdf/encryption/identity.rb +1 -1
  45. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  46. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  47. data/lib/hexapdf/encryption/security_handler.rb +1 -1
  48. data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
  49. data/lib/hexapdf/encryption.rb +1 -1
  50. data/lib/hexapdf/error.rb +1 -1
  51. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  52. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  53. data/lib/hexapdf/filter/crypt.rb +1 -1
  54. data/lib/hexapdf/filter/encryption.rb +1 -1
  55. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  56. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  57. data/lib/hexapdf/filter/pass_through.rb +1 -1
  58. data/lib/hexapdf/filter/predictor.rb +1 -1
  59. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  60. data/lib/hexapdf/filter.rb +1 -1
  61. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  62. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  63. data/lib/hexapdf/font/cmap.rb +1 -1
  64. data/lib/hexapdf/font/encoding/base.rb +1 -1
  65. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  66. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  67. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  68. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  69. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  70. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  71. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  72. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  73. data/lib/hexapdf/font/encoding.rb +1 -1
  74. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  75. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  76. data/lib/hexapdf/font/true_type/font.rb +1 -1
  77. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  78. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  79. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  80. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  81. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  82. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  83. data/lib/hexapdf/font/true_type/table/head.rb +1 -1
  84. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  85. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  86. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  87. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  88. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  89. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  90. data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
  91. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  92. data/lib/hexapdf/font/true_type/table.rb +1 -1
  93. data/lib/hexapdf/font/true_type.rb +1 -1
  94. data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
  95. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  96. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  97. data/lib/hexapdf/font/type1/font.rb +1 -1
  98. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  99. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  100. data/lib/hexapdf/font/type1.rb +1 -1
  101. data/lib/hexapdf/font/type1_wrapper.rb +1 -1
  102. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  103. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  104. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  105. data/lib/hexapdf/font_loader.rb +1 -1
  106. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  107. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  108. data/lib/hexapdf/image_loader/png.rb +1 -1
  109. data/lib/hexapdf/image_loader.rb +1 -1
  110. data/lib/hexapdf/importer.rb +1 -1
  111. data/lib/hexapdf/layout/box.rb +4 -2
  112. data/lib/hexapdf/layout/frame.rb +1 -1
  113. data/lib/hexapdf/layout/image_box.rb +1 -1
  114. data/lib/hexapdf/layout/inline_box.rb +1 -1
  115. data/lib/hexapdf/layout/line.rb +1 -1
  116. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  117. data/lib/hexapdf/layout/style.rb +40 -2
  118. data/lib/hexapdf/layout/text_box.rb +1 -1
  119. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  120. data/lib/hexapdf/layout/text_layouter.rb +1 -1
  121. data/lib/hexapdf/layout/text_shaper.rb +1 -1
  122. data/lib/hexapdf/layout/width_from_polygon.rb +2 -2
  123. data/lib/hexapdf/layout.rb +1 -1
  124. data/lib/hexapdf/name_tree_node.rb +1 -1
  125. data/lib/hexapdf/number_tree_node.rb +1 -1
  126. data/lib/hexapdf/object.rb +1 -1
  127. data/lib/hexapdf/parser.rb +2 -2
  128. data/lib/hexapdf/pdf_array.rb +1 -1
  129. data/lib/hexapdf/rectangle.rb +1 -1
  130. data/lib/hexapdf/reference.rb +1 -1
  131. data/lib/hexapdf/revision.rb +1 -1
  132. data/lib/hexapdf/revisions.rb +1 -1
  133. data/lib/hexapdf/serializer.rb +1 -1
  134. data/lib/hexapdf/stream.rb +1 -1
  135. data/lib/hexapdf/task/dereference.rb +1 -1
  136. data/lib/hexapdf/task/optimize.rb +1 -1
  137. data/lib/hexapdf/task.rb +1 -1
  138. data/lib/hexapdf/tokenizer.rb +1 -1
  139. data/lib/hexapdf/type/acro_form/appearance_generator.rb +14 -7
  140. data/lib/hexapdf/type/acro_form/button_field.rb +53 -28
  141. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  142. data/lib/hexapdf/type/acro_form/field.rb +21 -2
  143. data/lib/hexapdf/type/acro_form/form.rb +48 -29
  144. data/lib/hexapdf/type/acro_form/text_field.rb +2 -2
  145. data/lib/hexapdf/type/acro_form/variable_text_field.rb +17 -9
  146. data/lib/hexapdf/type/acro_form.rb +1 -1
  147. data/lib/hexapdf/type/action.rb +1 -1
  148. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  149. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  150. data/lib/hexapdf/type/actions/launch.rb +1 -1
  151. data/lib/hexapdf/type/actions/uri.rb +1 -1
  152. data/lib/hexapdf/type/actions.rb +1 -1
  153. data/lib/hexapdf/type/annotation.rb +1 -1
  154. data/lib/hexapdf/type/annotations/link.rb +1 -1
  155. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  156. data/lib/hexapdf/type/annotations/text.rb +1 -1
  157. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  158. data/lib/hexapdf/type/annotations.rb +1 -1
  159. data/lib/hexapdf/type/catalog.rb +1 -1
  160. data/lib/hexapdf/type/cid_font.rb +1 -1
  161. data/lib/hexapdf/type/embedded_file.rb +1 -1
  162. data/lib/hexapdf/type/file_specification.rb +1 -1
  163. data/lib/hexapdf/type/font.rb +1 -1
  164. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  165. data/lib/hexapdf/type/font_simple.rb +1 -1
  166. data/lib/hexapdf/type/font_true_type.rb +1 -1
  167. data/lib/hexapdf/type/font_type0.rb +1 -1
  168. data/lib/hexapdf/type/font_type1.rb +1 -1
  169. data/lib/hexapdf/type/font_type3.rb +1 -1
  170. data/lib/hexapdf/type/form.rb +1 -1
  171. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  172. data/lib/hexapdf/type/icon_fit.rb +1 -1
  173. data/lib/hexapdf/type/image.rb +1 -1
  174. data/lib/hexapdf/type/info.rb +1 -1
  175. data/lib/hexapdf/type/names.rb +1 -1
  176. data/lib/hexapdf/type/object_stream.rb +1 -1
  177. data/lib/hexapdf/type/page.rb +15 -1
  178. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  179. data/lib/hexapdf/type/resources.rb +1 -1
  180. data/lib/hexapdf/type/trailer.rb +1 -1
  181. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  182. data/lib/hexapdf/type/xref_stream.rb +1 -1
  183. data/lib/hexapdf/type.rb +1 -1
  184. data/lib/hexapdf/utils/bit_field.rb +1 -1
  185. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  186. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  187. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  188. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  189. data/lib/hexapdf/utils/object_hash.rb +1 -1
  190. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  191. data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
  192. data/lib/hexapdf/version.rb +2 -2
  193. data/lib/hexapdf/writer.rb +1 -1
  194. data/lib/hexapdf/xref_section.rb +1 -1
  195. data/lib/hexapdf.rb +1 -1
  196. metadata +5 -264
  197. data/CHANGELOG.md +0 -954
  198. data/LICENSE +0 -29
  199. data/README.md +0 -120
  200. data/Rakefile +0 -108
  201. data/agpl-3.0.txt +0 -661
  202. data/examples/001-hello_world.rb +0 -16
  203. data/examples/002-graphics.rb +0 -275
  204. data/examples/003-arcs.rb +0 -50
  205. data/examples/004-optimizing.rb +0 -23
  206. data/examples/005-merging.rb +0 -27
  207. data/examples/006-standard_pdf_fonts.rb +0 -73
  208. data/examples/007-truetype.rb +0 -42
  209. data/examples/008-show_char_bboxes.rb +0 -55
  210. data/examples/009-text_layouter_alignment.rb +0 -47
  211. data/examples/010-text_layouter_inline_boxes.rb +0 -64
  212. data/examples/011-text_layouter_line_wrapping.rb +0 -57
  213. data/examples/012-text_layouter_styling.rb +0 -122
  214. data/examples/013-text_layouter_shapes.rb +0 -176
  215. data/examples/014-text_in_polygon.rb +0 -60
  216. data/examples/015-boxes.rb +0 -76
  217. data/examples/016-frame_automatic_box_placement.rb +0 -90
  218. data/examples/017-frame_text_flow.rb +0 -60
  219. data/examples/018-composer.rb +0 -44
  220. data/examples/019-acro_form.rb +0 -88
  221. data/examples/emoji-smile.png +0 -0
  222. data/examples/emoji-wink.png +0 -0
  223. data/examples/machupicchu.jpg +0 -0
  224. data/test/data/aes-test-vectors/CBCGFSbox-128-decrypt.data.gz +0 -0
  225. data/test/data/aes-test-vectors/CBCGFSbox-128-encrypt.data.gz +0 -0
  226. data/test/data/aes-test-vectors/CBCGFSbox-192-decrypt.data.gz +0 -0
  227. data/test/data/aes-test-vectors/CBCGFSbox-192-encrypt.data.gz +0 -0
  228. data/test/data/aes-test-vectors/CBCGFSbox-256-decrypt.data.gz +0 -0
  229. data/test/data/aes-test-vectors/CBCGFSbox-256-encrypt.data.gz +0 -0
  230. data/test/data/aes-test-vectors/CBCKeySbox-128-decrypt.data.gz +0 -0
  231. data/test/data/aes-test-vectors/CBCKeySbox-128-encrypt.data.gz +0 -0
  232. data/test/data/aes-test-vectors/CBCKeySbox-192-decrypt.data.gz +0 -0
  233. data/test/data/aes-test-vectors/CBCKeySbox-192-encrypt.data.gz +0 -0
  234. data/test/data/aes-test-vectors/CBCKeySbox-256-decrypt.data.gz +0 -0
  235. data/test/data/aes-test-vectors/CBCKeySbox-256-encrypt.data.gz +0 -0
  236. data/test/data/aes-test-vectors/CBCVarKey-128-decrypt.data.gz +0 -0
  237. data/test/data/aes-test-vectors/CBCVarKey-128-encrypt.data.gz +0 -0
  238. data/test/data/aes-test-vectors/CBCVarKey-192-decrypt.data.gz +0 -0
  239. data/test/data/aes-test-vectors/CBCVarKey-192-encrypt.data.gz +0 -0
  240. data/test/data/aes-test-vectors/CBCVarKey-256-decrypt.data.gz +0 -0
  241. data/test/data/aes-test-vectors/CBCVarKey-256-encrypt.data.gz +0 -0
  242. data/test/data/aes-test-vectors/CBCVarTxt-128-decrypt.data.gz +0 -0
  243. data/test/data/aes-test-vectors/CBCVarTxt-128-encrypt.data.gz +0 -0
  244. data/test/data/aes-test-vectors/CBCVarTxt-192-decrypt.data.gz +0 -0
  245. data/test/data/aes-test-vectors/CBCVarTxt-192-encrypt.data.gz +0 -0
  246. data/test/data/aes-test-vectors/CBCVarTxt-256-decrypt.data.gz +0 -0
  247. data/test/data/aes-test-vectors/CBCVarTxt-256-encrypt.data.gz +0 -0
  248. data/test/data/fonts/Ubuntu-Title.ttf +0 -0
  249. data/test/data/images/cmyk.jpg +0 -0
  250. data/test/data/images/fillbytes.jpg +0 -0
  251. data/test/data/images/gray.jpg +0 -0
  252. data/test/data/images/greyscale-1bit.png +0 -0
  253. data/test/data/images/greyscale-2bit.png +0 -0
  254. data/test/data/images/greyscale-4bit.png +0 -0
  255. data/test/data/images/greyscale-8bit.png +0 -0
  256. data/test/data/images/greyscale-alpha-8bit.png +0 -0
  257. data/test/data/images/greyscale-trns-8bit.png +0 -0
  258. data/test/data/images/greyscale-with-gamma1.0.png +0 -0
  259. data/test/data/images/greyscale-with-gamma1.5.png +0 -0
  260. data/test/data/images/indexed-1bit.png +0 -0
  261. data/test/data/images/indexed-2bit.png +0 -0
  262. data/test/data/images/indexed-4bit.png +0 -0
  263. data/test/data/images/indexed-8bit.png +0 -0
  264. data/test/data/images/indexed-alpha-4bit.png +0 -0
  265. data/test/data/images/indexed-alpha-8bit.png +0 -0
  266. data/test/data/images/rgb.jpg +0 -0
  267. data/test/data/images/truecolour-8bit.png +0 -0
  268. data/test/data/images/truecolour-alpha-8bit.png +0 -0
  269. data/test/data/images/truecolour-gama-chrm-8bit.png +0 -0
  270. data/test/data/images/truecolour-srgb-8bit.png +0 -0
  271. data/test/data/images/ycck.jpg +0 -0
  272. data/test/data/minimal.pdf +0 -44
  273. data/test/data/standard-security-handler/README +0 -9
  274. data/test/data/standard-security-handler/bothpwd-aes-128bit-V4.pdf +0 -44
  275. data/test/data/standard-security-handler/bothpwd-aes-256bit-V5.pdf +0 -0
  276. data/test/data/standard-security-handler/bothpwd-arc4-128bit-V2.pdf +0 -43
  277. data/test/data/standard-security-handler/bothpwd-arc4-128bit-V4.pdf +0 -43
  278. data/test/data/standard-security-handler/bothpwd-arc4-40bit-V1.pdf +0 -0
  279. data/test/data/standard-security-handler/nopwd-aes-128bit-V4.pdf +0 -43
  280. data/test/data/standard-security-handler/nopwd-aes-256bit-V5.pdf +0 -0
  281. data/test/data/standard-security-handler/nopwd-arc4-128bit-V2.pdf +0 -43
  282. data/test/data/standard-security-handler/nopwd-arc4-128bit-V4.pdf +0 -43
  283. data/test/data/standard-security-handler/nopwd-arc4-40bit-V1.pdf +0 -43
  284. data/test/data/standard-security-handler/ownerpwd-aes-128bit-V4.pdf +0 -0
  285. data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5.pdf +0 -43
  286. data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V2.pdf +0 -43
  287. data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V4.pdf +0 -43
  288. data/test/data/standard-security-handler/ownerpwd-arc4-40bit-V1.pdf +0 -43
  289. data/test/data/standard-security-handler/userpwd-aes-128bit-V4.pdf +0 -43
  290. data/test/data/standard-security-handler/userpwd-aes-256bit-V5.pdf +0 -43
  291. data/test/data/standard-security-handler/userpwd-arc4-128bit-V2.pdf +0 -0
  292. data/test/data/standard-security-handler/userpwd-arc4-128bit-V4.pdf +0 -0
  293. data/test/data/standard-security-handler/userpwd-arc4-40bit-V1.pdf +0 -43
  294. data/test/hexapdf/common_tokenizer_tests.rb +0 -236
  295. data/test/hexapdf/content/common.rb +0 -39
  296. data/test/hexapdf/content/graphic_object/test_arc.rb +0 -93
  297. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +0 -90
  298. data/test/hexapdf/content/graphic_object/test_geom2d.rb +0 -79
  299. data/test/hexapdf/content/graphic_object/test_solid_arc.rb +0 -86
  300. data/test/hexapdf/content/test_canvas.rb +0 -1216
  301. data/test/hexapdf/content/test_color_space.rb +0 -164
  302. data/test/hexapdf/content/test_graphics_state.rb +0 -151
  303. data/test/hexapdf/content/test_operator.rb +0 -619
  304. data/test/hexapdf/content/test_parser.rb +0 -99
  305. data/test/hexapdf/content/test_processor.rb +0 -163
  306. data/test/hexapdf/content/test_transformation_matrix.rb +0 -64
  307. data/test/hexapdf/document/test_files.rb +0 -72
  308. data/test/hexapdf/document/test_fonts.rb +0 -60
  309. data/test/hexapdf/document/test_images.rb +0 -72
  310. data/test/hexapdf/document/test_pages.rb +0 -130
  311. data/test/hexapdf/encryption/common.rb +0 -87
  312. data/test/hexapdf/encryption/test_aes.rb +0 -129
  313. data/test/hexapdf/encryption/test_arc4.rb +0 -39
  314. data/test/hexapdf/encryption/test_fast_aes.rb +0 -17
  315. data/test/hexapdf/encryption/test_fast_arc4.rb +0 -12
  316. data/test/hexapdf/encryption/test_identity.rb +0 -21
  317. data/test/hexapdf/encryption/test_ruby_aes.rb +0 -23
  318. data/test/hexapdf/encryption/test_ruby_arc4.rb +0 -20
  319. data/test/hexapdf/encryption/test_security_handler.rb +0 -380
  320. data/test/hexapdf/encryption/test_standard_security_handler.rb +0 -322
  321. data/test/hexapdf/filter/common.rb +0 -53
  322. data/test/hexapdf/filter/test_ascii85_decode.rb +0 -59
  323. data/test/hexapdf/filter/test_ascii_hex_decode.rb +0 -38
  324. data/test/hexapdf/filter/test_crypt.rb +0 -21
  325. data/test/hexapdf/filter/test_encryption.rb +0 -24
  326. data/test/hexapdf/filter/test_flate_decode.rb +0 -44
  327. data/test/hexapdf/filter/test_lzw_decode.rb +0 -52
  328. data/test/hexapdf/filter/test_predictor.rb +0 -219
  329. data/test/hexapdf/filter/test_run_length_decode.rb +0 -32
  330. data/test/hexapdf/font/cmap/test_parser.rb +0 -102
  331. data/test/hexapdf/font/cmap/test_writer.rb +0 -66
  332. data/test/hexapdf/font/encoding/test_base.rb +0 -45
  333. data/test/hexapdf/font/encoding/test_difference_encoding.rb +0 -29
  334. data/test/hexapdf/font/encoding/test_glyph_list.rb +0 -59
  335. data/test/hexapdf/font/encoding/test_zapf_dingbats_encoding.rb +0 -16
  336. data/test/hexapdf/font/test_cmap.rb +0 -104
  337. data/test/hexapdf/font/test_encoding.rb +0 -27
  338. data/test/hexapdf/font/test_invalid_glyph.rb +0 -34
  339. data/test/hexapdf/font/test_true_type_wrapper.rb +0 -186
  340. data/test/hexapdf/font/test_type1_wrapper.rb +0 -107
  341. data/test/hexapdf/font/true_type/common.rb +0 -17
  342. data/test/hexapdf/font/true_type/table/common.rb +0 -27
  343. data/test/hexapdf/font/true_type/table/test_cmap.rb +0 -47
  344. data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +0 -141
  345. data/test/hexapdf/font/true_type/table/test_directory.rb +0 -30
  346. data/test/hexapdf/font/true_type/table/test_glyf.rb +0 -58
  347. data/test/hexapdf/font/true_type/table/test_head.rb +0 -56
  348. data/test/hexapdf/font/true_type/table/test_hhea.rb +0 -26
  349. data/test/hexapdf/font/true_type/table/test_hmtx.rb +0 -30
  350. data/test/hexapdf/font/true_type/table/test_kern.rb +0 -61
  351. data/test/hexapdf/font/true_type/table/test_loca.rb +0 -33
  352. data/test/hexapdf/font/true_type/table/test_maxp.rb +0 -50
  353. data/test/hexapdf/font/true_type/table/test_name.rb +0 -76
  354. data/test/hexapdf/font/true_type/table/test_os2.rb +0 -55
  355. data/test/hexapdf/font/true_type/table/test_post.rb +0 -78
  356. data/test/hexapdf/font/true_type/test_builder.rb +0 -42
  357. data/test/hexapdf/font/true_type/test_font.rb +0 -116
  358. data/test/hexapdf/font/true_type/test_optimizer.rb +0 -26
  359. data/test/hexapdf/font/true_type/test_subsetter.rb +0 -73
  360. data/test/hexapdf/font/true_type/test_table.rb +0 -48
  361. data/test/hexapdf/font/type1/common.rb +0 -6
  362. data/test/hexapdf/font/type1/test_afm_parser.rb +0 -65
  363. data/test/hexapdf/font/type1/test_font.rb +0 -104
  364. data/test/hexapdf/font/type1/test_font_metrics.rb +0 -22
  365. data/test/hexapdf/font/type1/test_pfb_parser.rb +0 -37
  366. data/test/hexapdf/font_loader/test_from_configuration.rb +0 -43
  367. data/test/hexapdf/font_loader/test_from_file.rb +0 -36
  368. data/test/hexapdf/font_loader/test_standard14.rb +0 -33
  369. data/test/hexapdf/image_loader/test_jpeg.rb +0 -93
  370. data/test/hexapdf/image_loader/test_pdf.rb +0 -47
  371. data/test/hexapdf/image_loader/test_png.rb +0 -259
  372. data/test/hexapdf/layout/test_box.rb +0 -152
  373. data/test/hexapdf/layout/test_frame.rb +0 -350
  374. data/test/hexapdf/layout/test_image_box.rb +0 -73
  375. data/test/hexapdf/layout/test_inline_box.rb +0 -71
  376. data/test/hexapdf/layout/test_line.rb +0 -206
  377. data/test/hexapdf/layout/test_style.rb +0 -779
  378. data/test/hexapdf/layout/test_text_box.rb +0 -140
  379. data/test/hexapdf/layout/test_text_fragment.rb +0 -375
  380. data/test/hexapdf/layout/test_text_layouter.rb +0 -758
  381. data/test/hexapdf/layout/test_text_shaper.rb +0 -62
  382. data/test/hexapdf/layout/test_width_from_polygon.rb +0 -108
  383. data/test/hexapdf/task/test_dereference.rb +0 -51
  384. data/test/hexapdf/task/test_optimize.rb +0 -162
  385. data/test/hexapdf/test_composer.rb +0 -258
  386. data/test/hexapdf/test_configuration.rb +0 -93
  387. data/test/hexapdf/test_data_dir.rb +0 -32
  388. data/test/hexapdf/test_dictionary.rb +0 -340
  389. data/test/hexapdf/test_dictionary_fields.rb +0 -245
  390. data/test/hexapdf/test_document.rb +0 -641
  391. data/test/hexapdf/test_filter.rb +0 -100
  392. data/test/hexapdf/test_importer.rb +0 -106
  393. data/test/hexapdf/test_object.rb +0 -258
  394. data/test/hexapdf/test_parser.rb +0 -637
  395. data/test/hexapdf/test_pdf_array.rb +0 -169
  396. data/test/hexapdf/test_rectangle.rb +0 -73
  397. data/test/hexapdf/test_reference.rb +0 -50
  398. data/test/hexapdf/test_revision.rb +0 -188
  399. data/test/hexapdf/test_revisions.rb +0 -196
  400. data/test/hexapdf/test_serializer.rb +0 -195
  401. data/test/hexapdf/test_stream.rb +0 -274
  402. data/test/hexapdf/test_tokenizer.rb +0 -80
  403. data/test/hexapdf/test_type.rb +0 -18
  404. data/test/hexapdf/test_writer.rb +0 -140
  405. data/test/hexapdf/test_xref_section.rb +0 -61
  406. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +0 -794
  407. data/test/hexapdf/type/acro_form/test_button_field.rb +0 -302
  408. data/test/hexapdf/type/acro_form/test_choice_field.rb +0 -220
  409. data/test/hexapdf/type/acro_form/test_field.rb +0 -247
  410. data/test/hexapdf/type/acro_form/test_form.rb +0 -353
  411. data/test/hexapdf/type/acro_form/test_signature_field.rb +0 -38
  412. data/test/hexapdf/type/acro_form/test_text_field.rb +0 -195
  413. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +0 -77
  414. data/test/hexapdf/type/actions/test_launch.rb +0 -24
  415. data/test/hexapdf/type/actions/test_uri.rb +0 -23
  416. data/test/hexapdf/type/annotations/test_markup_annotation.rb +0 -22
  417. data/test/hexapdf/type/annotations/test_text.rb +0 -34
  418. data/test/hexapdf/type/annotations/test_widget.rb +0 -225
  419. data/test/hexapdf/type/test_annotation.rb +0 -97
  420. data/test/hexapdf/type/test_catalog.rb +0 -48
  421. data/test/hexapdf/type/test_cid_font.rb +0 -61
  422. data/test/hexapdf/type/test_file_specification.rb +0 -141
  423. data/test/hexapdf/type/test_font.rb +0 -67
  424. data/test/hexapdf/type/test_font_descriptor.rb +0 -61
  425. data/test/hexapdf/type/test_font_simple.rb +0 -176
  426. data/test/hexapdf/type/test_font_true_type.rb +0 -31
  427. data/test/hexapdf/type/test_font_type0.rb +0 -120
  428. data/test/hexapdf/type/test_font_type1.rb +0 -142
  429. data/test/hexapdf/type/test_font_type3.rb +0 -26
  430. data/test/hexapdf/type/test_form.rb +0 -120
  431. data/test/hexapdf/type/test_image.rb +0 -261
  432. data/test/hexapdf/type/test_info.rb +0 -9
  433. data/test/hexapdf/type/test_object_stream.rb +0 -117
  434. data/test/hexapdf/type/test_page.rb +0 -587
  435. data/test/hexapdf/type/test_page_tree_node.rb +0 -315
  436. data/test/hexapdf/type/test_resources.rb +0 -209
  437. data/test/hexapdf/type/test_trailer.rb +0 -116
  438. data/test/hexapdf/type/test_xref_stream.rb +0 -143
  439. data/test/hexapdf/utils/test_bit_field.rb +0 -63
  440. data/test/hexapdf/utils/test_bit_stream.rb +0 -69
  441. data/test/hexapdf/utils/test_graphics_helpers.rb +0 -37
  442. data/test/hexapdf/utils/test_lru_cache.rb +0 -22
  443. data/test/hexapdf/utils/test_object_hash.rb +0 -120
  444. data/test/hexapdf/utils/test_pdf_doc_encoding.rb +0 -18
  445. data/test/hexapdf/utils/test_sorted_tree_node.rb +0 -239
  446. data/test/test_helper.rb +0 -58
@@ -1,758 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- require 'test_helper'
4
- require 'hexapdf/layout'
5
- require 'hexapdf/document'
6
- require_relative "../content/common"
7
-
8
- module TestTextLayouterHelpers
9
- def boxes(*dims)
10
- dims.map do |width, height|
11
- box = HexaPDF::Layout::InlineBox.create(width: width, height: height || 0) {}
12
- HexaPDF::Layout::TextLayouter::Box.new(box)
13
- end
14
- end
15
-
16
- def glue(width)
17
- HexaPDF::Layout::TextLayouter::Glue.new(HexaPDF::Layout::InlineBox.create(width: width) {})
18
- end
19
-
20
- def penalty(penalty, item = nil)
21
- if item
22
- HexaPDF::Layout::TextLayouter::Penalty.new(penalty, item.width, item: item)
23
- else
24
- HexaPDF::Layout::TextLayouter::Penalty.new(penalty)
25
- end
26
- end
27
-
28
- def assert_box(obj, item)
29
- assert_kind_of(HexaPDF::Layout::TextLayouter::Box, obj)
30
- if obj.item.kind_of?(HexaPDF::Layout::InlineBox)
31
- assert_same(item, obj.item)
32
- else
33
- assert_same(item.style, obj.item.style)
34
- assert_equal(item.items, obj.item.items)
35
- end
36
- end
37
-
38
- def assert_glue(obj, fragment)
39
- assert_kind_of(HexaPDF::Layout::TextLayouter::Glue, obj)
40
- assert_same(fragment.style, obj.item.style)
41
- end
42
-
43
- def assert_penalty(obj, penalty, item = nil)
44
- assert_kind_of(HexaPDF::Layout::TextLayouter::Penalty, obj)
45
- assert_equal(penalty, obj.penalty)
46
- if item
47
- assert_same(item.style, obj.item.style)
48
- assert_equal(item.items, obj.item.items)
49
- end
50
- end
51
-
52
- def assert_line_wrapping(result, widths)
53
- rest, lines = *result
54
- assert(rest.empty?)
55
- assert_equal(widths.length, lines.count)
56
- widths.each_with_index {|width, index| assert_equal(width, lines[index].width) }
57
- end
58
- end
59
-
60
- describe HexaPDF::Layout::TextLayouter::SimpleTextSegmentation do
61
- include TestTextLayouterHelpers
62
-
63
- before do
64
- @doc = HexaPDF::Document.new
65
- @font = @doc.fonts.add("Times")
66
- @obj = HexaPDF::Layout::TextLayouter::SimpleTextSegmentation
67
- end
68
-
69
- def setup_fragment(text, style = nil)
70
- if style
71
- HexaPDF::Layout::TextFragment.create(text, style)
72
- else
73
- HexaPDF::Layout::TextFragment.create(text, font: @font)
74
- end
75
- end
76
-
77
- it "handles InlineBox objects" do
78
- input = HexaPDF::Layout::InlineBox.create(width: 10, height: 10) {}
79
- result = @obj.call([input, input])
80
- assert_equal(2, result.size)
81
- assert_box(result[0], input)
82
- assert_box(result[1], input)
83
- end
84
-
85
- it "handles plain text" do
86
- frag = setup_fragment("Testtext")
87
- result = @obj.call([frag])
88
- assert_equal(1, result.size)
89
- assert_box(result[0], frag)
90
- end
91
-
92
- it "inserts a glue in places where spaces are" do
93
- frag = setup_fragment("This is a test")
94
- space = setup_fragment(" ", frag.style)
95
-
96
- result = @obj.call([frag])
97
- assert_equal(7, result.size)
98
- assert_glue(result[1], space)
99
- assert_glue(result[3], space)
100
- assert_glue(result[5], space)
101
- end
102
-
103
- it "inserts a glue representing 8 spaces when a tab is encountered" do
104
- frag = setup_fragment("This\ttest")
105
- tab = setup_fragment(" " * 8, frag.style)
106
-
107
- result = @obj.call([frag])
108
- assert_equal(3, result.size)
109
- assert_glue(result[1], tab)
110
- end
111
-
112
- it "insert a mandatory break when an Unicode line boundary characters is encountered" do
113
- frag = setup_fragment("A\rB\r\nC\nD\vE\fF\u{85}G\u{2029}H\u{2028}I\r")
114
- frag.items << 5 << frag.items[-2]
115
-
116
- result = @obj.call([frag])
117
- assert_equal(20, result.size)
118
- [1, 3, 5, 7, 9, 11, 13, 17, 19].each do |index|
119
- assert_penalty(result[index],
120
- HexaPDF::Layout::TextLayouter::Penalty::PARAGRAPH_BREAK)
121
- assert_equal([], result[index].item.items)
122
- assert(result[index].item.items.frozen?)
123
- assert_same(frag.style, result[index].item.style)
124
- end
125
- assert_penalty(result[15], HexaPDF::Layout::TextLayouter::Penalty::LINE_BREAK)
126
- assert_equal([], result[15].item.items)
127
- assert(result[15].item.items.frozen?)
128
- assert_same(frag.style, result[15].item.style)
129
- end
130
-
131
- it "insert a standard penalty after a hyphen" do
132
- frag = setup_fragment("hy-phen-a-tion - cool!")
133
-
134
- result = @obj.call([frag])
135
- assert_equal(12, result.size)
136
- [1, 3, 5, 9].each do |index|
137
- assert_penalty(result[index], HexaPDF::Layout::TextLayouter::Penalty::Standard.penalty)
138
- end
139
- end
140
-
141
- it "insert a neutral penalty in places where zero-width-spaces are" do
142
- frag = setup_fragment("zero\u{200B}width\u{200B}space")
143
-
144
- result = @obj.call([frag])
145
- assert_equal(5, result.size)
146
- assert_penalty(result[1], 0)
147
- assert_penalty(result[3], 0)
148
- end
149
-
150
- it "insert a special penalty for soft-hyphens" do
151
- frag = setup_fragment("soft\u{00AD}hyphened")
152
- hyphen = setup_fragment("-", frag.style)
153
-
154
- result = @obj.call([frag])
155
- assert_equal(3, result.size)
156
- assert_penalty(result[1], HexaPDF::Layout::TextLayouter::Penalty::Standard.penalty, hyphen)
157
- end
158
-
159
- it "insert a prohibited break penalty for non-breaking spaces" do
160
- frag = setup_fragment("soft\u{00A0}hyphened")
161
- space = setup_fragment(" ", frag.style)
162
-
163
- result = @obj.call([frag])
164
- assert_equal(3, result.size)
165
- assert_penalty(result[1], HexaPDF::Layout::TextLayouter::Penalty::ProhibitedBreak.penalty, space)
166
- end
167
- end
168
-
169
- # Common tests for fixed and variable width line wrapping. The including class needs to define a
170
- # #call(items, width = 100) method with a default with of 100. The optional block is called after a
171
- # line has been yielded by the line wrapping algorithm.
172
- module CommonLineWrappingTests
173
- extend Minitest::Spec::DSL
174
-
175
- include TestTextLayouterHelpers
176
-
177
- it "breaks before a box if it doesn't fit onto the line anymore" do
178
- rest, lines = call(boxes(25, 50, 25, 10))
179
- assert_line_wrapping([rest, lines], [100, 10])
180
- lines.each {|line| line.items.each {|item| assert_kind_of(HexaPDF::Layout::InlineBox, item) } }
181
- end
182
-
183
- it "breaks at a glue and ignores it if it doesn't fit onto the line anymore" do
184
- result = call(boxes(90) + [glue(20)] + boxes(20))
185
- assert_line_wrapping(result, [90, 20])
186
- end
187
-
188
- it "handles spaces at the start of a line" do
189
- rest, lines = call([glue(15)] + boxes(25, 50))
190
- assert_line_wrapping([rest, lines], [75])
191
- assert_equal(25, lines[0].items[0].width)
192
- end
193
-
194
- it "handles spaces at the end of a line" do
195
- rest, lines = call(boxes(20, 50) + [glue(10), glue(10)] + boxes(20))
196
- assert_line_wrapping([rest, lines], [70, 20])
197
- assert_equal(50, lines[0].items[-1].width)
198
- end
199
-
200
- it "handles spaces at the end of a line before a mandatory break" do
201
- rest, lines = call(boxes(20, 50) + [glue(10), penalty(-5000)] + boxes(20))
202
- assert_line_wrapping([rest, lines], [70, 20])
203
- assert_equal(50, lines[0].items[-1].width)
204
- end
205
-
206
- it "handles multiple glue items after another" do
207
- result = call(boxes(20) + [glue(20), glue(20)] + boxes(20, 50, 20))
208
- assert_line_wrapping(result, [80, 70])
209
- end
210
-
211
- it "handles mandatory line breaks" do
212
- rest, lines = call(boxes(20) + [penalty(-5000)] + boxes(20))
213
- assert_line_wrapping([rest, lines], [20, 20])
214
- assert(lines[0].ignore_justification?)
215
- end
216
-
217
- it "handles breaking at penalties with zero width" do
218
- result = call(boxes(80) + [penalty(0)] + boxes(10) + [penalty(0)] + boxes(20))
219
- assert_line_wrapping(result, [90, 20])
220
- end
221
-
222
- it "handles breaking at penalties with non-zero width if they fit on the line" do
223
- pitem = penalty(0, boxes(20).first)
224
- rest, lines = call(boxes(20) + [pitem] + boxes(50) + [glue(10), pitem] + boxes(30))
225
- assert_line_wrapping([rest, lines], [100, 30])
226
- assert_same(pitem.item, lines[0].items[-1])
227
- end
228
-
229
- it "handles breaking at penalties with non-zero width that fit on the line and are followed by 1+ penalties" do
230
- pitem = penalty(0, boxes(20).first)
231
- result = call(boxes(80) + [pitem, penalty(0), penalty(0)] + boxes(30))
232
- assert_line_wrapping(result, [100, 30])
233
- end
234
-
235
- it "handles penalties with non-zero width if they don't fit on the line" do
236
- item = boxes(20).first
237
- result = call(boxes(70) + [glue(10)] + boxes(10) + [penalty(0, item)] + boxes(30))
238
- assert_line_wrapping(result, [70, 40])
239
- end
240
-
241
- it "handles breaking at penalties with non-zero width surrounded by glue" do
242
- item = boxes(20).first
243
- result = call(boxes(70) + [glue(10)] + [penalty(0, item)] + [glue(30)] + boxes(30))
244
- assert_line_wrapping(result, [100, 30])
245
- end
246
-
247
- it "handles prohibited breakpoint penalties with zero width" do
248
- result = call(boxes(70) + [glue(10)] + boxes(10) + [penalty(5000)] + boxes(30))
249
- assert_line_wrapping(result, [70, 40])
250
- end
251
-
252
- it "handles prohibited breakpoint penalties with non-zero width" do
253
- item = boxes(20).first
254
- result = call(boxes(70) + [glue(10)] + boxes(10) + [penalty(5000, item)] + boxes(30))
255
- assert_line_wrapping(result, [70, 60])
256
- end
257
-
258
- it "stops when nil is returned by the block: last item is a box" do
259
- done = false
260
- rest, lines = call(boxes(20, 20, 20), 20) { done ? nil : done = true }
261
- assert_equal(2, rest.count)
262
- assert_equal(2, lines.count)
263
- end
264
-
265
- it "stops when nil is returned by the block: last item is a glue" do
266
- done = false
267
- items = boxes(20, 15, 20).insert(-2, glue(10))
268
- rest, = call(items, 20) { done ? nil : done = true }
269
- assert_equal(3, rest.count)
270
- assert_equal(15, rest[0].width)
271
- end
272
-
273
- it "stops when nil is returned by the block: last item is a mandatory break penalty" do
274
- items = boxes(20, 20).insert(-2, penalty(-5000))
275
- rest, = call(items, 20) { nil }
276
- assert_equal(3, rest.count)
277
- end
278
-
279
- it "stops when nil is returned by the block: works for the last line" do
280
- done = false
281
- rest, lines = call(boxes(20, 20), 20) { done ? nil : done = true }
282
- assert_equal(1, rest.count)
283
- assert_equal(2, lines.count)
284
- end
285
-
286
- end
287
-
288
- describe HexaPDF::Layout::TextLayouter::SimpleLineWrapping do
289
- before do
290
- @obj = HexaPDF::Layout::TextLayouter::SimpleLineWrapping
291
- end
292
-
293
- describe "fixed width wrapping" do
294
- include CommonLineWrappingTests
295
-
296
- def call(items, width = 100, &block)
297
- lines = []
298
- block ||= proc { true }
299
- rest = @obj.call(items, proc { width }) {|line, item| lines << line; block.call(line, item) }
300
- [rest, lines]
301
- end
302
- end
303
-
304
- describe "variable width wrapping" do
305
- include CommonLineWrappingTests
306
-
307
- def call(items, width = 100, &block)
308
- lines = []
309
- block ||= proc { true }
310
- rest = @obj.call(items, proc {|_| width }) {|line, i| lines << line; block.call(line, i) }
311
- [rest, lines]
312
- end
313
-
314
- it "handles changing widths" do
315
- height = 0
316
- width_block = lambda do |line|
317
- case height + line.height
318
- when 0..10 then 60
319
- when 11..20 then 40
320
- when 21..30 then 20
321
- else 60
322
- end
323
- end
324
- lines = []
325
- rest = @obj.call(boxes([20, 10], [10, 10], [20, 15], [40, 10]), width_block) do |line|
326
- height += line.height
327
- lines << line
328
- true
329
- end
330
- assert(rest.empty?)
331
- assert_equal(3, lines.size)
332
- assert_equal(30, lines[0].width)
333
- assert_equal(20, lines[1].width)
334
- assert_equal(40, lines[2].width)
335
- end
336
-
337
- it "handles changing widths when breaking on a penalty" do
338
- height = 0
339
- width_block = lambda do |line|
340
- case height + line.height
341
- when 0..10 then 80
342
- else 50
343
- end
344
- end
345
- lines = []
346
- item = HexaPDF::Layout::InlineBox.create(width: 20, height: 10) {}
347
- items = boxes([20, 10]) + [penalty(0, item)] + boxes([40, 15])
348
- rest = @obj.call(items, width_block) do |line|
349
- height += line.height
350
- lines << line
351
- true
352
- end
353
- assert(rest.empty?)
354
- assert_equal(2, lines.size)
355
- assert_equal(40, lines[0].width)
356
- assert_equal(40, lines[1].width)
357
- assert_equal(25, height)
358
- end
359
- end
360
- end
361
-
362
- describe HexaPDF::Layout::TextLayouter do
363
- include TestTextLayouterHelpers
364
-
365
- before do
366
- @doc = HexaPDF::Document.new
367
- @font = @doc.fonts.add("Times")
368
- @style = HexaPDF::Layout::Style.new(font: @font)
369
- end
370
-
371
- describe "initialize" do
372
- it "can use a Style object" do
373
- style = HexaPDF::Layout::Style.new(font: @font, font_size: 20)
374
- layouter = HexaPDF::Layout::TextLayouter.new(style)
375
- assert_equal(20, layouter.style.font_size)
376
- end
377
-
378
- it "can use a style options" do
379
- layouter = HexaPDF::Layout::TextLayouter.new(font: @font, font_size: 20)
380
- assert_equal(20, layouter.style.font_size)
381
- end
382
- end
383
-
384
- describe "fit" do
385
- before do
386
- @layouter = HexaPDF::Layout::TextLayouter.new(@style)
387
- end
388
-
389
- it "does nothing if there are no items" do
390
- result = @layouter.fit([], 100, 100)
391
- assert_equal(:success, result.status)
392
- assert_equal(0, result.height)
393
- end
394
-
395
- it "handles text indentation" do
396
- items = boxes([20, 20], [20, 20], [20, 20]) +
397
- [penalty(HexaPDF::Layout::TextLayouter::Penalty::PARAGRAPH_BREAK)] +
398
- boxes([40, 20]) + [glue(20)] +
399
- boxes(*([[20, 20]] * 4)) + [penalty(HexaPDF::Layout::TextLayouter::Penalty::LINE_BREAK)] +
400
- boxes(*([[20, 20]] * 4))
401
- @style.text_indent = 20
402
-
403
- [60, proc { 60 }].each do |width|
404
- result = @layouter.fit(items, width, 200)
405
- assert_equal([40, 20, 40, 60, 20, 60, 20], result.lines.map(&:width))
406
- assert_equal([20, 0, 20, 0, 0, 0, 0], result.lines.map(&:x_offset))
407
- assert(result.remaining_items.empty?)
408
- assert_equal(:success, result.status)
409
- end
410
- end
411
-
412
- it "fits using a limited height" do
413
- result = @layouter.fit(boxes(*([[20, 20]] * 100)), 20, 100)
414
- assert_equal(95, result.remaining_items.count)
415
- assert_equal(:height, result.status)
416
- assert_equal(100, result.height)
417
- end
418
-
419
- it "takes line spacing into account when calculating the height" do
420
- @style.line_spacing = :double
421
- result = @layouter.fit(boxes(*([[20, 20]] * 5)), 20, 200)
422
- assert(result.remaining_items.empty?)
423
- assert_equal(:success, result.status)
424
- assert_equal(20 * (5 + 4), result.height)
425
- end
426
-
427
- it "takes line spacing into account with variable width" do
428
- @style.line_spacing = :double
429
- width_block = lambda {|l, h| l + h <= 90 ? 40 : 20 }
430
- result = @layouter.fit(boxes(*([[20, 20]] * 6)), width_block, 170)
431
- assert(result.remaining_items.empty?)
432
- assert_equal(:success, result.status)
433
- assert_line_wrapping([[], result.lines], [40, 40, 20, 20])
434
- assert_equal(140, result.height)
435
- end
436
-
437
- it "handles empty lines if the break penalties don't have an item" do
438
- items = boxes([20, 20]) + [penalty(-5000)] + boxes([30, 20]) + [penalty(-5000)] * 2 +
439
- boxes([20, 20]) + [penalty(-5000)] * 2
440
- result = @layouter.fit(items, 30, 100)
441
- assert(result.remaining_items.empty?)
442
- assert_equal(:success, result.status)
443
- assert_equal(5, result.lines.count)
444
- assert_equal(20 + 20 + 9 + 20 + 9, result.height)
445
- end
446
-
447
- it "handles line breaks in combination with multiple parts per line" do
448
- items = boxes([20, 20]) + [penalty(-5000)] +
449
- boxes([20, 20], [20, 20], [20, 20]) + [penalty(-5000)] +
450
- [penalty(-5000)] +
451
- boxes([20, 20])
452
- result = @layouter.fit(items, [0, 40, 0, 40, 0, 40], 100)
453
- assert_equal(:success, result.status)
454
- assert_equal([20, 40, 20, 0, 20], result.lines.map(&:width))
455
- assert_equal([20, 20, 0, 6.83, 22.17], result.lines.map(&:y_offset))
456
- end
457
-
458
- describe "fixed width and too wide item" do
459
- it "single part per line" do
460
- result = @layouter.fit(boxes([20, 20], [50, 20]), 30, 100)
461
- assert_equal(1, result.remaining_items.count)
462
- assert_equal(:box_too_wide, result.status)
463
- assert_equal(20, result.height)
464
- end
465
-
466
- it "multiple parts per line, one fits" do
467
- result = @layouter.fit(boxes([20, 20], [40, 20], [40, 20], [10, 20]),
468
- [0, 30, 0, 50, 0, 30, 0, 30], 100)
469
- assert_equal(0, result.remaining_items.count)
470
- assert_equal([20, 40, 0, 0, 0, 50], result.lines.map(&:width))
471
- assert_equal([0, 30, 80, 110, 0, 30], result.lines.map(&:x_offset))
472
- assert_equal([20, 0, 0, 0, 20, 0], result.lines.map(&:y_offset))
473
- assert_equal(:success, result.status)
474
- assert_equal(40, result.height)
475
- end
476
-
477
- it "multiple parts per line, none fits" do
478
- result = @layouter.fit(boxes([20, 20], [50, 20]), [0, 30, 0, 30, 0, 30], 100)
479
- assert_equal(1, result.remaining_items.count)
480
- assert_equal(:box_too_wide, result.status)
481
- assert_equal(20, result.height)
482
- end
483
- end
484
-
485
- describe "variable width" do
486
- it "single part per line, searches for vertical offset if the first item is too wide" do
487
- width_block = lambda do |height, _|
488
- case height
489
- when 0..20 then 10
490
- else 40
491
- end
492
- end
493
- result = @layouter.fit(boxes([20, 18]), width_block, 100)
494
- assert(result.remaining_items.empty?)
495
- assert_equal(:success, result.status)
496
- assert_equal(1, result.lines.count)
497
- assert_equal(42, result.lines[0].y_offset)
498
- assert_equal(42, result.height)
499
- end
500
-
501
- it "single part per line, searches for vertical offset if an item is too wide" do
502
- width_block = lambda do |height, line_height|
503
- if (40..60).cover?(height) || (40..60).cover?(height + line_height)
504
- 10
505
- else
506
- 40
507
- end
508
- end
509
- result = @layouter.fit(boxes(*([[20, 18]] * 7)), width_block, 100)
510
- assert_equal(1, result.remaining_items.count)
511
- assert_equal(:height, result.status)
512
- assert_equal(3, result.lines.count)
513
- assert_equal(18, result.lines[0].y_offset)
514
- assert_equal(18, result.lines[1].y_offset)
515
- assert_equal(48, result.lines[2].y_offset)
516
- assert_equal(84, result.height)
517
- end
518
-
519
- it "multiple parts per line, reset line because of line height change during first part" do
520
- width_block = lambda do |height, line_height|
521
- if height == 0 && line_height <= 10
522
- [0, 40, 0, 40]
523
- elsif height == 0 && line_height > 10
524
- [0, 30, 0, 40]
525
- else
526
- [0, 60]
527
- end
528
- end
529
- result = @layouter.fit(boxes([20, 10], [20, 10], [20, 18], [20, 10]), width_block, 100)
530
- assert_equal(:success, result.status)
531
- assert_equal(0, result.remaining_items.count)
532
- assert_equal(3, result.lines.count)
533
- assert_equal([20, 40, 20], result.lines.map(&:width))
534
- assert_equal([18, 0, 10], result.lines.map(&:y_offset))
535
- assert_equal(28, result.height)
536
- end
537
-
538
- it "multiple parts per line, reset line because of line height change after first part" do
539
- width_block = lambda do |height, line_height|
540
- if height == 0 && line_height <= 10
541
- [0, 40, 0, 40]
542
- elsif height == 0 && line_height > 10
543
- [0, 30, 0, 40]
544
- else
545
- [0, 60]
546
- end
547
- end
548
- result = @layouter.fit(boxes([20, 10], [15, 10], [10, 10], [12, 18], [20, 10]),
549
- width_block, 100)
550
- assert_equal(:success, result.status)
551
- assert_equal(0, result.remaining_items.count)
552
- assert_equal(3, result.lines.count)
553
- assert_equal([20, 37, 20], result.lines.map(&:width))
554
- assert_equal([18, 0, 10], result.lines.map(&:y_offset))
555
- assert_equal(28, result.height)
556
- end
557
- end
558
-
559
- describe "breaks a text fragment into parts if it is wider than the available width" do
560
- before do
561
- @str = " This is averylongstring"
562
- @frag = HexaPDF::Layout::TextFragment.create(@str, font: @font)
563
- end
564
-
565
- it "works with fixed width" do
566
- result = @layouter.fit([@frag], 20, 100)
567
- assert(result.remaining_items.empty?)
568
- assert_equal(:success, result.status)
569
- assert_equal(@str.delete(" ").length, result.lines.sum {|l| l.items.sum {|i| i.items.count } })
570
- assert_equal(54, result.height)
571
-
572
- result = @layouter.fit([@frag], 1, 100)
573
- assert_equal(8, result.remaining_items.count)
574
- assert_equal(:box_too_wide, result.status)
575
- end
576
-
577
- it "works with variable width" do
578
- width_block = lambda do |height, line_height|
579
- # 'averylongstring' would fit when only considering height but not height + line_height
580
- if height + line_height < 15
581
- 63
582
- else
583
- 10
584
- end
585
- end
586
- result = @layouter.fit([@frag], width_block, 30)
587
- assert_equal(:height, result.status)
588
- assert_equal([26.95, 9.44, 7.77], result.lines.map {|l| l.width.round(3) })
589
- end
590
- end
591
-
592
- describe "horizontal alignment" do
593
- before do
594
- @items = boxes(*[[20, 20]] * 4) + [glue(10), penalty(-5000, boxes(0).first.item)]
595
- end
596
-
597
- it "aligns the contents to the left" do
598
- @style.align = :left
599
- result = @layouter.fit(@items, 100, 100)
600
- assert_equal(0, result.lines[0].x_offset)
601
- assert_equal(80, result.lines[0].width)
602
- result = @layouter.fit(@items, proc { 100 }, 100)
603
- assert_equal(0, result.lines[0].x_offset)
604
- assert_equal(80, result.lines[0].width)
605
- end
606
-
607
- it "aligns the contents to the center" do
608
- @style.align = :center
609
- result = @layouter.fit(@items, 100, 100)
610
- assert_equal(10, result.lines[0].x_offset)
611
- result = @layouter.fit(@items, proc { 100 }, 100)
612
- assert_equal(10, result.lines[0].x_offset)
613
- end
614
-
615
- it "aligns the contents to the right" do
616
- @style.align = :right
617
- result = @layouter.fit(@items, 100, 100)
618
- assert_equal(20, result.lines[0].x_offset)
619
- result = @layouter.fit(@items, proc { 100 }, 100)
620
- assert_equal(20, result.lines[0].x_offset)
621
- end
622
- end
623
-
624
- describe "vertical alignment" do
625
- before do
626
- @items = boxes(*[[20, 20]] * 4)
627
- end
628
-
629
- it "aligns the contents to the top" do
630
- @style.valign = :top
631
- result = @layouter.fit(@items, 40, 100)
632
- assert_equal(result.lines[0].y_max, result.lines[0].y_offset)
633
- assert_equal(40, result.height)
634
- end
635
-
636
- it "aligns the contents to the center" do
637
- @style.valign = :center
638
- result = @layouter.fit(@items, 40, 100)
639
- assert_equal((100 - 40) / 2 + 20, result.lines[0].y_offset)
640
- assert_equal(70, result.height)
641
- end
642
-
643
- it "aligns the contents to the bottom" do
644
- @style.valign = :bottom
645
- result = @layouter.fit(@items, 40, 100)
646
- assert_equal(100 - 20 * 2 + 20, result.lines[0].y_offset)
647
- assert_equal(100, result.height)
648
- end
649
- end
650
-
651
- it "post-processes lines for justification if needed" do
652
- frag10 = HexaPDF::Layout::TextFragment.create(" ", font: @font)
653
- frag10.items.freeze
654
- frag10b = HexaPDF::Layout::TextLayouter::Box.new(frag10)
655
- frag20 = HexaPDF::Layout::TextFragment.create(" ", font: @font, font_size: 20)
656
- frag20b = HexaPDF::Layout::TextLayouter::Box.new(frag20)
657
- items = boxes(20, 20, 20, 20, 30).insert(1, frag10b).insert(3, frag20b).insert(5, frag10b)
658
- # Width of spaces: 2.5 * 2 + 5 = 10 (from AFM file, adjusted for font size)
659
- # Line width: 20 * 4 + width_of_spaces = 90
660
- # Missing width: 100 - 90 = 10
661
- # -> Each space must be doubled!
662
-
663
- @style.align = :justify
664
- result = @layouter.fit(items, 100, 100)
665
- assert(result.remaining_items.empty?)
666
- assert_equal(:success, result.status)
667
- assert_equal(9, result.lines[0].items.count)
668
- assert_in_delta(100, result.lines[0].width)
669
- assert_equal(-250, result.lines[0].items[1].items[0])
670
- assert_equal(-250, result.lines[0].items[4].items[0])
671
- assert_equal(-250, result.lines[0].items[6].items[0])
672
- assert_equal(30, result.lines[1].width)
673
- end
674
- end
675
-
676
- describe "Result#draw" do
677
- def assert_positions(content, positions)
678
- processor = TestHelper::OperatorRecorder.new
679
- HexaPDF::Content::Parser.new.parse(content, processor)
680
- result = processor.recorded_ops
681
- leading = (result.select {|name, _| name == :set_leading } || [0]).map(&:last).flatten.first
682
- pos = [0, 0]
683
- result.select! {|name, _| name == :set_text_matrix || name == :move_text_next_line }.
684
- map! do |name, ops|
685
- case name
686
- when :set_text_matrix then pos = ops[-2, 2]
687
- when :move_text_next_line then pos[1] -= leading
688
- end
689
- pos.dup
690
- end
691
- positions.each_with_index do |(x, y), index|
692
- assert_in_delta(x, result[index][0], 0.00001)
693
- assert_in_delta(y, result[index][1], 0.00001)
694
- end
695
- end
696
-
697
- before do
698
- @frag = HexaPDF::Layout::TextFragment.create("This is some more text.\n" \
699
- "This is some more text.", font: @font)
700
- @width = HexaPDF::Layout::TextFragment.create("This is some ", font: @font).width
701
- @layouter = HexaPDF::Layout::TextLayouter.new
702
- @canvas = @doc.pages.add.canvas
703
-
704
- @line1w = HexaPDF::Layout::TextFragment.create("This is some", font: @font).width
705
- @line2w = HexaPDF::Layout::TextFragment.create("more text.", font: @font).width
706
- end
707
-
708
- it "respects the x- and y-offsets" do
709
- top = 100
710
- @layouter.style.valign = :center
711
- @layouter.style.align = :center
712
-
713
- result = @layouter.fit([@frag], @width, top)
714
- result.draw(@canvas, 5, top)
715
-
716
- initial_baseline = top - result.lines.first.y_offset
717
- assert_positions(@canvas.contents,
718
- [[5 + (@width - @line1w) / 2, initial_baseline],
719
- [5 + (@width - @line2w) / 2, initial_baseline - @frag.height],
720
- [5 + (@width - @line1w) / 2, initial_baseline - @frag.height * 2],
721
- [5 + (@width - @line2w) / 2, initial_baseline - @frag.height * 3]])
722
- end
723
-
724
- it "makes sure that text fragments don't pollute the graphics state for inline boxes" do
725
- inline_box = HexaPDF::Layout::InlineBox.create(width: 10, height: 10) {|c, _| c.text("A") }
726
- result = @layouter.fit([@frag, inline_box], 200, 100)
727
- assert_raises(HexaPDF::Error) { result.draw(@canvas, 0, 0) } # bc font should be reset to nil
728
- end
729
-
730
- it "doesn't do unnecessary work for consecutive text fragments with same style" do
731
- @layouter.fit([@frag], 200, 100).draw(@canvas, 0, 0)
732
- assert_operators(@canvas.contents, [[:save_graphics_state],
733
- [:set_leading, [9.0]],
734
- [:set_font_and_size, [:F1, 10]],
735
- [:begin_text],
736
- [:move_text, [0, -6.83]],
737
- [:show_text, ["This is some more text."]],
738
- [:move_text_next_line],
739
- [:show_text, ["This is some more text."]],
740
- [:end_text],
741
- [:restore_graphics_state]])
742
- end
743
-
744
- it "doesn't do unnecessary work for placeholder boxes" do
745
- box1 = HexaPDF::Layout::InlineBox.create(width: 10, height: 20)
746
- box2 = HexaPDF::Layout::InlineBox.create(width: 30, height: 40) { @canvas.line_width(2) }
747
- @layouter.fit([box1, box2], 200, 100).draw(@canvas, 0, 0)
748
- assert_operators(@canvas.contents, [[:save_graphics_state],
749
- [:restore_graphics_state],
750
- [:save_graphics_state],
751
- [:concatenate_matrix, [1, 0, 0, 1, 10, -40]],
752
- [:set_line_width, [2]],
753
- [:restore_graphics_state],
754
- [:save_graphics_state],
755
- [:restore_graphics_state]])
756
- end
757
- end
758
- end