hexapdf 0.46.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +342 -16
  3. data/LICENSE +1 -1
  4. data/README.md +9 -8
  5. data/examples/009-text_layouter_alignment.rb +4 -0
  6. data/examples/010-text_layouter_inline_boxes.rb +4 -0
  7. data/examples/011-text_layouter_line_wrapping.rb +4 -0
  8. data/examples/012-text_layouter_styling.rb +9 -4
  9. data/examples/013-text_layouter_shapes.rb +5 -0
  10. data/examples/015-boxes.rb +3 -0
  11. data/examples/016-frame_automatic_box_placement.rb +3 -0
  12. data/examples/017-frame_text_flow.rb +3 -0
  13. data/examples/022-outline.rb +5 -1
  14. data/examples/{028-frame_mask_mode.rb → 028-composer_mask_mode.rb} +3 -3
  15. data/lib/hexapdf/cli/batch.rb +1 -1
  16. data/lib/hexapdf/cli/command.rb +65 -65
  17. data/lib/hexapdf/cli/debug_info.rb +98 -0
  18. data/lib/hexapdf/cli/files.rb +1 -1
  19. data/lib/hexapdf/cli/fonts.rb +1 -1
  20. data/lib/hexapdf/cli/form.rb +11 -6
  21. data/lib/hexapdf/cli/image2pdf.rb +1 -1
  22. data/lib/hexapdf/cli/images.rb +19 -4
  23. data/lib/hexapdf/cli/info.rb +1 -1
  24. data/lib/hexapdf/cli/inspect.rb +24 -8
  25. data/lib/hexapdf/cli/merge.rb +1 -1
  26. data/lib/hexapdf/cli/modify.rb +1 -2
  27. data/lib/hexapdf/cli/optimize.rb +6 -6
  28. data/lib/hexapdf/cli/split.rb +1 -1
  29. data/lib/hexapdf/cli/usage.rb +1 -1
  30. data/lib/hexapdf/cli/watermark.rb +1 -1
  31. data/lib/hexapdf/cli.rb +20 -2
  32. data/lib/hexapdf/composer.rb +22 -1
  33. data/lib/hexapdf/configuration.rb +56 -1
  34. data/lib/hexapdf/content/canvas.rb +1 -1
  35. data/lib/hexapdf/content/canvas_composer.rb +1 -1
  36. data/lib/hexapdf/content/color_space.rb +1 -1
  37. data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
  38. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  39. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  40. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  41. data/lib/hexapdf/content/graphic_object.rb +1 -1
  42. data/lib/hexapdf/content/graphics_state.rb +2 -2
  43. data/lib/hexapdf/content/operator.rb +1 -1
  44. data/lib/hexapdf/content/parser.rb +22 -23
  45. data/lib/hexapdf/content/processor.rb +1 -1
  46. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  47. data/lib/hexapdf/content.rb +1 -1
  48. data/lib/hexapdf/data_dir.rb +1 -1
  49. data/lib/hexapdf/dictionary.rb +8 -2
  50. data/lib/hexapdf/dictionary_fields.rb +2 -2
  51. data/lib/hexapdf/digital_signature/cms_handler.rb +19 -2
  52. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  53. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +1 -1
  54. data/lib/hexapdf/digital_signature/signature.rb +2 -2
  55. data/lib/hexapdf/digital_signature/signatures.rb +1 -1
  56. data/lib/hexapdf/digital_signature/signing/default_handler.rb +3 -3
  57. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -2
  58. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +25 -5
  59. data/lib/hexapdf/digital_signature/signing.rb +1 -1
  60. data/lib/hexapdf/digital_signature/verification_result.rb +1 -1
  61. data/lib/hexapdf/digital_signature.rb +1 -1
  62. data/lib/hexapdf/document/annotations.rb +220 -0
  63. data/lib/hexapdf/document/destinations.rb +1 -1
  64. data/lib/hexapdf/document/files.rb +1 -1
  65. data/lib/hexapdf/document/fonts.rb +1 -1
  66. data/lib/hexapdf/document/images.rb +1 -1
  67. data/lib/hexapdf/document/layout.rb +95 -16
  68. data/lib/hexapdf/document/metadata.rb +11 -4
  69. data/lib/hexapdf/document/pages.rb +1 -1
  70. data/lib/hexapdf/document.rb +52 -9
  71. data/lib/hexapdf/encryption/aes.rb +1 -1
  72. data/lib/hexapdf/encryption/arc4.rb +3 -3
  73. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  74. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  75. data/lib/hexapdf/encryption/identity.rb +1 -1
  76. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  77. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  78. data/lib/hexapdf/encryption/security_handler.rb +4 -2
  79. data/lib/hexapdf/encryption/standard_security_handler.rb +40 -29
  80. data/lib/hexapdf/encryption.rb +1 -1
  81. data/lib/hexapdf/error.rb +12 -4
  82. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  83. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  84. data/lib/hexapdf/filter/crypt.rb +1 -1
  85. data/lib/hexapdf/filter/encryption.rb +1 -1
  86. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  87. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  88. data/lib/hexapdf/filter/pass_through.rb +1 -1
  89. data/lib/hexapdf/filter/predictor.rb +1 -1
  90. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  91. data/lib/hexapdf/filter.rb +1 -1
  92. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  93. data/lib/hexapdf/font/cmap/writer.rb +59 -5
  94. data/lib/hexapdf/font/cmap.rb +18 -7
  95. data/lib/hexapdf/font/encoding/base.rb +28 -1
  96. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  97. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  98. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  99. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  100. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  101. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  102. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  103. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  104. data/lib/hexapdf/font/encoding.rb +1 -1
  105. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  106. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  107. data/lib/hexapdf/font/true_type/font.rb +1 -1
  108. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  109. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  110. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  111. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  112. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  113. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  114. data/lib/hexapdf/font/true_type/table/head.rb +1 -1
  115. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  116. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  117. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  118. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  119. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  120. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  121. data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
  122. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  123. data/lib/hexapdf/font/true_type/table.rb +7 -2
  124. data/lib/hexapdf/font/true_type.rb +1 -1
  125. data/lib/hexapdf/font/true_type_wrapper.rb +51 -16
  126. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  127. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  128. data/lib/hexapdf/font/type1/font.rb +1 -1
  129. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  130. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  131. data/lib/hexapdf/font/type1.rb +1 -1
  132. data/lib/hexapdf/font/type1_wrapper.rb +3 -4
  133. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  134. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  135. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  136. data/lib/hexapdf/font_loader/variant_from_name.rb +1 -1
  137. data/lib/hexapdf/font_loader.rb +1 -1
  138. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  139. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  140. data/lib/hexapdf/image_loader/png.rb +1 -1
  141. data/lib/hexapdf/image_loader.rb +1 -1
  142. data/lib/hexapdf/importer.rb +2 -2
  143. data/lib/hexapdf/layout/box.rb +6 -1
  144. data/lib/hexapdf/layout/box_fitter.rb +1 -1
  145. data/lib/hexapdf/layout/column_box.rb +1 -1
  146. data/lib/hexapdf/layout/container_box.rb +64 -29
  147. data/lib/hexapdf/layout/frame.rb +1 -1
  148. data/lib/hexapdf/layout/image_box.rb +1 -1
  149. data/lib/hexapdf/layout/inline_box.rb +1 -1
  150. data/lib/hexapdf/layout/line.rb +1 -1
  151. data/lib/hexapdf/layout/list_box.rb +1 -1
  152. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  153. data/lib/hexapdf/layout/page_style.rb +1 -1
  154. data/lib/hexapdf/layout/style.rb +133 -22
  155. data/lib/hexapdf/layout/table_box.rb +86 -14
  156. data/lib/hexapdf/layout/text_box.rb +1 -1
  157. data/lib/hexapdf/layout/text_fragment.rb +13 -2
  158. data/lib/hexapdf/layout/text_layouter.rb +1 -1
  159. data/lib/hexapdf/layout/text_shaper.rb +1 -1
  160. data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
  161. data/lib/hexapdf/layout.rb +1 -1
  162. data/lib/hexapdf/name_tree_node.rb +1 -1
  163. data/lib/hexapdf/number_tree_node.rb +1 -1
  164. data/lib/hexapdf/object.rb +4 -4
  165. data/lib/hexapdf/parser.rb +36 -7
  166. data/lib/hexapdf/pdf_array.rb +26 -4
  167. data/lib/hexapdf/rectangle.rb +1 -1
  168. data/lib/hexapdf/reference.rb +2 -2
  169. data/lib/hexapdf/revision.rb +7 -3
  170. data/lib/hexapdf/revisions.rb +1 -1
  171. data/lib/hexapdf/serializer.rb +8 -8
  172. data/lib/hexapdf/stream.rb +1 -1
  173. data/lib/hexapdf/task/dereference.rb +1 -1
  174. data/lib/hexapdf/task/merge_acro_form.rb +164 -0
  175. data/lib/hexapdf/task/optimize.rb +5 -5
  176. data/lib/hexapdf/task/pdfa.rb +1 -1
  177. data/lib/hexapdf/task.rb +2 -1
  178. data/lib/hexapdf/test_utils.rb +3 -2
  179. data/lib/hexapdf/tokenizer.rb +52 -44
  180. data/lib/hexapdf/type/acro_form/appearance_generator.rb +66 -13
  181. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  182. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  183. data/lib/hexapdf/type/acro_form/field.rb +6 -2
  184. data/lib/hexapdf/type/acro_form/form.rb +23 -32
  185. data/lib/hexapdf/type/acro_form/java_script_actions.rb +10 -3
  186. data/lib/hexapdf/type/acro_form/signature_field.rb +19 -8
  187. data/lib/hexapdf/type/acro_form/text_field.rb +10 -3
  188. data/lib/hexapdf/type/acro_form/variable_text_field.rb +13 -5
  189. data/lib/hexapdf/type/acro_form.rb +1 -1
  190. data/lib/hexapdf/type/action.rb +1 -1
  191. data/lib/hexapdf/type/actions/go_to.rb +2 -1
  192. data/lib/hexapdf/type/actions/go_to_r.rb +2 -1
  193. data/lib/hexapdf/type/actions/launch.rb +6 -2
  194. data/lib/hexapdf/type/actions/set_ocg_state.rb +1 -1
  195. data/lib/hexapdf/type/actions/uri.rb +1 -1
  196. data/lib/hexapdf/type/actions.rb +1 -1
  197. data/lib/hexapdf/type/annotation.rb +78 -3
  198. data/lib/hexapdf/type/annotations/appearance_generator.rb +426 -0
  199. data/lib/hexapdf/type/annotations/border_effect.rb +99 -0
  200. data/lib/hexapdf/type/annotations/border_styling.rb +160 -0
  201. data/lib/hexapdf/type/annotations/circle.rb +65 -0
  202. data/lib/hexapdf/type/annotations/interior_color.rb +84 -0
  203. data/lib/hexapdf/type/annotations/line.rb +334 -0
  204. data/lib/hexapdf/type/annotations/line_ending_styling.rb +208 -0
  205. data/lib/hexapdf/type/annotations/link.rb +1 -1
  206. data/lib/hexapdf/type/annotations/markup_annotation.rb +15 -3
  207. data/lib/hexapdf/type/annotations/polygon.rb +64 -0
  208. data/lib/hexapdf/type/annotations/polygon_polyline.rb +109 -0
  209. data/lib/hexapdf/type/annotations/polyline.rb +64 -0
  210. data/lib/hexapdf/type/annotations/square.rb +65 -0
  211. data/lib/hexapdf/type/annotations/square_circle.rb +77 -0
  212. data/lib/hexapdf/type/annotations/text.rb +1 -1
  213. data/lib/hexapdf/type/annotations/widget.rb +56 -118
  214. data/lib/hexapdf/type/annotations.rb +13 -1
  215. data/lib/hexapdf/type/catalog.rb +5 -2
  216. data/lib/hexapdf/type/cid_font.rb +6 -3
  217. data/lib/hexapdf/type/cmap.rb +58 -0
  218. data/lib/hexapdf/type/embedded_file.rb +1 -1
  219. data/lib/hexapdf/type/file_specification.rb +18 -15
  220. data/lib/hexapdf/type/font.rb +1 -1
  221. data/lib/hexapdf/type/font_descriptor.rb +5 -4
  222. data/lib/hexapdf/type/font_simple.rb +4 -2
  223. data/lib/hexapdf/type/font_true_type.rb +3 -1
  224. data/lib/hexapdf/type/font_type0.rb +2 -2
  225. data/lib/hexapdf/type/font_type1.rb +19 -1
  226. data/lib/hexapdf/type/font_type3.rb +1 -2
  227. data/lib/hexapdf/type/form.rb +8 -5
  228. data/lib/hexapdf/type/graphics_state_parameter.rb +8 -5
  229. data/lib/hexapdf/type/icon_fit.rb +1 -1
  230. data/lib/hexapdf/type/image.rb +9 -5
  231. data/lib/hexapdf/type/info.rb +3 -3
  232. data/lib/hexapdf/type/mark_information.rb +3 -3
  233. data/lib/hexapdf/type/marked_content_reference.rb +59 -0
  234. data/lib/hexapdf/type/measure.rb +57 -0
  235. data/lib/hexapdf/type/metadata.rb +1 -1
  236. data/lib/hexapdf/type/names.rb +1 -1
  237. data/lib/hexapdf/type/namespace.rb +57 -0
  238. data/lib/hexapdf/type/object_reference.rb +57 -0
  239. data/lib/hexapdf/type/object_stream.rb +1 -1
  240. data/lib/hexapdf/type/optional_content_configuration.rb +2 -2
  241. data/lib/hexapdf/type/optional_content_group.rb +1 -1
  242. data/lib/hexapdf/type/optional_content_membership.rb +2 -2
  243. data/lib/hexapdf/type/optional_content_properties.rb +1 -1
  244. data/lib/hexapdf/type/outline.rb +1 -1
  245. data/lib/hexapdf/type/outline_item.rb +1 -1
  246. data/lib/hexapdf/type/output_intent.rb +1 -1
  247. data/lib/hexapdf/type/page.rb +6 -4
  248. data/lib/hexapdf/type/page_label.rb +1 -1
  249. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  250. data/lib/hexapdf/type/resources.rb +13 -9
  251. data/lib/hexapdf/type/struct_elem.rb +72 -0
  252. data/lib/hexapdf/type/struct_tree_root.rb +64 -0
  253. data/lib/hexapdf/type/trailer.rb +1 -1
  254. data/lib/hexapdf/type/viewer_preferences.rb +5 -4
  255. data/lib/hexapdf/type/xref_stream.rb +1 -1
  256. data/lib/hexapdf/type.rb +8 -1
  257. data/lib/hexapdf/utils/bit_field.rb +1 -1
  258. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  259. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  260. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  261. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  262. data/lib/hexapdf/utils/object_hash.rb +1 -1
  263. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  264. data/lib/hexapdf/utils/sorted_tree_node.rb +17 -4
  265. data/lib/hexapdf/utils.rb +1 -1
  266. data/lib/hexapdf/version.rb +2 -2
  267. data/lib/hexapdf/writer.rb +3 -2
  268. data/lib/hexapdf/xref_section.rb +25 -6
  269. data/lib/hexapdf.rb +1 -1
  270. data/test/data/standard-security-handler/bothpwd-aes-256bit-V5-R5.pdf +43 -0
  271. data/test/data/standard-security-handler/nopwd-aes-256bit-V5-R5.pdf +44 -0
  272. data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5-R5.pdf +43 -0
  273. data/test/data/standard-security-handler/userpwd-aes-256bit-V5-R5.pdf +0 -0
  274. data/test/hexapdf/common_tokenizer_tests.rb +7 -7
  275. data/test/hexapdf/content/test_graphics_state.rb +2 -3
  276. data/test/hexapdf/content/test_operator.rb +4 -5
  277. data/test/hexapdf/digital_signature/common.rb +6 -1
  278. data/test/hexapdf/digital_signature/signing/test_default_handler.rb +6 -1
  279. data/test/hexapdf/digital_signature/signing/test_timestamp_handler.rb +12 -0
  280. data/test/hexapdf/digital_signature/test_cms_handler.rb +25 -15
  281. data/test/hexapdf/digital_signature/test_handler.rb +2 -3
  282. data/test/hexapdf/digital_signature/test_pkcs1_handler.rb +1 -2
  283. data/test/hexapdf/digital_signature/test_signature.rb +7 -0
  284. data/test/hexapdf/digital_signature/test_signatures.rb +12 -7
  285. data/test/hexapdf/document/test_annotations.rb +75 -0
  286. data/test/hexapdf/document/test_layout.rb +38 -10
  287. data/test/hexapdf/document/test_metadata.rb +13 -1
  288. data/test/hexapdf/encryption/common.rb +1 -1
  289. data/test/hexapdf/encryption/test_aes.rb +1 -1
  290. data/test/hexapdf/encryption/test_arc4.rb +2 -2
  291. data/test/hexapdf/encryption/test_security_handler.rb +8 -6
  292. data/test/hexapdf/encryption/test_standard_security_handler.rb +7 -3
  293. data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
  294. data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
  295. data/test/hexapdf/filter/test_flate_decode.rb +2 -3
  296. data/test/hexapdf/font/cmap/test_writer.rb +73 -16
  297. data/test/hexapdf/font/encoding/test_base.rb +20 -0
  298. data/test/hexapdf/font/encoding/test_glyph_list.rb +1 -1
  299. data/test/hexapdf/font/test_true_type_wrapper.rb +31 -5
  300. data/test/hexapdf/font/test_type1_wrapper.rb +8 -1
  301. data/test/hexapdf/font/true_type/test_table.rb +12 -0
  302. data/test/hexapdf/layout/test_box.rb +8 -2
  303. data/test/hexapdf/layout/test_container_box.rb +34 -6
  304. data/test/hexapdf/layout/test_list_box.rb +7 -7
  305. data/test/hexapdf/layout/test_page_style.rb +1 -1
  306. data/test/hexapdf/layout/test_style.rb +46 -12
  307. data/test/hexapdf/layout/test_table_box.rb +66 -16
  308. data/test/hexapdf/layout/test_text_box.rb +0 -6
  309. data/test/hexapdf/layout/test_text_fragment.rb +3 -3
  310. data/test/hexapdf/layout/test_text_layouter.rb +4 -2
  311. data/test/hexapdf/task/test_merge_acro_form.rb +104 -0
  312. data/test/hexapdf/task/test_optimize.rb +3 -1
  313. data/test/hexapdf/test_composer.rb +15 -0
  314. data/test/hexapdf/test_dictionary.rb +15 -0
  315. data/test/hexapdf/test_dictionary_fields.rb +1 -0
  316. data/test/hexapdf/test_document.rb +26 -8
  317. data/test/hexapdf/test_filter.rb +1 -1
  318. data/test/hexapdf/test_importer.rb +7 -0
  319. data/test/hexapdf/test_object.rb +1 -1
  320. data/test/hexapdf/test_parser.rb +87 -18
  321. data/test/hexapdf/test_pdf_array.rb +36 -3
  322. data/test/hexapdf/test_revision.rb +27 -6
  323. data/test/hexapdf/test_revisions.rb +1 -1
  324. data/test/hexapdf/test_serializer.rb +4 -4
  325. data/test/hexapdf/test_stream.rb +1 -2
  326. data/test/hexapdf/test_tokenizer.rb +1 -1
  327. data/test/hexapdf/test_writer.rb +22 -8
  328. data/test/hexapdf/test_xref_section.rb +15 -0
  329. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +118 -26
  330. data/test/hexapdf/type/acro_form/test_button_field.rb +7 -6
  331. data/test/hexapdf/type/acro_form/test_field.rb +10 -0
  332. data/test/hexapdf/type/acro_form/test_form.rb +32 -9
  333. data/test/hexapdf/type/acro_form/test_java_script_actions.rb +21 -0
  334. data/test/hexapdf/type/acro_form/test_signature_field.rb +3 -1
  335. data/test/hexapdf/type/acro_form/test_text_field.rb +7 -1
  336. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +14 -1
  337. data/test/hexapdf/type/actions/test_launch.rb +6 -2
  338. data/test/hexapdf/type/annotations/test_appearance_generator.rb +608 -0
  339. data/test/hexapdf/type/annotations/test_border_effect.rb +59 -0
  340. data/test/hexapdf/type/annotations/test_border_styling.rb +114 -0
  341. data/test/hexapdf/type/annotations/test_interior_color.rb +37 -0
  342. data/test/hexapdf/type/annotations/test_line.rb +144 -0
  343. data/test/hexapdf/type/annotations/test_line_ending_styling.rb +42 -0
  344. data/test/hexapdf/type/annotations/test_polygon_polyline.rb +29 -0
  345. data/test/hexapdf/type/annotations/test_widget.rb +47 -81
  346. data/test/hexapdf/type/test_annotation.rb +58 -0
  347. data/test/hexapdf/type/test_font_type1.rb +20 -1
  348. data/test/hexapdf/type/test_form.rb +7 -1
  349. data/test/hexapdf/type/test_image.rb +1 -1
  350. data/test/hexapdf/type/test_page.rb +7 -1
  351. data/test/hexapdf/type/test_page_tree_node.rb +2 -2
  352. data/test/hexapdf/type/test_resources.rb +3 -1
  353. data/test/hexapdf/utils/test_sorted_tree_node.rb +18 -7
  354. data/test/test_helper.rb +7 -0
  355. metadata +69 -9
