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
|
@@ -0,0 +1,160 @@
|
|
|
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/type/annotation'
|
|
38
|
+
require 'hexapdf/content'
|
|
39
|
+
require 'hexapdf/serializer'
|
|
40
|
+
|
|
41
|
+
module HexaPDF
|
|
42
|
+
module Type
|
|
43
|
+
module Annotations
|
|
44
|
+
|
|
45
|
+
# This module provides a convenience method for getting and setting the border style and is
|
|
46
|
+
# included in the annotations that need it.
|
|
47
|
+
#
|
|
48
|
+
# See: PDF2.0 s12.5.4
|
|
49
|
+
module BorderStyling
|
|
50
|
+
|
|
51
|
+
# Describes the border of an annotation.
|
|
52
|
+
#
|
|
53
|
+
# The +color+ property is either +nil+ if the border is transparent or else a device color
|
|
54
|
+
# object - see HexaPDF::Content::ColorSpace.
|
|
55
|
+
#
|
|
56
|
+
# The +style+ property can be one of the following:
|
|
57
|
+
#
|
|
58
|
+
# :solid:: Solid line.
|
|
59
|
+
# :beveled:: Embossed rectangle seemingly raised above the surface of the page.
|
|
60
|
+
# :inset:: Engraved rectangle receeding into the page.
|
|
61
|
+
# :underlined:: Underlined, i.e. only the bottom border is draw.
|
|
62
|
+
# Array: Dash array describing how to dash the line.
|
|
63
|
+
BorderStyle = Struct.new(:width, :color, :style, :horizontal_corner_radius,
|
|
64
|
+
:vertical_corner_radius)
|
|
65
|
+
|
|
66
|
+
# :call-seq:
|
|
67
|
+
# annot.border_style => border_style
|
|
68
|
+
# annot.border_style(color: 0, width: 1, style: :solid) => annot
|
|
69
|
+
#
|
|
70
|
+
# Returns a BorderStyle instance representing the border style of the annotation when no
|
|
71
|
+
# argument is given. Otherwise sets the border style of the annotation and returns self.
|
|
72
|
+
#
|
|
73
|
+
# When setting a border style, arguments that are not provided will use the default: a
|
|
74
|
+
# border with a solid, black, 1pt wide line. This also means that multiple invocations will
|
|
75
|
+
# reset *all* prior values.
|
|
76
|
+
#
|
|
77
|
+
# +color+:: The color of the border. See
|
|
78
|
+
# HexaPDF::Content::ColorSpace.device_color_from_specification for information on
|
|
79
|
+
# the allowed arguments.
|
|
80
|
+
#
|
|
81
|
+
# If the special value +:transparent+ is used when setting the color, a
|
|
82
|
+
# transparent is used. A transparent border will return a +nil+ value when getting
|
|
83
|
+
# the border color.
|
|
84
|
+
#
|
|
85
|
+
# +width+:: The width of the border. If set to 0, no border is shown.
|
|
86
|
+
#
|
|
87
|
+
# +style+:: Defines how the border is drawn. can be one of the following:
|
|
88
|
+
#
|
|
89
|
+
# +:solid+:: Draws a solid border.
|
|
90
|
+
# +:beveled+:: Draws a beveled border.
|
|
91
|
+
# +:inset+:: Draws an inset border.
|
|
92
|
+
# +:underlined+:: Draws only the bottom border.
|
|
93
|
+
# Array:: An array specifying a line dash pattern (see
|
|
94
|
+
# HexaPDF::Content::LineDashPattern)
|
|
95
|
+
def border_style(color: nil, width: nil, style: nil)
|
|
96
|
+
if color || width || style
|
|
97
|
+
color = if color == :transparent
|
|
98
|
+
[]
|
|
99
|
+
else
|
|
100
|
+
Content::ColorSpace.device_color_from_specification(color || 0).components
|
|
101
|
+
end
|
|
102
|
+
width ||= 1
|
|
103
|
+
style ||= :solid
|
|
104
|
+
|
|
105
|
+
if self[:Subtype] == :Widget
|
|
106
|
+
(self[:MK] ||= {})[:BC] = color
|
|
107
|
+
else
|
|
108
|
+
self[:C] = color
|
|
109
|
+
end
|
|
110
|
+
bs = self[:BS] = {W: width}
|
|
111
|
+
case style
|
|
112
|
+
when :solid then bs[:S] = :S
|
|
113
|
+
when :beveled then bs[:S] = :B
|
|
114
|
+
when :inset then bs[:S] = :I
|
|
115
|
+
when :underlined then bs[:S] = :U
|
|
116
|
+
when Array
|
|
117
|
+
bs[:S] = :D
|
|
118
|
+
bs[:D] = style
|
|
119
|
+
else
|
|
120
|
+
raise ArgumentError, "Unknown value #{style} for style argument"
|
|
121
|
+
end
|
|
122
|
+
self
|
|
123
|
+
else
|
|
124
|
+
result = BorderStyle.new(1, nil, :solid, 0, 0)
|
|
125
|
+
bc = if self[:Subtype] == :Widget
|
|
126
|
+
(ac = self[:MK]) && (bc = ac[:BC])
|
|
127
|
+
else
|
|
128
|
+
self[:C]
|
|
129
|
+
end
|
|
130
|
+
if bc && !bc.empty?
|
|
131
|
+
result.color = Content::ColorSpace.prenormalized_device_color(bc.value)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if (bs = self[:BS])
|
|
135
|
+
result.width = bs[:W] if bs.key?(:W)
|
|
136
|
+
result.style = case bs[:S]
|
|
137
|
+
when :S then :solid
|
|
138
|
+
when :B then :beveled
|
|
139
|
+
when :I then :inset
|
|
140
|
+
when :U then :underlined
|
|
141
|
+
when :D then bs[:D].value
|
|
142
|
+
else :solid
|
|
143
|
+
end
|
|
144
|
+
elsif key?(:Border)
|
|
145
|
+
border = self[:Border]
|
|
146
|
+
result.horizontal_corner_radius = border[0]
|
|
147
|
+
result.vertical_corner_radius = border[1]
|
|
148
|
+
result.width = border[2]
|
|
149
|
+
result.style = border[3] if border[3]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
result
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
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/type/annotations'
|
|
38
|
+
|
|
39
|
+
module HexaPDF
|
|
40
|
+
module Type
|
|
41
|
+
module Annotations
|
|
42
|
+
|
|
43
|
+
# A circle annotation displays an ellipse inside the annotation rectangle (the "circle" name
|
|
44
|
+
# defined by the PDF specification is a bit misleading).
|
|
45
|
+
#
|
|
46
|
+
# Also see SquareCircle for more information.
|
|
47
|
+
#
|
|
48
|
+
# Example:
|
|
49
|
+
#
|
|
50
|
+
# #>pdf-small
|
|
51
|
+
# doc.annotations.create_ellipse(doc.pages[0], 50, 50, a: 30, b: 20).
|
|
52
|
+
# border_style(color: "hp-blue", width: 2, style: [3, 1]).
|
|
53
|
+
# interior_color("hp-orange").
|
|
54
|
+
# regenerate_appearance
|
|
55
|
+
#
|
|
56
|
+
# See: PDF2.0 s12.5.6.8, HexaPDF::Type::Annotations::SquareCircle,
|
|
57
|
+
class Circle < SquareCircle
|
|
58
|
+
|
|
59
|
+
define_field :Subtype, type: Symbol, required: true, default: :Circle
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
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/type/annotations'
|
|
38
|
+
|
|
39
|
+
module HexaPDF
|
|
40
|
+
module Type
|
|
41
|
+
module Annotations
|
|
42
|
+
|
|
43
|
+
# This module provides a convenience method for getting and setting the interior color for
|
|
44
|
+
# various annotations.
|
|
45
|
+
#
|
|
46
|
+
# See: PDF2.0 s12.5
|
|
47
|
+
module InteriorColor
|
|
48
|
+
|
|
49
|
+
# :call-seq:
|
|
50
|
+
# line.interior_color => color or nil
|
|
51
|
+
# line.interior_color(*color) => line
|
|
52
|
+
#
|
|
53
|
+
# Returns the interior color or +nil+ (in case the interior color should be transparent)
|
|
54
|
+
# when no argument is given. Otherwise sets the interior color and returns self.
|
|
55
|
+
#
|
|
56
|
+
# How the interior color is used depends on the concrete annotation type. For line
|
|
57
|
+
# annotations, for example, it is the color to fill the line endings
|
|
58
|
+
#
|
|
59
|
+
# +color+:: The interior color. See
|
|
60
|
+
# HexaPDF::Content::ColorSpace.device_color_from_specification for information on
|
|
61
|
+
# the allowed arguments.
|
|
62
|
+
#
|
|
63
|
+
# If the special value +:transparent+ is used when setting the color, no color is
|
|
64
|
+
# used for filling.
|
|
65
|
+
def interior_color(*color)
|
|
66
|
+
if color.empty?
|
|
67
|
+
color = self[:IC]
|
|
68
|
+
color && !color.empty? ? Content::ColorSpace.prenormalized_device_color(color.value) : nil
|
|
69
|
+
else
|
|
70
|
+
color = if color.length == 1 && color.first == :transparent
|
|
71
|
+
[]
|
|
72
|
+
else
|
|
73
|
+
Content::ColorSpace.device_color_from_specification(color).components
|
|
74
|
+
end
|
|
75
|
+
self[:IC] = color
|
|
76
|
+
self
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,334 @@
|
|
|
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/type/annotation'
|
|
38
|
+
|
|
39
|
+
module HexaPDF
|
|
40
|
+
module Type
|
|
41
|
+
module Annotations
|
|
42
|
+
|
|
43
|
+
# A line annotation is a markup annotation that displays a single straight line.
|
|
44
|
+
#
|
|
45
|
+
# The style of the line annotation, like adding leader lines, changing the colors and so on,
|
|
46
|
+
# can be customized using the provided convenience methods and those from the included
|
|
47
|
+
# modules.
|
|
48
|
+
#
|
|
49
|
+
# Note that while BorderStyling#border_style allows special styling of the line (like
|
|
50
|
+
# :beveled), only a simple line dash pattern is supported by the line annotation.
|
|
51
|
+
#
|
|
52
|
+
# Example:
|
|
53
|
+
#
|
|
54
|
+
# #>pdf-small
|
|
55
|
+
# doc.annotations.create_line(doc.pages[0], start_point: [30, 20], end_point: [90, 60]).
|
|
56
|
+
# border_style(color: "hp-blue", width: 2, style: [3, 1]).
|
|
57
|
+
# leader_line_length(15).
|
|
58
|
+
# leader_line_extension_length(10).
|
|
59
|
+
# leader_line_offset(5).
|
|
60
|
+
# interior_color("hp-orange").
|
|
61
|
+
# line_ending_style(start_style: :circle, end_style: :open_arrow).
|
|
62
|
+
# captioned(true).
|
|
63
|
+
# contents("Caption").
|
|
64
|
+
# caption_position(:top).
|
|
65
|
+
# caption_offset(0, 5).
|
|
66
|
+
# regenerate_appearance
|
|
67
|
+
# canvas.line(30, 20, 90, 60).stroke
|
|
68
|
+
#
|
|
69
|
+
# See: PDF2.0 s12.5.6.7, HexaPDF::Type::MarkupAnnotation
|
|
70
|
+
class Line < MarkupAnnotation
|
|
71
|
+
|
|
72
|
+
include BorderStyling
|
|
73
|
+
include InteriorColor
|
|
74
|
+
include LineEndingStyling
|
|
75
|
+
|
|
76
|
+
define_field :Subtype, type: Symbol, required: true, default: :Line
|
|
77
|
+
define_field :L, type: PDFArray, required: true
|
|
78
|
+
define_field :BS, type: :Border
|
|
79
|
+
define_field :LE, type: PDFArray, default: [:None, :None], version: '1.4'
|
|
80
|
+
define_field :IC, type: PDFArray, version: '1.4'
|
|
81
|
+
define_field :LL, type: Numeric, default: 0, version: '1.6'
|
|
82
|
+
define_field :LLE, type: Numeric, default: 0, version: '1.6'
|
|
83
|
+
define_field :Cap, type: Boolean, default: false, version: '1.6'
|
|
84
|
+
define_field :IT, type: Symbol, version: '1.6',
|
|
85
|
+
allowed_values: [:LineArrow, :LineDimension]
|
|
86
|
+
define_field :LLO, type: Numeric, version: '1.7'
|
|
87
|
+
define_field :CP, type: Symbol, default: :Inline, version: '1.7',
|
|
88
|
+
allowed_values: [:Inline, :Top]
|
|
89
|
+
define_field :Measure, type: Dictionary, version: '1.7'
|
|
90
|
+
define_field :CO, type: PDFArray, default: [0, 0], version: '1.7'
|
|
91
|
+
|
|
92
|
+
# :call-seq:
|
|
93
|
+
# line.line => [x0, y0, x1, y1]
|
|
94
|
+
# line.line(x0, y0, x1, y1) => line
|
|
95
|
+
#
|
|
96
|
+
# Returns the start point and end point of the line as an array of four numbers [x0, y0, x1,
|
|
97
|
+
# y1] when no argument is given. Otherwise sets the start and end point of the line and
|
|
98
|
+
# returns self.
|
|
99
|
+
#
|
|
100
|
+
# This is the only required setting for a line annotation. Note, however, that without
|
|
101
|
+
# setting an appropriate color through #border_style the line will be transparent.
|
|
102
|
+
#
|
|
103
|
+
# Example:
|
|
104
|
+
#
|
|
105
|
+
# #>pdf-small
|
|
106
|
+
# doc.annotations.
|
|
107
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
108
|
+
# regenerate_appearance
|
|
109
|
+
def line(x0 = nil, y0 = nil, x1 = nil, y1 = nil)
|
|
110
|
+
if x0.nil? && y0.nil? && x1.nil? && y1.nil?
|
|
111
|
+
self[:L].to_ary
|
|
112
|
+
elsif !x0 || !y0 || !x1 || !y1
|
|
113
|
+
raise ArgumentError, "All four arguments x0, y0, x1, y1 must be provided"
|
|
114
|
+
else
|
|
115
|
+
self[:L] = [x0, y0, x1, y1]
|
|
116
|
+
self
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# :call-seq:
|
|
121
|
+
# line.leader_line_length => leader_line_length
|
|
122
|
+
# line.leader_line_length(length) => line
|
|
123
|
+
#
|
|
124
|
+
# Returns the leader line length when no argument is given. Otherwise sets the leader line
|
|
125
|
+
# length and returns self.
|
|
126
|
+
#
|
|
127
|
+
# Leader lines extend from the line's end points perpendicular to the line. If the length
|
|
128
|
+
# value is positive, the leader lines appear in the clockwise direction, otherwise in the
|
|
129
|
+
# opposite direction.
|
|
130
|
+
#
|
|
131
|
+
# Note: The "line's end points" mean the actually drawn line and not the one specified with
|
|
132
|
+
# #line as those two are different when leader lines are involved.
|
|
133
|
+
#
|
|
134
|
+
# A value of zero means that no leader lines are used.
|
|
135
|
+
#
|
|
136
|
+
# Example:
|
|
137
|
+
#
|
|
138
|
+
# #>pdf-small
|
|
139
|
+
# doc.annotations.
|
|
140
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
141
|
+
# leader_line_length(15).
|
|
142
|
+
# regenerate_appearance
|
|
143
|
+
# canvas.stroke_color("hp-orange").line(20, 20, 80, 60).stroke
|
|
144
|
+
#
|
|
145
|
+
# Also see: #leader_line_extension_length, #leader_line_offset
|
|
146
|
+
def leader_line_length(length = nil)
|
|
147
|
+
length ? (self[:LL] = length; self) : self[:LL]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# :call-seq:
|
|
151
|
+
# line.leader_line_extension_length => leader_line_extension_length
|
|
152
|
+
# line.leader_line_extension_length(length) => line
|
|
153
|
+
#
|
|
154
|
+
# Returns the leader line extension length when no argument is given. Otherwise sets the
|
|
155
|
+
# leader line extension length and returns self.
|
|
156
|
+
#
|
|
157
|
+
# Leader line extensions extend from the line into the opposite direction of the leader
|
|
158
|
+
# lines.
|
|
159
|
+
#
|
|
160
|
+
# The argument +length+ must be non-negative.
|
|
161
|
+
#
|
|
162
|
+
# If the leader line extension length is set to a positive value, the leader line length
|
|
163
|
+
# also needs to be specified.
|
|
164
|
+
#
|
|
165
|
+
# Example:
|
|
166
|
+
#
|
|
167
|
+
# #>pdf-small
|
|
168
|
+
# doc.annotations.
|
|
169
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
170
|
+
# leader_line_length(15).
|
|
171
|
+
# leader_line_extension_length(5).
|
|
172
|
+
# regenerate_appearance
|
|
173
|
+
# canvas.stroke_color("hp-orange").line(20, 20, 80, 60).stroke
|
|
174
|
+
#
|
|
175
|
+
# Also see: #leader_line_length, #leader_line_offset
|
|
176
|
+
def leader_line_extension_length(length = nil)
|
|
177
|
+
if length
|
|
178
|
+
raise ArgumentError, "length must be non-negative" if length < 0
|
|
179
|
+
self[:LLE] = length
|
|
180
|
+
self
|
|
181
|
+
else
|
|
182
|
+
self[:LLE]
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# :call-seq:
|
|
187
|
+
# line.leader_line_offset => leader_line_offset
|
|
188
|
+
# line.leader_line_offset(number) => line
|
|
189
|
+
#
|
|
190
|
+
# Returns the leader line offset when no argument is given. Otherwise sets the leader line
|
|
191
|
+
# offset and returns self.
|
|
192
|
+
#
|
|
193
|
+
# The leader line offset is a non-negative number that describes the offset of the leader
|
|
194
|
+
# lines from the endpoints of the line.
|
|
195
|
+
#
|
|
196
|
+
# Example:
|
|
197
|
+
#
|
|
198
|
+
# #>pdf-small
|
|
199
|
+
# doc.annotations.
|
|
200
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
201
|
+
# leader_line_length(15).
|
|
202
|
+
# leader_line_offset(5).
|
|
203
|
+
# regenerate_appearance
|
|
204
|
+
# canvas.stroke_color("hp-orange").line(20, 20, 80, 60).stroke
|
|
205
|
+
#
|
|
206
|
+
# Also see: #leader_line_length, #leader_line_extension_length
|
|
207
|
+
def leader_line_offset(offset = nil)
|
|
208
|
+
offset ? (self[:LLO] = offset; self) : self[:LLO] || 0
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# :call-seq:
|
|
212
|
+
# line.captioned => true or false
|
|
213
|
+
# line.captioned(value) => line
|
|
214
|
+
#
|
|
215
|
+
# Returns +true+ (if the line has a visible caption) or +false+ (no visible caption) when no
|
|
216
|
+
# argument is given. Otherwise sets whether a caption should be visible and returns self.
|
|
217
|
+
#
|
|
218
|
+
# If a caption should be shown, the text specified by the /Contents or /RC entries is shown
|
|
219
|
+
# in the appearance of the line.
|
|
220
|
+
#
|
|
221
|
+
# Example:
|
|
222
|
+
#
|
|
223
|
+
# #>pdf-small-hide
|
|
224
|
+
# doc.annotations.
|
|
225
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
226
|
+
# contents("Inline text").
|
|
227
|
+
# captioned(true).
|
|
228
|
+
# regenerate_appearance
|
|
229
|
+
# Also see: #caption_position, #caption_offset
|
|
230
|
+
def captioned(value = nil)
|
|
231
|
+
value ? (self[:Cap] = value; self) : self[:Cap]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Maps HexaPDF names to PDF names.
|
|
235
|
+
CAPTION_POSITION_MAP = { # :nodoc:
|
|
236
|
+
Inline: :Inline, inline: :Inline,
|
|
237
|
+
Top: :Top, top: :Top,
|
|
238
|
+
}.freeze
|
|
239
|
+
CAPTION_POSITION_REVERSE_MAP = CAPTION_POSITION_MAP.invert # :nodoc:
|
|
240
|
+
|
|
241
|
+
# :call-seq:
|
|
242
|
+
# line.caption_position => caption_position
|
|
243
|
+
# line.caption_position(value) => line
|
|
244
|
+
#
|
|
245
|
+
# Returns the caption position when no argument is given. Otherwise sets the caption
|
|
246
|
+
# position and returns self.
|
|
247
|
+
#
|
|
248
|
+
# Possible caption positions are (the first one is the HexaPDF name, the second the PDF
|
|
249
|
+
# name):
|
|
250
|
+
#
|
|
251
|
+
# :inline or :Inline::
|
|
252
|
+
# The caption is centered inside the line (default).
|
|
253
|
+
#
|
|
254
|
+
# #>pdf-small-hide
|
|
255
|
+
# doc.annotations.
|
|
256
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
257
|
+
# contents("Inline text").
|
|
258
|
+
# captioned(true).
|
|
259
|
+
# caption_position(:inline).
|
|
260
|
+
# regenerate_appearance
|
|
261
|
+
#
|
|
262
|
+
# :top or :Top::
|
|
263
|
+
# The caption is on the top of the line.
|
|
264
|
+
#
|
|
265
|
+
# #>pdf-small-hide
|
|
266
|
+
# doc.annotations.
|
|
267
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
268
|
+
# contents("Top text").
|
|
269
|
+
# captioned(true).
|
|
270
|
+
# caption_position(:top).
|
|
271
|
+
# regenerate_appearance
|
|
272
|
+
#
|
|
273
|
+
# Also see: #captioned, #caption_offset
|
|
274
|
+
def caption_position(value = nil)
|
|
275
|
+
if value
|
|
276
|
+
value = CAPTION_POSITION_MAP.fetch(value) do
|
|
277
|
+
raise ArgumentError, "Invalid caption position: #{value.inspect}"
|
|
278
|
+
end
|
|
279
|
+
self[:CP] = value
|
|
280
|
+
self
|
|
281
|
+
else
|
|
282
|
+
CAPTION_POSITION_REVERSE_MAP[self[:CP]]
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# :call-seq:
|
|
287
|
+
# line.caption_offset => caption_offset
|
|
288
|
+
# line.caption_offset(x, y) => line
|
|
289
|
+
#
|
|
290
|
+
# Returns the caption offset when no argument is given. Otherwise sets the caption offset
|
|
291
|
+
# and returns self.
|
|
292
|
+
#
|
|
293
|
+
# The caption offset is an array of two numbers that specify the horizontal and vertical
|
|
294
|
+
# offsets of the caption from its normal position. A positive horizontal offset means moving
|
|
295
|
+
# the caption to the right. A positive vertical offset means shifting the caption up.
|
|
296
|
+
#
|
|
297
|
+
# Example:
|
|
298
|
+
#
|
|
299
|
+
# #>pdf-small-hide
|
|
300
|
+
# doc.annotations.
|
|
301
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
|
302
|
+
# contents("Top text").
|
|
303
|
+
# captioned(true).
|
|
304
|
+
# caption_position(:top).
|
|
305
|
+
# caption_offset(20, 10).
|
|
306
|
+
# regenerate_appearance
|
|
307
|
+
#
|
|
308
|
+
# Also see: #captioned, #caption_position
|
|
309
|
+
def caption_offset(x = nil, y = nil)
|
|
310
|
+
x || y ? (self[:CO] = [x || 0, y || 0]; self) : self[:CO].to_ary
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
private
|
|
314
|
+
|
|
315
|
+
def perform_validation #:nodoc:
|
|
316
|
+
super
|
|
317
|
+
if self[:LLE] < 0
|
|
318
|
+
yield('/LLE must be a non-negative number', true)
|
|
319
|
+
self[:LLE] = -self[:LLE]
|
|
320
|
+
end
|
|
321
|
+
if key?(:LLO) && self[:LLO] < 0
|
|
322
|
+
yield('/LLO must be a non-negative number', true)
|
|
323
|
+
self[:LLO] = -self[:LLO]
|
|
324
|
+
end
|
|
325
|
+
if self[:LLE] > 0 && self[:LL] == 0
|
|
326
|
+
yield("/LL required to be non-zero if /LLE is set")
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|