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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +342 -16
- data/LICENSE +1 -1
- data/README.md +9 -8
- data/examples/009-text_layouter_alignment.rb +4 -0
- data/examples/010-text_layouter_inline_boxes.rb +4 -0
- data/examples/011-text_layouter_line_wrapping.rb +4 -0
- data/examples/012-text_layouter_styling.rb +9 -4
- data/examples/013-text_layouter_shapes.rb +5 -0
- data/examples/015-boxes.rb +3 -0
- data/examples/016-frame_automatic_box_placement.rb +3 -0
- data/examples/017-frame_text_flow.rb +3 -0
- data/examples/022-outline.rb +5 -1
- data/examples/{028-frame_mask_mode.rb → 028-composer_mask_mode.rb} +3 -3
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +65 -65
- data/lib/hexapdf/cli/debug_info.rb +98 -0
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +11 -6
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +19 -4
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +24 -8
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/modify.rb +1 -2
- data/lib/hexapdf/cli/optimize.rb +6 -6
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/usage.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/cli.rb +20 -2
- data/lib/hexapdf/composer.rb +22 -1
- data/lib/hexapdf/configuration.rb +56 -1
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/content/canvas_composer.rb +1 -1
- data/lib/hexapdf/content/color_space.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphics_state.rb +2 -2
- data/lib/hexapdf/content/operator.rb +1 -1
- data/lib/hexapdf/content/parser.rb +22 -23
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +8 -2
- data/lib/hexapdf/dictionary_fields.rb +2 -2
- data/lib/hexapdf/digital_signature/cms_handler.rb +19 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +1 -1
- data/lib/hexapdf/digital_signature/signature.rb +2 -2
- data/lib/hexapdf/digital_signature/signatures.rb +1 -1
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +3 -3
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -2
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +25 -5
- data/lib/hexapdf/digital_signature/signing.rb +1 -1
- data/lib/hexapdf/digital_signature/verification_result.rb +1 -1
- data/lib/hexapdf/digital_signature.rb +1 -1
- data/lib/hexapdf/document/annotations.rb +220 -0
- data/lib/hexapdf/document/destinations.rb +1 -1
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/layout.rb +95 -16
- data/lib/hexapdf/document/metadata.rb +11 -4
- data/lib/hexapdf/document/pages.rb +1 -1
- data/lib/hexapdf/document.rb +52 -9
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/arc4.rb +3 -3
- data/lib/hexapdf/encryption/fast_aes.rb +1 -1
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +4 -2
- data/lib/hexapdf/encryption/standard_security_handler.rb +40 -29
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/error.rb +12 -4
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/crypt.rb +1 -1
- data/lib/hexapdf/filter/encryption.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +1 -1
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +59 -5
- data/lib/hexapdf/font/cmap.rb +18 -7
- data/lib/hexapdf/font/encoding/base.rb +28 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +1 -1
- data/lib/hexapdf/font/true_type/builder.rb +1 -1
- data/lib/hexapdf/font/true_type/font.rb +1 -1
- data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
- data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
- data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
- data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
- data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
- data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
- data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
- data/lib/hexapdf/font/true_type/table/name.rb +1 -1
- data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type/table.rb +7 -2
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +51 -16
- data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
- data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/font.rb +1 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
- data/lib/hexapdf/font/type1.rb +1 -1
- data/lib/hexapdf/font/type1_wrapper.rb +3 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
- data/lib/hexapdf/font_loader/from_file.rb +1 -1
- data/lib/hexapdf/font_loader/standard14.rb +1 -1
- data/lib/hexapdf/font_loader/variant_from_name.rb +1 -1
- data/lib/hexapdf/font_loader.rb +1 -1
- data/lib/hexapdf/image_loader/jpeg.rb +1 -1
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +2 -2
- data/lib/hexapdf/layout/box.rb +6 -1
- data/lib/hexapdf/layout/box_fitter.rb +1 -1
- data/lib/hexapdf/layout/column_box.rb +1 -1
- data/lib/hexapdf/layout/container_box.rb +64 -29
- data/lib/hexapdf/layout/frame.rb +1 -1
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/inline_box.rb +1 -1
- data/lib/hexapdf/layout/line.rb +1 -1
- data/lib/hexapdf/layout/list_box.rb +1 -1
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/page_style.rb +1 -1
- data/lib/hexapdf/layout/style.rb +133 -22
- data/lib/hexapdf/layout/table_box.rb +86 -14
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +13 -2
- data/lib/hexapdf/layout/text_layouter.rb +1 -1
- data/lib/hexapdf/layout/text_shaper.rb +1 -1
- data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
- data/lib/hexapdf/layout.rb +1 -1
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +4 -4
- data/lib/hexapdf/parser.rb +36 -7
- data/lib/hexapdf/pdf_array.rb +26 -4
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +2 -2
- data/lib/hexapdf/revision.rb +7 -3
- data/lib/hexapdf/revisions.rb +1 -1
- data/lib/hexapdf/serializer.rb +8 -8
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/merge_acro_form.rb +164 -0
- data/lib/hexapdf/task/optimize.rb +5 -5
- data/lib/hexapdf/task/pdfa.rb +1 -1
- data/lib/hexapdf/task.rb +2 -1
- data/lib/hexapdf/test_utils.rb +3 -2
- data/lib/hexapdf/tokenizer.rb +52 -44
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +66 -13
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +6 -2
- data/lib/hexapdf/type/acro_form/form.rb +23 -32
- data/lib/hexapdf/type/acro_form/java_script_actions.rb +10 -3
- data/lib/hexapdf/type/acro_form/signature_field.rb +19 -8
- data/lib/hexapdf/type/acro_form/text_field.rb +10 -3
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +13 -5
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +2 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +2 -1
- data/lib/hexapdf/type/actions/launch.rb +6 -2
- data/lib/hexapdf/type/actions/set_ocg_state.rb +1 -1
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +78 -3
- data/lib/hexapdf/type/annotations/appearance_generator.rb +426 -0
- data/lib/hexapdf/type/annotations/border_effect.rb +99 -0
- data/lib/hexapdf/type/annotations/border_styling.rb +160 -0
- data/lib/hexapdf/type/annotations/circle.rb +65 -0
- data/lib/hexapdf/type/annotations/interior_color.rb +84 -0
- data/lib/hexapdf/type/annotations/line.rb +334 -0
- data/lib/hexapdf/type/annotations/line_ending_styling.rb +208 -0
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +15 -3
- data/lib/hexapdf/type/annotations/polygon.rb +64 -0
- data/lib/hexapdf/type/annotations/polygon_polyline.rb +109 -0
- data/lib/hexapdf/type/annotations/polyline.rb +64 -0
- data/lib/hexapdf/type/annotations/square.rb +65 -0
- data/lib/hexapdf/type/annotations/square_circle.rb +77 -0
- data/lib/hexapdf/type/annotations/text.rb +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +56 -118
- data/lib/hexapdf/type/annotations.rb +13 -1
- data/lib/hexapdf/type/catalog.rb +5 -2
- data/lib/hexapdf/type/cid_font.rb +6 -3
- data/lib/hexapdf/type/cmap.rb +58 -0
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +18 -15
- data/lib/hexapdf/type/font.rb +1 -1
- data/lib/hexapdf/type/font_descriptor.rb +5 -4
- data/lib/hexapdf/type/font_simple.rb +4 -2
- data/lib/hexapdf/type/font_true_type.rb +3 -1
- data/lib/hexapdf/type/font_type0.rb +2 -2
- data/lib/hexapdf/type/font_type1.rb +19 -1
- data/lib/hexapdf/type/font_type3.rb +1 -2
- data/lib/hexapdf/type/form.rb +8 -5
- data/lib/hexapdf/type/graphics_state_parameter.rb +8 -5
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +9 -5
- data/lib/hexapdf/type/info.rb +3 -3
- data/lib/hexapdf/type/mark_information.rb +3 -3
- data/lib/hexapdf/type/marked_content_reference.rb +59 -0
- data/lib/hexapdf/type/measure.rb +57 -0
- data/lib/hexapdf/type/metadata.rb +1 -1
- data/lib/hexapdf/type/names.rb +1 -1
- data/lib/hexapdf/type/namespace.rb +57 -0
- data/lib/hexapdf/type/object_reference.rb +57 -0
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/optional_content_configuration.rb +2 -2
- data/lib/hexapdf/type/optional_content_group.rb +1 -1
- data/lib/hexapdf/type/optional_content_membership.rb +2 -2
- data/lib/hexapdf/type/optional_content_properties.rb +1 -1
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/output_intent.rb +1 -1
- data/lib/hexapdf/type/page.rb +6 -4
- data/lib/hexapdf/type/page_label.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +13 -9
- data/lib/hexapdf/type/struct_elem.rb +72 -0
- data/lib/hexapdf/type/struct_tree_root.rb +64 -0
- data/lib/hexapdf/type/trailer.rb +1 -1
- data/lib/hexapdf/type/viewer_preferences.rb +5 -4
- data/lib/hexapdf/type/xref_stream.rb +1 -1
- data/lib/hexapdf/type.rb +8 -1
- data/lib/hexapdf/utils/bit_field.rb +1 -1
- data/lib/hexapdf/utils/bit_stream.rb +1 -1
- data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
- data/lib/hexapdf/utils/lru_cache.rb +1 -1
- data/lib/hexapdf/utils/math_helpers.rb +1 -1
- data/lib/hexapdf/utils/object_hash.rb +1 -1
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/utils/sorted_tree_node.rb +17 -4
- data/lib/hexapdf/utils.rb +1 -1
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +3 -2
- data/lib/hexapdf/xref_section.rb +25 -6
- data/lib/hexapdf.rb +1 -1
- data/test/data/standard-security-handler/bothpwd-aes-256bit-V5-R5.pdf +43 -0
- data/test/data/standard-security-handler/nopwd-aes-256bit-V5-R5.pdf +44 -0
- data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5-R5.pdf +43 -0
- data/test/data/standard-security-handler/userpwd-aes-256bit-V5-R5.pdf +0 -0
- data/test/hexapdf/common_tokenizer_tests.rb +7 -7
- data/test/hexapdf/content/test_graphics_state.rb +2 -3
- data/test/hexapdf/content/test_operator.rb +4 -5
- data/test/hexapdf/digital_signature/common.rb +6 -1
- data/test/hexapdf/digital_signature/signing/test_default_handler.rb +6 -1
- data/test/hexapdf/digital_signature/signing/test_timestamp_handler.rb +12 -0
- data/test/hexapdf/digital_signature/test_cms_handler.rb +25 -15
- data/test/hexapdf/digital_signature/test_handler.rb +2 -3
- data/test/hexapdf/digital_signature/test_pkcs1_handler.rb +1 -2
- data/test/hexapdf/digital_signature/test_signature.rb +7 -0
- data/test/hexapdf/digital_signature/test_signatures.rb +12 -7
- data/test/hexapdf/document/test_annotations.rb +75 -0
- data/test/hexapdf/document/test_layout.rb +38 -10
- data/test/hexapdf/document/test_metadata.rb +13 -1
- data/test/hexapdf/encryption/common.rb +1 -1
- data/test/hexapdf/encryption/test_aes.rb +1 -1
- data/test/hexapdf/encryption/test_arc4.rb +2 -2
- data/test/hexapdf/encryption/test_security_handler.rb +8 -6
- data/test/hexapdf/encryption/test_standard_security_handler.rb +7 -3
- data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
- data/test/hexapdf/filter/test_flate_decode.rb +2 -3
- data/test/hexapdf/font/cmap/test_writer.rb +73 -16
- data/test/hexapdf/font/encoding/test_base.rb +20 -0
- data/test/hexapdf/font/encoding/test_glyph_list.rb +1 -1
- data/test/hexapdf/font/test_true_type_wrapper.rb +31 -5
- data/test/hexapdf/font/test_type1_wrapper.rb +8 -1
- data/test/hexapdf/font/true_type/test_table.rb +12 -0
- data/test/hexapdf/layout/test_box.rb +8 -2
- data/test/hexapdf/layout/test_container_box.rb +34 -6
- data/test/hexapdf/layout/test_list_box.rb +7 -7
- data/test/hexapdf/layout/test_page_style.rb +1 -1
- data/test/hexapdf/layout/test_style.rb +46 -12
- data/test/hexapdf/layout/test_table_box.rb +66 -16
- data/test/hexapdf/layout/test_text_box.rb +0 -6
- data/test/hexapdf/layout/test_text_fragment.rb +3 -3
- data/test/hexapdf/layout/test_text_layouter.rb +4 -2
- data/test/hexapdf/task/test_merge_acro_form.rb +104 -0
- data/test/hexapdf/task/test_optimize.rb +3 -1
- data/test/hexapdf/test_composer.rb +15 -0
- data/test/hexapdf/test_dictionary.rb +15 -0
- data/test/hexapdf/test_dictionary_fields.rb +1 -0
- data/test/hexapdf/test_document.rb +26 -8
- data/test/hexapdf/test_filter.rb +1 -1
- data/test/hexapdf/test_importer.rb +7 -0
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_parser.rb +87 -18
- data/test/hexapdf/test_pdf_array.rb +36 -3
- data/test/hexapdf/test_revision.rb +27 -6
- data/test/hexapdf/test_revisions.rb +1 -1
- data/test/hexapdf/test_serializer.rb +4 -4
- data/test/hexapdf/test_stream.rb +1 -2
- data/test/hexapdf/test_tokenizer.rb +1 -1
- data/test/hexapdf/test_writer.rb +22 -8
- data/test/hexapdf/test_xref_section.rb +15 -0
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +118 -26
- data/test/hexapdf/type/acro_form/test_button_field.rb +7 -6
- data/test/hexapdf/type/acro_form/test_field.rb +10 -0
- data/test/hexapdf/type/acro_form/test_form.rb +32 -9
- data/test/hexapdf/type/acro_form/test_java_script_actions.rb +21 -0
- data/test/hexapdf/type/acro_form/test_signature_field.rb +3 -1
- data/test/hexapdf/type/acro_form/test_text_field.rb +7 -1
- data/test/hexapdf/type/acro_form/test_variable_text_field.rb +14 -1
- data/test/hexapdf/type/actions/test_launch.rb +6 -2
- data/test/hexapdf/type/annotations/test_appearance_generator.rb +608 -0
- data/test/hexapdf/type/annotations/test_border_effect.rb +59 -0
- data/test/hexapdf/type/annotations/test_border_styling.rb +114 -0
- data/test/hexapdf/type/annotations/test_interior_color.rb +37 -0
- data/test/hexapdf/type/annotations/test_line.rb +144 -0
- data/test/hexapdf/type/annotations/test_line_ending_styling.rb +42 -0
- data/test/hexapdf/type/annotations/test_polygon_polyline.rb +29 -0
- data/test/hexapdf/type/annotations/test_widget.rb +47 -81
- data/test/hexapdf/type/test_annotation.rb +58 -0
- data/test/hexapdf/type/test_font_type1.rb +20 -1
- data/test/hexapdf/type/test_form.rb +7 -1
- data/test/hexapdf/type/test_image.rb +1 -1
- data/test/hexapdf/type/test_page.rb +7 -1
- data/test/hexapdf/type/test_page_tree_node.rb +2 -2
- data/test/hexapdf/type/test_resources.rb +3 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +18 -7
- data/test/test_helper.rb +7 -0
- metadata +69 -9
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -53,8 +53,8 @@ module HexaPDF
|
|
|
53
53
|
# == Usage
|
|
54
54
|
#
|
|
55
55
|
# It is necessary to provide at least the URL of the timestamp authority server (TSA) via
|
|
56
|
-
# #tsa_url, everything else is optional and uses default values. The TSA server
|
|
57
|
-
#
|
|
56
|
+
# #tsa_url, everything else is optional and uses default values. The TSA server can optionally
|
|
57
|
+
# use HTTP basic authentication.
|
|
58
58
|
#
|
|
59
59
|
# Example:
|
|
60
60
|
#
|
|
@@ -66,6 +66,18 @@ module HexaPDF
|
|
|
66
66
|
# This value is required.
|
|
67
67
|
attr_accessor :tsa_url
|
|
68
68
|
|
|
69
|
+
# The username for basic authentication to the TSA server.
|
|
70
|
+
#
|
|
71
|
+
# If the username is not set, no basic authentication is done.
|
|
72
|
+
#
|
|
73
|
+
# See: #tsa_password
|
|
74
|
+
attr_accessor :tsa_username
|
|
75
|
+
|
|
76
|
+
# The password for basic authentication to the TSA server.
|
|
77
|
+
#
|
|
78
|
+
# See: #tsa_username
|
|
79
|
+
attr_accessor :tsa_password
|
|
80
|
+
|
|
69
81
|
# The hash algorithm to use for timestamping. Defaults to SHA512.
|
|
70
82
|
attr_accessor :tsa_hash_algorithm
|
|
71
83
|
|
|
@@ -127,8 +139,14 @@ module HexaPDF
|
|
|
127
139
|
req.message_imprint = digest.digest
|
|
128
140
|
req.policy_id = tsa_policy_id if tsa_policy_id
|
|
129
141
|
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
url = URI(tsa_url)
|
|
143
|
+
http_request = Net::HTTP::Post.new(url, 'Content-Type' => 'application/timestamp-query')
|
|
144
|
+
http_request.body = req.to_der
|
|
145
|
+
http_request.basic_auth(tsa_username, tsa_password) if tsa_username
|
|
146
|
+
http_response = Net::HTTP.start(url.hostname, url.port, use_ssl: (url.scheme == 'https')) do |http|
|
|
147
|
+
http.request(http_request)
|
|
148
|
+
end
|
|
149
|
+
|
|
132
150
|
if http_response.kind_of?(Net::HTTPOK)
|
|
133
151
|
response = OpenSSL::Timestamp::Response.new(http_response.body)
|
|
134
152
|
if response.status == 0
|
|
@@ -136,6 +154,8 @@ module HexaPDF
|
|
|
136
154
|
else
|
|
137
155
|
raise HexaPDF::Error, "Timestamp token could not be created: #{response.failure_info}"
|
|
138
156
|
end
|
|
157
|
+
elsif http_response.kind_of?(Net::HTTPUnauthorized)
|
|
158
|
+
raise HexaPDF::Error, "Basic authentication to the server failed: #{http_response.body}"
|
|
139
159
|
else
|
|
140
160
|
raise HexaPDF::Error, "Invalid TSA server response: #{http_response.body}"
|
|
141
161
|
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
|
+
#
|
|
3
|
+
#--
|
|
4
|
+
# This file is part of HexaPDF.
|
|
5
|
+
#
|
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
|
+
#
|
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
16
|
+
#
|
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
20
|
+
# License for more details.
|
|
21
|
+
#
|
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
|
24
|
+
#
|
|
25
|
+
# The interactive user interfaces in modified source and object code
|
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
|
28
|
+
#
|
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
|
31
|
+
# is created or manipulated using HexaPDF.
|
|
32
|
+
#
|
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
|
35
|
+
#++
|
|
36
|
+
|
|
37
|
+
require 'hexapdf/dictionary'
|
|
38
|
+
require 'hexapdf/error'
|
|
39
|
+
|
|
40
|
+
module HexaPDF
|
|
41
|
+
class Document
|
|
42
|
+
|
|
43
|
+
# This class provides methods for creating and managing the annotations of a PDF file.
|
|
44
|
+
#
|
|
45
|
+
# An annotation is an object that can be added to a certain location on a page, provides a
|
|
46
|
+
# visual appearance and allows for interaction with the user via keyboard and mouse.
|
|
47
|
+
#
|
|
48
|
+
# == Usage
|
|
49
|
+
#
|
|
50
|
+
# To create an annotation either call the general #create method or a specific creation method
|
|
51
|
+
# for an annotation type. After the annotation has been created customize it using the
|
|
52
|
+
# convenience methods on the annotation object. The last step should be the call to
|
|
53
|
+
# +regenerate_appearance+ so that the appearance is generated.
|
|
54
|
+
#
|
|
55
|
+
# See: PDF2.0 s12.5
|
|
56
|
+
class Annotations
|
|
57
|
+
|
|
58
|
+
include Enumerable
|
|
59
|
+
|
|
60
|
+
# Creates a new Annotations object for the given PDF document.
|
|
61
|
+
def initialize(document)
|
|
62
|
+
@document = document
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# :call-seq:
|
|
66
|
+
# annotations.create(type, page, **options) -> annotation
|
|
67
|
+
#
|
|
68
|
+
# Creates a new annotation object with the given +type+ and +page+ by calling the respective
|
|
69
|
+
# +create_type+ method.
|
|
70
|
+
#
|
|
71
|
+
# The +options+ are passed on the specific annotation creation method.
|
|
72
|
+
def create(type, page, *args, **options)
|
|
73
|
+
method_name = "create_#{type}"
|
|
74
|
+
unless respond_to?(method_name)
|
|
75
|
+
raise ArgumentError, "Invalid type specified"
|
|
76
|
+
end
|
|
77
|
+
send("create_#{type}", page, *args, **options)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# :call-seq:
|
|
81
|
+
# annotations.create_line(page, start_point:, end_point:) -> annotation
|
|
82
|
+
#
|
|
83
|
+
# Creates a line annotation from +start_point+ to +end_point+ on the given page and returns
|
|
84
|
+
# it.
|
|
85
|
+
#
|
|
86
|
+
# The line uses a black color and a width of 1pt. It can be further styled using the
|
|
87
|
+
# convenience methods on the returned annotation object.
|
|
88
|
+
#
|
|
89
|
+
# Example:
|
|
90
|
+
#
|
|
91
|
+
# doc.annotations.create_line(doc.pages[0], start_point: [100, 100], end_point: [130, 180]).
|
|
92
|
+
# border_style(color: "blue", width: 2).
|
|
93
|
+
# leader_line_length(10).
|
|
94
|
+
# regenerate_appearance
|
|
95
|
+
#
|
|
96
|
+
# See: Type::Annotations::Line
|
|
97
|
+
def create_line(page, start_point:, end_point:)
|
|
98
|
+
create_and_add_to_page(:Line, page).
|
|
99
|
+
line(*start_point, *end_point).
|
|
100
|
+
border_style(color: 0, width: 1)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# :call-seq:
|
|
104
|
+
# annotations.create_rectangle(page, x, y, width, height) -> annotation
|
|
105
|
+
#
|
|
106
|
+
# Creates a rectangle (called "square" in the PDF specification) annotation with the
|
|
107
|
+
# lower-left corner at (+x+, +y+) and the given +width+ and +height+.
|
|
108
|
+
#
|
|
109
|
+
# The rectangle uses a black stroke color, no interior color and a line width of 1pt by
|
|
110
|
+
# default. It can be further styled using the convenience methods on the returned annotation
|
|
111
|
+
# object.
|
|
112
|
+
#
|
|
113
|
+
# Example:
|
|
114
|
+
#
|
|
115
|
+
# #>pdf-small
|
|
116
|
+
# doc.annotations.create_rectangle(doc.pages[0], 20, 20, 20, 60).
|
|
117
|
+
# regenerate_appearance
|
|
118
|
+
#
|
|
119
|
+
# doc.annotations.create_rectangle(doc.pages[0], 60, 20, 20, 60).
|
|
120
|
+
# border_style(color: "hp-blue", width: 2).
|
|
121
|
+
# interior_color("hp-orange").
|
|
122
|
+
# regenerate_appearance
|
|
123
|
+
#
|
|
124
|
+
# See: Type::Annotations::Square
|
|
125
|
+
def create_rectangle(page, x, y, w, h)
|
|
126
|
+
annot = create_and_add_to_page(:Square, page)
|
|
127
|
+
annot[:Rect] = [x, y, x + w, y + h]
|
|
128
|
+
annot.border_style(color: 0, width: 1)
|
|
129
|
+
annot
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# :call-seq:
|
|
133
|
+
# annotations.create_ellipse(page, cx, cy, a:, b:) -> annotation
|
|
134
|
+
#
|
|
135
|
+
# Creates an ellipse (called "circle" in the PDF specification) annotation with the center
|
|
136
|
+
# point at (+cx+, +cy+), the semi-major axis +a+ and the semi-minor axis +b+.
|
|
137
|
+
#
|
|
138
|
+
# The ellipse uses a black stroke color, no interior color and a line width of 1pt by
|
|
139
|
+
# default. It can be further styled using the convenience methods on the returned annotation
|
|
140
|
+
# object.
|
|
141
|
+
#
|
|
142
|
+
# Example:
|
|
143
|
+
#
|
|
144
|
+
# #>pdf-small
|
|
145
|
+
# doc.annotations.create_ellipse(doc.pages[0], 30, 50, a: 15, b: 20).
|
|
146
|
+
# regenerate_appearance
|
|
147
|
+
#
|
|
148
|
+
# doc.annotations.create_ellipse(doc.pages[0], 70, 50, a: 15, b: 20).
|
|
149
|
+
# border_style(color: "hp-blue", width: 2).
|
|
150
|
+
# interior_color("hp-orange").
|
|
151
|
+
# regenerate_appearance
|
|
152
|
+
#
|
|
153
|
+
# See: Type::Annotations::Circle
|
|
154
|
+
def create_ellipse(page, x, y, a:, b:)
|
|
155
|
+
annot = create_and_add_to_page(:Circle, page)
|
|
156
|
+
annot[:Rect] = [x - a, y - b, x + a, y + b]
|
|
157
|
+
annot.border_style(color: 0, width: 1)
|
|
158
|
+
annot
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# :call-seq:
|
|
162
|
+
# annotations.create_polyline(page, *points) -> annotation
|
|
163
|
+
#
|
|
164
|
+
# Creates a polyline annotation for the given +points+ (alternating horizontal and vertical
|
|
165
|
+
# coordinates) on the given page and returns it.
|
|
166
|
+
#
|
|
167
|
+
# The polyline uses a black color and a width of 1pt. It can be further styled using the
|
|
168
|
+
# convenience methods on the returned annotation object.
|
|
169
|
+
#
|
|
170
|
+
# Example:
|
|
171
|
+
#
|
|
172
|
+
# #>pdf-small
|
|
173
|
+
# doc.annotations.create_polyline(doc.pages[0], 20, 20, 30, 70, 80, 60, 40, 30).
|
|
174
|
+
# border_style(color: "hp-blue", width: 2, style: [3, 1]).
|
|
175
|
+
# regenerate_appearance
|
|
176
|
+
#
|
|
177
|
+
# See: Type::Annotations::Polyline
|
|
178
|
+
def create_polyline(page, *points)
|
|
179
|
+
create_and_add_to_page(:PolyLine, page).
|
|
180
|
+
vertices(*points).
|
|
181
|
+
border_style(color: 0, width: 1)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# :call-seq:
|
|
185
|
+
# annotations.create_polygon(page, *points) -> annotation
|
|
186
|
+
#
|
|
187
|
+
# Creates a polygon annotation for the given +points+ (alternating horizontal and vertical
|
|
188
|
+
# coordinates) on the given page and returns it.
|
|
189
|
+
#
|
|
190
|
+
# The polygon uses a black color and a width of 1pt for the border and no interior color. It
|
|
191
|
+
# can be further styled using the convenience methods on the returned annotation object.
|
|
192
|
+
#
|
|
193
|
+
# Example:
|
|
194
|
+
#
|
|
195
|
+
# #>pdf-small
|
|
196
|
+
# doc.annotations.create_polygon(doc.pages[0], 20, 20, 30, 70, 80, 60, 40, 30).
|
|
197
|
+
# border_style(color: "hp-blue", width: 2, style: [3, 1]).
|
|
198
|
+
# interior_color("hp-orange").
|
|
199
|
+
# regenerate_appearance
|
|
200
|
+
#
|
|
201
|
+
# See: Type::Annotations::Polygon
|
|
202
|
+
def create_polygon(page, *points)
|
|
203
|
+
create_and_add_to_page(:Polygon, page).
|
|
204
|
+
vertices(*points).
|
|
205
|
+
border_style(color: 0, width: 1)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
|
|
210
|
+
# Returns the root of the destinations name tree.
|
|
211
|
+
def create_and_add_to_page(subtype, page)
|
|
212
|
+
annot = @document.add({Type: :Annot, Subtype: subtype})
|
|
213
|
+
(page[:Annots] ||= []) << annot
|
|
214
|
+
annot
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -92,13 +92,23 @@ module HexaPDF
|
|
|
92
92
|
#
|
|
93
93
|
# style.font = ['Helvetica', variant: :bold]
|
|
94
94
|
#
|
|
95
|
-
# Helvetica in bold could also be set the
|
|
95
|
+
# Helvetica in bold could also be set in the following ways:
|
|
96
96
|
#
|
|
97
97
|
# style.font = 'Helvetica bold'
|
|
98
|
+
# # or
|
|
99
|
+
# style.font_bold = true
|
|
100
|
+
# style.font = 'Helvetica'
|
|
101
|
+
#
|
|
102
|
+
# The font_bold and font_italic style properties are always taken into account. For example,
|
|
103
|
+
# if the font is set to 'Helvetica italic' and font_bold to +true+, the actual font would be
|
|
104
|
+
# the bold _and_ italic Helvetica font.
|
|
98
105
|
#
|
|
99
106
|
# However, using an array it is also possible to specify other options when setting a font,
|
|
100
107
|
# like the :subset option.
|
|
101
108
|
#
|
|
109
|
+
# * It is possible to resolve the font of a style object manually by using the #resolve_font
|
|
110
|
+
# method.
|
|
111
|
+
#
|
|
102
112
|
class Layout
|
|
103
113
|
|
|
104
114
|
# This class is used when a box can contain child boxes and the creation of such boxes should
|
|
@@ -218,6 +228,77 @@ module HexaPDF
|
|
|
218
228
|
style
|
|
219
229
|
end
|
|
220
230
|
|
|
231
|
+
# Returns +true+ if a style with the given +name+ exists, else +false+.
|
|
232
|
+
#
|
|
233
|
+
# Example:
|
|
234
|
+
#
|
|
235
|
+
# layout.style(:header, font: 'Helvetica')
|
|
236
|
+
# layout.style?(:header) # => true
|
|
237
|
+
# layout.style?(:paragraph) # => false
|
|
238
|
+
#
|
|
239
|
+
# See: #style
|
|
240
|
+
def style?(name)
|
|
241
|
+
@styles.key?(name)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
FONT_BOLD_VARIANT_MAPPER = { #:nodoc:
|
|
245
|
+
nil => {true => :bold, false: :none},
|
|
246
|
+
none: {true => :bold, false: :none},
|
|
247
|
+
bold: {true => :bold, false: :none},
|
|
248
|
+
italic: {true => :bold_italic, false: :italic},
|
|
249
|
+
bold_italic: {true => :bold_italic, false: :italic},
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
FONT_ITALIC_VARIANT_MAPPER = { #:nodoc:
|
|
253
|
+
nil => {true => :italic, false: :none},
|
|
254
|
+
none: {true => :italic, false: :none},
|
|
255
|
+
italic: {true => :italic, false: :none},
|
|
256
|
+
bold: {true => :bold_italic, false: :bold},
|
|
257
|
+
bold_italic: {true => :bold_italic, false: :bold},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
# Resolves the font object for the given +style+ and applies the result to it.
|
|
261
|
+
#
|
|
262
|
+
# The Layout::Style#font property is the only one without a default value but is needed for
|
|
263
|
+
# many operations. This method ensures that the +style+ has a valid font object for the font
|
|
264
|
+
# property by resolving the font name.
|
|
265
|
+
#
|
|
266
|
+
# The font object is resolved in the following way:
|
|
267
|
+
#
|
|
268
|
+
# * If the font property is not set, the font value of the :base style is used and if that is
|
|
269
|
+
# also not set, the 'font.default' configuration value is used.
|
|
270
|
+
#
|
|
271
|
+
# * Afterwards, if the font property is a valid font object, nothing needs to be done.
|
|
272
|
+
#
|
|
273
|
+
# * Otherwise, if the font property is a single font name or a [font name, options hash]
|
|
274
|
+
# array, it is resolved to a font object, also taking the font_bold and font_italic style
|
|
275
|
+
# properties into account.
|
|
276
|
+
#
|
|
277
|
+
# Example:
|
|
278
|
+
#
|
|
279
|
+
# style = layout.style(:header, font: 'Helvetica')
|
|
280
|
+
# style.font # => 'Helvetica'
|
|
281
|
+
# layout.resolve_font(style)
|
|
282
|
+
# style.font # => #<HexaPDF::Font::Type1Wrapper>
|
|
283
|
+
#
|
|
284
|
+
# See: The "Box Styles" section in Layout for more details.
|
|
285
|
+
def resolve_font(style)
|
|
286
|
+
unless style.font?
|
|
287
|
+
style.font(@styles[:base].font? && @styles[:base].font || @document.config['font.default'])
|
|
288
|
+
end
|
|
289
|
+
unless style.font.respond_to?(:pdf_object)
|
|
290
|
+
name, options = *style.font
|
|
291
|
+
options ||= {}
|
|
292
|
+
if style.font_bold?
|
|
293
|
+
options[:variant] = FONT_BOLD_VARIANT_MAPPER.dig(options[:variant], style.font_bold)
|
|
294
|
+
end
|
|
295
|
+
if style.font_italic?
|
|
296
|
+
options[:variant] = FONT_ITALIC_VARIANT_MAPPER.dig(options[:variant], style.font_italic)
|
|
297
|
+
end
|
|
298
|
+
style.font(@document.fonts.add(name, **options))
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
221
302
|
# :call-seq:
|
|
222
303
|
# layout.styles -> styles
|
|
223
304
|
# layout.styles(**mapping) -> styles
|
|
@@ -286,8 +367,9 @@ module HexaPDF
|
|
|
286
367
|
box_options[:children] = ChildrenCollector.collect(self, &block)
|
|
287
368
|
end
|
|
288
369
|
end
|
|
370
|
+
style = retrieve_style(style)
|
|
289
371
|
box_class_for_name(name).new(width: width, height: height,
|
|
290
|
-
style:
|
|
372
|
+
style: style, **style.box_options, **box_options, &box_block)
|
|
291
373
|
end
|
|
292
374
|
|
|
293
375
|
# Creates an array of HexaPDF::Layout::TextFragment objects for the given +text+.
|
|
@@ -354,7 +436,7 @@ module HexaPDF
|
|
|
354
436
|
box_style = (box_style ? retrieve_style(box_style) : style)
|
|
355
437
|
box_class_for_name(:text).new(items: text_fragments(text, style: style),
|
|
356
438
|
width: width, height: height, properties: properties,
|
|
357
|
-
style: box_style)
|
|
439
|
+
style: box_style, **box_style.box_options)
|
|
358
440
|
end
|
|
359
441
|
alias text text_box
|
|
360
442
|
|
|
@@ -457,7 +539,8 @@ module HexaPDF
|
|
|
457
539
|
end
|
|
458
540
|
end
|
|
459
541
|
box_class_for_name(:text).new(items: data, width: width, height: height,
|
|
460
|
-
properties: properties, style: box_style
|
|
542
|
+
properties: properties, style: box_style,
|
|
543
|
+
**box_style.box_options)
|
|
461
544
|
end
|
|
462
545
|
alias formatted_text formatted_text_box
|
|
463
546
|
|
|
@@ -479,7 +562,7 @@ module HexaPDF
|
|
|
479
562
|
style = retrieve_style(style, style_properties)
|
|
480
563
|
image = file.kind_of?(HexaPDF::Stream) ? file : @document.images.add(file)
|
|
481
564
|
box_class_for_name(:image).new(image: image, width: width, height: height,
|
|
482
|
-
properties: properties, style: style)
|
|
565
|
+
properties: properties, style: style, **style.box_options)
|
|
483
566
|
end
|
|
484
567
|
alias image image_box
|
|
485
568
|
|
|
@@ -533,9 +616,10 @@ module HexaPDF
|
|
|
533
616
|
@argument_infos.each_with_object({}) do |arg_info, result|
|
|
534
617
|
next unless arg_info.rows.include?(row) && arg_info.cols.include?(col)
|
|
535
618
|
if arg_info.args[:cell]
|
|
536
|
-
arg_info.args
|
|
619
|
+
result.update(arg_info.args, cell: (result[:cell] || {}).merge(arg_info.args[:cell]))
|
|
620
|
+
else
|
|
621
|
+
result.update(arg_info.args)
|
|
537
622
|
end
|
|
538
|
-
result.update(arg_info.args)
|
|
539
623
|
end
|
|
540
624
|
end
|
|
541
625
|
|
|
@@ -608,7 +692,8 @@ module HexaPDF
|
|
|
608
692
|
end
|
|
609
693
|
box_class_for_name(:table).new(cells: cells, column_widths: column_widths, header: header,
|
|
610
694
|
footer: footer, cell_style: cell_style, width: width,
|
|
611
|
-
height: height, properties: properties, style: style
|
|
695
|
+
height: height, properties: properties, style: style,
|
|
696
|
+
**style.box_options)
|
|
612
697
|
end
|
|
613
698
|
alias table table_box
|
|
614
699
|
|
|
@@ -685,13 +770,7 @@ module HexaPDF
|
|
|
685
770
|
end
|
|
686
771
|
style = HexaPDF::Layout::Style.create(@styles[style] || style || @styles[:base])
|
|
687
772
|
style = style.dup.update(**properties) unless properties.nil? || properties.empty?
|
|
688
|
-
|
|
689
|
-
style.font(@styles[:base].font? && @styles[:base].font || @document.config['font.default'])
|
|
690
|
-
end
|
|
691
|
-
unless style.font.respond_to?(:pdf_object)
|
|
692
|
-
name, options = *style.font
|
|
693
|
-
style.font(@document.fonts.add(name, **(options || {})))
|
|
694
|
-
end
|
|
773
|
+
resolve_font(style)
|
|
695
774
|
style
|
|
696
775
|
end
|
|
697
776
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -430,8 +430,12 @@ module HexaPDF
|
|
|
430
430
|
@metadata[ns_dc]['creator'] = info_dict[:Author] if info_dict.key?(:Author)
|
|
431
431
|
@metadata[ns_dc]['description'] = info_dict[:Subject] if info_dict.key?(:Subject)
|
|
432
432
|
@metadata[ns_xmp]['CreatorTool'] = info_dict[:Creator] if info_dict.key?(:Creator)
|
|
433
|
-
|
|
434
|
-
|
|
433
|
+
if info_dict.key?(:CreationDate) && !info_dict[:CreationDate].kind_of?(String)
|
|
434
|
+
@metadata[ns_xmp]['CreateDate'] = info_dict[:CreationDate]
|
|
435
|
+
end
|
|
436
|
+
if info_dict.key?(:ModDate) && !info_dict[:ModDate].kind_of?(String)
|
|
437
|
+
@metadata[ns_xmp]['ModifyDate'] = info_dict[:ModDate] if info_dict.key?(:ModDate)
|
|
438
|
+
end
|
|
435
439
|
@metadata[ns_pdf]['Keywords'] = info_dict[:Keywords] if info_dict.key?(:Keywords)
|
|
436
440
|
@metadata[ns_pdf]['Producer'] = info_dict[:Producer] if info_dict.key?(:Producer)
|
|
437
441
|
if info_dict.key?(:Trapped) && info_dict[:Trapped] != :Unknown
|
|
@@ -528,7 +532,10 @@ module HexaPDF
|
|
|
528
532
|
# Formats the given date-time object (Time, Date, or DateTime) to be a valid XMP date-time
|
|
529
533
|
# value.
|
|
530
534
|
def xmp_date(date)
|
|
531
|
-
date
|
|
535
|
+
case date
|
|
536
|
+
when Time, Date, DateTime then date.strftime("%Y-%m-%dT%H:%M:%S%:z")
|
|
537
|
+
else ''
|
|
538
|
+
end
|
|
532
539
|
end
|
|
533
540
|
|
|
534
541
|
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|