@@ -0,0 +1,114 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/annotations/border_styling'
6
+
7
+ describe HexaPDF::Type::Annotations::BorderStyling do
8
+ class TestAnnot < HexaPDF::Type::Annotation
9
+ define_field :BS, type: :Border
10
+ define_field :MK, type: :XXAppearanceCharacteristics
11
+ include HexaPDF::Type::Annotations::BorderStyling
12
+ end
13
+
14
+ before do
15
+ @doc = HexaPDF::Document.new
16
+ @annot = @doc.wrap({Type: :Annot}, type: TestAnnot)
17
+ @color = HexaPDF::Content::ColorSpace.prenormalized_device_color([1, 0, 1])
18
+ end
19
+
20
+ describe "border_style" do
21
+ describe "getter" do
22
+ it "no /Border, /BS or /C|/MK set" do
23
+ @annot.delete(:MK)
24
+ assert_equal([1, nil, :solid, 0, 0], @annot.border_style.to_a)
25
+ end
26
+
27
+ it "no /Border, /BS but with /MK empty" do
28
+ @annot[:Subtype] = :Widget
29
+ @annot[:MK] = {}
30
+ assert_equal([1, nil, :solid, 0, 0], @annot.border_style.to_a)
31
+ end
32
+
33
+ it "uses the color from /C" do
34
+ @annot[:C] = [1, 0, 1]
35
+ assert_equal([1, @color, :solid, 0, 0], @annot.border_style.to_a)
36
+ @annot[:C] = []
37
+ assert_equal([1, nil, :solid, 0, 0], @annot.border_style.to_a)
38
+ end
39
+
40
+ it "uses the color from /MK" do
41
+ @annot[:Subtype] = :Widget
42
+ @annot[:MK] = {BC: [1, 0, 1]}
43
+ assert_equal([1, @color, :solid, 0, 0], @annot.border_style.to_a)
44
+ @annot[:MK][:BC] = []
45
+ assert_equal([1, nil, :solid, 0, 0], @annot.border_style.to_a)
46
+ end
47
+
48
+ it "uses the data from /Border" do
49
+ @annot[:Border] = [1, 2, 3, [1, 2]]
50
+ assert_equal([3, nil, [1, 2], 1, 2], @annot.border_style.to_a)
51
+ end
52
+
53
+ it "uses the data from /BS, overriding /Border values" do
54
+ @annot[:Border] = [1, 2, 3, [1, 2]]
55
+ @annot[:BS] = {W: 5, S: :D, D: [5, 6]}
56
+ assert_equal([5, nil, [5, 6], 0, 0], @annot.border_style.to_a)
57
+
58
+ [[:S, :solid], [:D, [5, 6]], [:B, :beveled], [:I, :inset],
59
+ [:U, :underlined], [:Unknown, :solid]].each do |val, result|
60
+ @annot[:BS] = {S: val, D: [5, 6]}
61
+ assert_equal([1, nil, result, 0, 0], @annot.border_style.to_a)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "setter" do
67
+ it "returns self" do
68
+ assert_equal(@annot, @annot.border_style(width: 1))
69
+ end
70
+
71
+ it "sets the color" do
72
+ @annot.border_style(color: [1.0, 51, 1.0])
73
+ assert_equal([1, 0.2, 1], @annot[:C])
74
+
75
+ @annot.border_style(color: :transparent)
76
+ assert_equal([], @annot[:C])
77
+ end
78
+
79
+ it "sets the color on a widget using /MK" do
80
+ @annot[:Subtype] = :Widget
81
+ @annot.border_style(color: [1.0, 51, 1.0])
82
+ assert_equal([1, 0.2, 1], @annot[:MK][:BC])
83
+
84
+ @annot.border_style(color: :transparent)
85
+ assert_equal([], @annot[:MK][:BC])
86
+ end
87
+
88
+ it "sets the width" do
89
+ @annot.border_style(width: 2)
90
+ assert_equal(2, @annot[:BS][:W])
91
+ end
92
+
93
+ it "sets the style" do
94
+ [[:solid, :S], [[5, 6], :D], [:beveled, :B], [:inset, :I], [:underlined, :U]].each do |val, r|
95
+ @annot.border_style(style: val)
96
+ assert_equal(r, @annot[:BS][:S])
97
+ assert_equal(val, @annot[:BS][:D]) if r == :D
98
+ end
99
+ end
100
+
101
+ it "overrides all priorly set values" do
102
+ @annot.border_style(width: 3, style: :inset, color: [1])
103
+ @annot.border_style(width: 5)
104
+ border_style = @annot.border_style
105
+ assert_equal(:solid, border_style.style)
106
+ assert_equal([0], border_style.color.components)
107
+ end
108
+
109
+ it "raises an error for an unknown style" do
110
+ assert_raises(ArgumentError) { @annot.border_style(style: :unknown) }
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/annotations/interior_color'
6
+
7
+ describe HexaPDF::Type::Annotations::InteriorColor do
8
+ class TestAnnot < HexaPDF::Type::Annotation
9
+ define_field :IC, type: HexaPDF::PDFArray
10
+ include HexaPDF::Type::Annotations::InteriorColor
11
+ end
12
+
13
+ before do
14
+ @doc = HexaPDF::Document.new
15
+ @annot = @doc.wrap({Type: :Annot}, type: TestAnnot)
16
+ end
17
+
18
+ describe "interior_color" do
19
+ it "returns the interior color" do
20
+ assert_nil(@annot.interior_color)
21
+ @annot[:IC] = []
22
+ assert_nil(@annot.interior_color)
23
+ @annot[:IC] = [0.5]
24
+ assert_equal(HexaPDF::Content::ColorSpace.device_color_from_specification(0.5),
25
+ @annot.interior_color)
26
+ end
27
+
28
+ it "sets the interior color" do
29
+ @annot.interior_color(255)
30
+ assert_equal([1.0], @annot[:IC])
31
+ @annot.interior_color(255, 255, 0)
32
+ assert_equal([1.0, 1.0, 0], @annot[:IC])
33
+ @annot.interior_color(:transparent)
34
+ assert_equal([], @annot[:IC])
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,144 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/annotations/line'
6
+
7
+ describe HexaPDF::Type::Annotations::Line do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @line = @doc.add({Type: :Annot, Subtype: :Line, Rect: [0, 0, 0, 0], L: [0, 0, 1, 1]})
11
+ end
12
+
13
+ describe "line" do
14
+ it "returns the coordinates of the start and end points" do
15
+ @line[:L] = [10, 20, 30, 40]
16
+ assert_equal([10, 20, 30, 40], @line.line)
17
+ end
18
+
19
+ it "sets the line points" do
20
+ assert_equal(@line, @line.line(1, 2, 3, 4))
21
+ assert_equal([1, 2, 3, 4], @line[:L])
22
+ end
23
+
24
+ it "raises an ArgumentError if not all arguments are provided" do
25
+ assert_raises(ArgumentError) { @line.line(1, 2, 3) }
26
+ end
27
+ end
28
+
29
+ describe "leader_line_length" do
30
+ it "returns the leader line length" do
31
+ assert_equal(0, @line.leader_line_length)
32
+ @line[:LL] = 10
33
+ assert_equal(10, @line.leader_line_length)
34
+ end
35
+
36
+ it "sets the leader line length" do
37
+ assert_equal(@line, @line.leader_line_length(10))
38
+ assert_equal(10, @line[:LL])
39
+ end
40
+ end
41
+
42
+ describe "leader_line_extension_length" do
43
+ it "returns the leader line extension length" do
44
+ assert_equal(0, @line.leader_line_extension_length)
45
+ @line[:LLE] = 10
46
+ assert_equal(10, @line.leader_line_extension_length)
47
+ end
48
+
49
+ it "sets the leader line extension length" do
50
+ assert_equal(@line, @line.leader_line_extension_length(10))
51
+ assert_equal(10, @line[:LLE])
52
+ end
53
+
54
+ it "raises an error for negative numbers" do
55
+ assert_raises(ArgumentError) { @line.leader_line_extension_length(-10) }
56
+ end
57
+ end
58
+
59
+ describe "leader_line_offset" do
60
+ it "returns the leader line offset" do
61
+ assert_equal(0, @line.leader_line_offset)
62
+ @line[:LLO] = 10
63
+ assert_equal(10, @line.leader_line_offset)
64
+ end
65
+
66
+ it "sets the leader line offset" do
67
+ assert_equal(@line, @line.leader_line_offset(10))
68
+ assert_equal(10, @line[:LLO])
69
+ end
70
+ end
71
+
72
+ describe "captioned" do
73
+ it "returns whether a caption is shown" do
74
+ refute(@line.captioned)
75
+ @line[:Cap] = true
76
+ assert(@line.captioned)
77
+ end
78
+
79
+ it "sets whether a caption should be shown" do
80
+ assert_equal(@line, @line.captioned(true))
81
+ assert_equal(true, @line[:Cap])
82
+ end
83
+ end
84
+
85
+ describe "caption_position" do
86
+ it "returns the caption position" do
87
+ assert_equal(:inline, @line.caption_position)
88
+ @line[:CP] = :Top
89
+ assert_equal(:top, @line.caption_position)
90
+ end
91
+
92
+ it "sets the caption position" do
93
+ assert_equal(@line, @line.caption_position(:top))
94
+ assert_equal(:Top, @line[:CP])
95
+ end
96
+
97
+ it "raises an error on invalid caption positions" do
98
+ assert_raises(ArgumentError) { @line.caption_position(:unknown) }
99
+ end
100
+ end
101
+
102
+ describe "caption_offset" do
103
+ it "returns the caption offset" do
104
+ assert_equal([0, 0], @line.caption_offset)
105
+ @line[:CO] = [10, 5]
106
+ assert_equal([10, 5], @line.caption_offset)
107
+ end
108
+
109
+ it "sets the caption offset" do
110
+ assert_equal(@line, @line.caption_offset(5, 10))
111
+ assert_equal([5, 10], @line[:CO])
112
+ assert_equal(@line, @line.caption_offset(5))
113
+ assert_equal([5, 0], @line[:CO])
114
+ assert_equal(@line, @line.caption_offset(nil, 5))
115
+ assert_equal([0, 5], @line[:CO])
116
+ end
117
+ end
118
+
119
+ describe "perform_validation" do
120
+ it "validates that leader line length is set if extension length is set" do
121
+ @line[:LLE] = 10
122
+ m = nil
123
+ refute(@line.validate {|msg| m = msg })
124
+ assert_match(/\/LL required to be non-zero/, m)
125
+ end
126
+
127
+ it "ensures leader line extension length is non-negative" do
128
+ @line[:LL] = 10
129
+ @line[:LLE] = -10
130
+ m = nil
131
+ assert(@line.validate {|msg| m = msg })
132
+ assert_equal(10, @line[:LLE])
133
+ assert_match(/non-negative/, m)
134
+ end
135
+
136
+ it "ensures leader line offset is non-negative" do
137
+ @line[:LLO] = -10
138
+ m = nil
139
+ assert(@line.validate {|msg| m = msg })
140
+ assert_equal(10, @line[:LLO])
141
+ assert_match(/\/LLO must be a non-negative/, m)
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/annotations/line_ending_styling'
6
+
7
+ describe HexaPDF::Type::Annotations::LineEndingStyling do
8
+ class TestAnnotLineEndingStyling < HexaPDF::Type::Annotation
9
+ define_field :LE, type: HexaPDF::PDFArray, default: [:None, :None]
10
+ include HexaPDF::Type::Annotations::LineEndingStyling
11
+ end
12
+
13
+ before do
14
+ @doc = HexaPDF::Document.new
15
+ @annot = @doc.wrap({Type: :Annot}, type: TestAnnotLineEndingStyling)
16
+ end
17
+
18
+ describe "line_ending_style" do
19
+ it "returns the current style" do
20
+ assert_kind_of(HexaPDF::Type::Annotations::Line::LineEndingStyle, @annot.line_ending_style)
21
+ assert_equal([:none, :none], @annot.line_ending_style.to_a)
22
+ @annot[:LE] = [:Diamond, :OpenArrow]
23
+ assert_equal([:diamond, :open_arrow], @annot.line_ending_style.to_a)
24
+ @annot[:LE] = [:Diamond, :Unknown]
25
+ assert_equal([:diamond, :none], @annot.line_ending_style.to_a)
26
+ end
27
+
28
+ it "sets the style" do
29
+ assert_same(@annot, @annot.line_ending_style(start_style: :OpenArrow))
30
+ assert_equal([:OpenArrow, :None], @annot[:LE])
31
+ assert_same(@annot, @annot.line_ending_style(end_style: :open_arrow))
32
+ assert_equal([:OpenArrow, :OpenArrow], @annot[:LE])
33
+ assert_same(@annot, @annot.line_ending_style(start_style: :circle, end_style: :ClosedArrow))
34
+ assert_equal([:Circle, :ClosedArrow], @annot[:LE])
35
+ end
36
+
37
+ it "raises an error for unknown styles" do
38
+ assert_raises(ArgumentError) { @annot.line_ending_style(start_style: :unknown) }
39
+ assert_raises(ArgumentError) { @annot.line_ending_style(end_style: :unknown) }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/document'
5
+ require 'hexapdf/type/annotations/polygon_polyline'
6
+
7
+ describe HexaPDF::Type::Annotations::PolygonPolyline do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @annot = @doc.add({Type: :Annot, Subtype: :Polyline, Rect: [0, 0, 0, 0]},
11
+ type: HexaPDF::Type::Annotations::PolygonPolyline)
12
+ end
13
+
14
+ describe "vertices" do
15
+ it "returns the coordinates of the vertices" do
16
+ @annot[:Vertices] = [10, 20, 30, 40, 50, 60]
17
+ assert_equal([10, 20, 30, 40, 50, 60], @annot.vertices)
18
+ end
19
+
20
+ it "sets the vertices" do
21
+ assert_same(@annot, @annot.vertices(1, 2, 3, 4, 5, 6))
22
+ assert_equal([1, 2, 3, 4, 5, 6], @annot[:Vertices])
23
+ end
24
+
25
+ it "raises an ArgumentError if an uneven number of arguments is provided" do
26
+ assert_raises(ArgumentError) { @annot.vertices(1, 2, 3) }
27
+ end
28
+ end
29
+ end
@@ -52,6 +52,14 @@ describe HexaPDF::Type::Annotations::Widget do
52
52
  assert_kind_of(HexaPDF::Type::AcroForm::TextField, result)
53
53
  refute_same(@widget.data, result.data)
54
54
  end
55
+
56
+ it "works when the type of the field is defined higher up in the field hierarchy" do
57
+ @widget[:Parent] = {T: 'parent', Kids: [@widget]}
58
+ @widget[:Parent][:Parent] = {FT: :Tx, Kids: [@widget[:Parent]]}
59
+ result = @widget.form_field
60
+ assert_kind_of(HexaPDF::Type::AcroForm::TextField, result)
61
+ refute_same(@widget.data, result.data)
62
+ end
55
63
  end
56
64
 
57
65
  describe "background_color" do
@@ -69,87 +77,6 @@ describe HexaPDF::Type::Annotations::Widget do
69
77
  end
70
78
  end
71
79
 
72
- describe "border_style" do
73
- before do
74
- @widget[:MK] = {BC: [1, 0, 1]}
75
- @color = HexaPDF::Content::ColorSpace.prenormalized_device_color([1, 0, 1])
76
- end
77
-
78
- describe "getter" do
79
- it "no /Border, /BS or /MK set" do
80
- @widget.delete(:MK)
81
- assert_equal([1, nil, :solid, 0, 0], @widget.border_style.to_a)
82
- end
83
-
84
- it "no /Border, /BS but with /MK empty" do
85
- @widget[:MK].delete(:BC)
86
- assert_equal([1, nil, :solid, 0, 0], @widget.border_style.to_a)
87
- end
88
-
89
- it "uses the color from /MK" do
90
- assert_equal([1, @color, :solid, 0, 0], @widget.border_style.to_a)
91
- @widget[:MK][:BC] = []
92
- assert_equal([1, nil, :solid, 0, 0], @widget.border_style.to_a)
93
- end
94
-
95
- it "uses the data from /Border" do
96
- @widget[:Border] = [1, 2, 3, [1, 2]]
97
- assert_equal([3, @color, [1, 2], 1, 2], @widget.border_style.to_a)
98
- end
99
-
100
- it "uses the data from /BS, overriding /Border values" do
101
- @widget[:Border] = [1, 2, 3, [1, 2]]
102
- @widget[:BS] = {W: 5, S: :D, D: [5, 6]}
103
- assert_equal([5, @color, [5, 6], 0, 0], @widget.border_style.to_a)
104
-
105
- [[:S, :solid], [:D, [5, 6]], [:B, :beveled], [:I, :inset],
106
- [:U, :underlined], [:Unknown, :solid]].each do |val, result|
107
- @widget[:BS] = {S: val, D: [5, 6]}
108
- assert_equal([1, @color, result, 0, 0], @widget.border_style.to_a)
109
- end
110
- end
111
- end
112
-
113
- describe "setter" do
114
- it "returns self" do
115
- assert_equal(@widget, @widget.border_style(width: 1))
116
- end
117
-
118
- it "sets the color" do
119
- @widget.border_style(color: [1.0, 51, 1.0])
120
- assert_equal([1, 0.2, 1], @widget[:MK][:BC].value)
121
-
122
- @widget.border_style(color: :transparent)
123
- assert_equal([], @widget[:MK][:BC].value)
124
- end
125
-
126
- it "sets the width" do
127
- @widget.border_style(width: 2)
128
- assert_equal(2, @widget[:BS][:W])
129
- end
130
-
131
- it "sets the style" do
132
- [[:solid, :S], [[5, 6], :D], [:beveled, :B], [:inset, :I], [:underlined, :U]].each do |val, r|
133
- @widget.border_style(style: val)
134
- assert_equal(r, @widget[:BS][:S])
135
- assert_equal(val, @widget[:BS][:D].value) if r == :D
136
- end
137
- end
138
-
139
- it "overrides all priorly set values" do
140
- @widget.border_style(width: 3, style: :inset, color: [1])
141
- @widget.border_style(width: 5)
142
- border_style = @widget.border_style
143
- assert_equal(:solid, border_style.style)
144
- assert_equal([0], border_style.color.components)
145
- end
146
-
147
- it "raises an error for an unknown style" do
148
- assert_raises(ArgumentError) { @widget.border_style(style: :unknown) }
149
- end
150
- end
151
- end
152
-
153
80
  describe "marker_style" do
154
81
  before do
155
82
  @chars = %w[4 l 8 u n H S]
@@ -179,6 +106,20 @@ describe HexaPDF::Type::Annotations::Widget do
179
106
  end
180
107
  end
181
108
 
109
+ it "uses the correct default style" do
110
+ @widget.form_field.initialize_as_check_box
111
+ @widget.marker_style(size: 10)
112
+ assert_equal('4', @widget[:MK][:CA])
113
+
114
+ @widget.form_field.initialize_as_radio_button
115
+ @widget.marker_style(size: 10)
116
+ assert_equal('l', @widget[:MK][:CA])
117
+
118
+ @widget.form_field.initialize_as_push_button
119
+ @widget.marker_style(size: 10)
120
+ assert_equal('', @widget[:MK][:CA])
121
+ end
122
+
182
123
  it "fails if an invalid argument is provided" do
183
124
  assert_raises(ArgumentError) { @widget.marker_style(style: 5) }
184
125
  end
@@ -194,6 +135,8 @@ describe HexaPDF::Type::Annotations::Widget do
194
135
 
195
136
  it "returns the default size if none is set" do
196
137
  assert_equal(0, @widget.marker_style.size)
138
+ @widget.form_field[:DA] = "0.0 g"
139
+ assert_equal(0, @widget.marker_style.size)
197
140
  end
198
141
 
199
142
  it "sets the given size" do
@@ -212,6 +155,8 @@ describe HexaPDF::Type::Annotations::Widget do
212
155
 
213
156
  it "returns the default color if none is set" do
214
157
  assert_equal([0], @widget.marker_style.color.components)
158
+ @widget.form_field[:DA] = "/ZaDb 10 Tfg"
159
+ assert_equal([0], @widget.marker_style.color.components)
215
160
  end
216
161
 
217
162
  it "sets the given color" do
@@ -221,5 +166,26 @@ describe HexaPDF::Type::Annotations::Widget do
221
166
  assert_equal([1, 0.2, 1, 1], @widget.marker_style.color.components)
222
167
  end
223
168
  end
169
+
170
+ describe "font_name" do
171
+ it "returns the font_name" do
172
+ @widget.form_field[:DA] = "/F1 15 Tf"
173
+ assert_equal(:F1, @widget.marker_style.font_name)
174
+ @widget[:DA] = "/F2 10 Tf"
175
+ assert_equal(:F2, @widget.marker_style.font_name)
176
+ end
177
+
178
+ it "returns nil if none is set" do
179
+ assert_nil(@widget.marker_style.font_name)
180
+ @widget.form_field[:DA] = "0.0 g"
181
+ assert_nil(@widget.marker_style.font_name)
182
+ end
183
+
184
+ it "sets the given font_name" do
185
+ @widget.form_field.initialize_as_push_button
186
+ @widget.marker_style(font_name: 'Helvetica', size: 10)
187
+ assert_equal('/F1 10 Tf 0.0 g', @widget[:DA])
188
+ end
189
+ end
224
190
  end
225
191
  end
@@ -67,6 +67,9 @@ describe HexaPDF::Type::Annotation do
67
67
  it "returns the appearance stream of the given type" do
68
68
  assert_nil(@annot.appearance)
69
69
 
70
+ @annot[:AP] = 'some invalid type'
71
+ assert_nil(@annot.appearance)
72
+
70
73
  @annot[:AP] = {N: {}}
71
74
  assert_nil(@annot.appearance)
72
75
 
@@ -113,6 +116,14 @@ describe HexaPDF::Type::Annotation do
113
116
  end
114
117
  end
115
118
 
119
+ describe "regenerate_appearance" do
120
+ it "regenerates the appearance using the data from the annotation object" do
121
+ @annot[:Subtype] = :Unknown
122
+ error = assert_raises(HexaPDF::Error) { @annot.regenerate_appearance }
123
+ assert_match(/Unknown.*not.*supported/, error.message)
124
+ end
125
+ end
126
+
116
127
  describe "flags" do
117
128
  it "returns all flags" do
118
129
  assert_equal([:invisible, :hidden, :no_view], @annot.flags)
@@ -139,6 +150,53 @@ describe HexaPDF::Type::Annotation do
139
150
  end
140
151
  end
141
152
 
153
+ describe "contents" do
154
+ it "returns the contents value" do
155
+ assert_nil(@annot.contents)
156
+ @annot[:Contents] = "test"
157
+ assert_equal("test", @annot.contents)
158
+ end
159
+
160
+ it "sets the contents value" do
161
+ assert_same(@annot, @annot.contents("Test"))
162
+ assert_equal("Test", @annot[:Contents])
163
+ @annot.contents(nil)
164
+ assert_nil(@annot[:Contents])
165
+ end
166
+ end
167
+
168
+ describe "opacity" do
169
+ it "returns the opacity values" do
170
+ opacity = @annot.opacity
171
+ assert_equal(1, opacity.fill_alpha)
172
+ assert_equal(1, opacity.stroke_alpha)
173
+
174
+ @annot[:CA] = 0.5
175
+ opacity = @annot.opacity
176
+ assert_equal(0.5, opacity.fill_alpha)
177
+ assert_equal(0.5, opacity.stroke_alpha)
178
+
179
+ @annot[:ca] = 0.3
180
+ opacity = @annot.opacity
181
+ assert_equal(0.3, opacity.fill_alpha)
182
+ assert_equal(0.5, opacity.stroke_alpha)
183
+ end
184
+
185
+ it "sets the opacity values" do
186
+ @annot.opacity(fill_alpha: 0.3)
187
+ refute(@annot.key?(:CA))
188
+ assert_equal(0.3, @annot[:ca])
189
+
190
+ @annot.opacity(stroke_alpha: 0.5)
191
+ assert_equal(0.3, @annot[:ca])
192
+ assert_equal(0.5, @annot[:CA])
193
+
194
+ @annot.opacity(stroke_alpha: 0.1, fill_alpha: 0.2)
195
+ assert_equal(0.1, @annot[:CA])
196
+ assert_equal(0.2, @annot[:ca])
197
+ end
198
+ end
199
+
142
200
  describe "validation" do
143
201
  it "makes sure that empty appearance stream dictionaries don't cause validation errors" do
144
202
  assert(@annot.validate)
@@ -31,7 +31,7 @@ describe HexaPDF::Type::FontType1::StandardFonts do
31
31
  end
32
32
 
33
33
  it "returns nil if the given name doesn't belong to a standard font" do
34
- refute_nil(@obj.font(:TimesNewRoman))
34
+ assert_nil(@obj.font(:SomeOtherFont))
35
35
  end
36
36
  end
37
37
  end
@@ -138,5 +138,24 @@ describe HexaPDF::Type::FontType1 do
138
138
  @embedded_font.delete(:FontDescriptor)
139
139
  refute(@embedded_font.validate)
140
140
  end
141
+
142
+ it "ensures a correct Symbol value for the /Encoding key" do
143
+ @font[:Encoding] = :Other
144
+ refute(@font.validate)
145
+ end
146
+
147
+ it "works around certain invalid PDFs with a /SymbolEncoding value for /Encoding" do
148
+ @font[:Encoding] = :SymbolEncoding
149
+ @font[:BaseFont] = :Symbol
150
+ assert(@font.validate)
151
+ refute(@font.key?(:Encoding))
152
+ end
153
+
154
+ it "works around certain invalid PDFs with a /StandardEncoding value for /Encoding" do
155
+ @font[:Encoding] = :StandardEncoding
156
+ assert(@font.validate)
157
+ assert(:WinAnsiEncoding, @font[:Encoding][:BaseEncoding])
158
+ assert_equal([39, :quoteright, 96, :quoteleft], @font[:Encoding][:Differences][0, 4])
159
+ end
141
160
  end
142
161
  end
@@ -57,7 +57,7 @@ describe HexaPDF::Type::Form do
57
57
  it "creates the resource dictionary if it is not found" do
58
58
  resources = @form.resources
59
59
  assert_equal(:XXResources, resources.type)
60
- assert_equal({ProcSet: [:PDF, :Text, :ImageB, :ImageC, :ImageI]}, resources.value)
60
+ assert_equal({}, resources.value)
61
61
  end
62
62
 
63
63
  it "returns the already used resource dictionary" do
@@ -125,6 +125,12 @@ describe HexaPDF::Type::Form do
125
125
  [:restore_graphics_state]])
126
126
  end
127
127
 
128
+ it "doesn't move the origin if translate is false" do
129
+ @form[:BBox] = [-10, -5, 100, 300]
130
+ @form.canvas(translate: false).line_width = 5
131
+ assert_operators(@form, [[:set_line_width, [5]]])
132
+ end
133
+
128
134
  it "fails if the form XObject already has data" do
129
135
  @form.stream = '10 w'
130
136
  assert_raises(HexaPDF::Error) { @form.canvas }
@@ -171,7 +171,7 @@ describe HexaPDF::Type::Image do
171
171
 
172
172
  def assert_valid_png(filename, original = nil)
173
173
  if PNG_CHECK_AVAILABLE
174
- result = `pngcheck -q #{filename}`
174
+ result = `pngcheck -q #{filename} 2>/dev/null`
175
175
  assert(result.empty?, "pngcheck error: #{result}")
176
176
  else
177
177
  skip("Skipping PNG output validity check because pngcheck executable is missing")