hexapdf 0.15.8 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +10 -1
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/fonts.rb +145 -0
- data/lib/hexapdf/cli/form.rb +27 -26
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +1 -10
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +1 -1
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/cli.rb +3 -1
- data/lib/hexapdf/composer.rb +1 -1
- data/lib/hexapdf/configuration.rb +11 -2
- data/lib/hexapdf/content/canvas.rb +658 -167
- data/lib/hexapdf/content/color_space.rb +185 -3
- data/lib/hexapdf/content/graphic_object/arc.rb +111 -12
- 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 +1 -1
- data/lib/hexapdf/content/operator.rb +1 -1
- data/lib/hexapdf/content/parser.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/dictionary_fields.rb +30 -4
- data/lib/hexapdf/document/files.rb +3 -3
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/pages.rb +1 -1
- data/lib/hexapdf/document.rb +1 -1
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/error.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/base.rb +1 -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 +1 -1
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
- 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 +1 -1
- 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.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 +1 -1
- data/lib/hexapdf/layout/box.rb +4 -2
- 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/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +40 -2
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- 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 +2 -2
- 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 +1 -1
- data/lib/hexapdf/parser.rb +2 -2
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +1 -1
- data/lib/hexapdf/revisions.rb +1 -1
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +1 -1
- data/lib/hexapdf/task.rb +1 -1
- data/lib/hexapdf/tokenizer.rb +1 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +14 -7
- data/lib/hexapdf/type/acro_form/button_field.rb +53 -28
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +21 -2
- data/lib/hexapdf/type/acro_form/form.rb +48 -29
- data/lib/hexapdf/type/acro_form/text_field.rb +2 -2
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +17 -9
- 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 +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.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 +1 -1
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +1 -1
- data/lib/hexapdf/type/cid_font.rb +1 -1
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +1 -1
- data/lib/hexapdf/type/font.rb +1 -1
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_true_type.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type1.rb +1 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +1 -1
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +1 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/names.rb +1 -1
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/page.rb +15 -1
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +1 -1
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +1 -1
- data/lib/hexapdf/type.rb +1 -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 +1 -1
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/lib/hexapdf.rb +1 -1
- metadata +5 -264
- data/CHANGELOG.md +0 -954
- data/LICENSE +0 -29
- data/README.md +0 -120
- data/Rakefile +0 -108
- data/agpl-3.0.txt +0 -661
- data/examples/001-hello_world.rb +0 -16
- data/examples/002-graphics.rb +0 -275
- data/examples/003-arcs.rb +0 -50
- data/examples/004-optimizing.rb +0 -23
- data/examples/005-merging.rb +0 -27
- data/examples/006-standard_pdf_fonts.rb +0 -73
- data/examples/007-truetype.rb +0 -42
- data/examples/008-show_char_bboxes.rb +0 -55
- data/examples/009-text_layouter_alignment.rb +0 -47
- data/examples/010-text_layouter_inline_boxes.rb +0 -64
- data/examples/011-text_layouter_line_wrapping.rb +0 -57
- data/examples/012-text_layouter_styling.rb +0 -122
- data/examples/013-text_layouter_shapes.rb +0 -176
- data/examples/014-text_in_polygon.rb +0 -60
- data/examples/015-boxes.rb +0 -76
- data/examples/016-frame_automatic_box_placement.rb +0 -90
- data/examples/017-frame_text_flow.rb +0 -60
- data/examples/018-composer.rb +0 -44
- data/examples/019-acro_form.rb +0 -88
- data/examples/emoji-smile.png +0 -0
- data/examples/emoji-wink.png +0 -0
- data/examples/machupicchu.jpg +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCGFSbox-256-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCKeySbox-256-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarKey-256-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-128-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-128-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-192-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-192-encrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-256-decrypt.data.gz +0 -0
- data/test/data/aes-test-vectors/CBCVarTxt-256-encrypt.data.gz +0 -0
- data/test/data/fonts/Ubuntu-Title.ttf +0 -0
- data/test/data/images/cmyk.jpg +0 -0
- data/test/data/images/fillbytes.jpg +0 -0
- data/test/data/images/gray.jpg +0 -0
- data/test/data/images/greyscale-1bit.png +0 -0
- data/test/data/images/greyscale-2bit.png +0 -0
- data/test/data/images/greyscale-4bit.png +0 -0
- data/test/data/images/greyscale-8bit.png +0 -0
- data/test/data/images/greyscale-alpha-8bit.png +0 -0
- data/test/data/images/greyscale-trns-8bit.png +0 -0
- data/test/data/images/greyscale-with-gamma1.0.png +0 -0
- data/test/data/images/greyscale-with-gamma1.5.png +0 -0
- data/test/data/images/indexed-1bit.png +0 -0
- data/test/data/images/indexed-2bit.png +0 -0
- data/test/data/images/indexed-4bit.png +0 -0
- data/test/data/images/indexed-8bit.png +0 -0
- data/test/data/images/indexed-alpha-4bit.png +0 -0
- data/test/data/images/indexed-alpha-8bit.png +0 -0
- data/test/data/images/rgb.jpg +0 -0
- data/test/data/images/truecolour-8bit.png +0 -0
- data/test/data/images/truecolour-alpha-8bit.png +0 -0
- data/test/data/images/truecolour-gama-chrm-8bit.png +0 -0
- data/test/data/images/truecolour-srgb-8bit.png +0 -0
- data/test/data/images/ycck.jpg +0 -0
- data/test/data/minimal.pdf +0 -44
- data/test/data/standard-security-handler/README +0 -9
- data/test/data/standard-security-handler/bothpwd-aes-128bit-V4.pdf +0 -44
- data/test/data/standard-security-handler/bothpwd-aes-256bit-V5.pdf +0 -0
- data/test/data/standard-security-handler/bothpwd-arc4-128bit-V2.pdf +0 -43
- data/test/data/standard-security-handler/bothpwd-arc4-128bit-V4.pdf +0 -43
- data/test/data/standard-security-handler/bothpwd-arc4-40bit-V1.pdf +0 -0
- data/test/data/standard-security-handler/nopwd-aes-128bit-V4.pdf +0 -43
- data/test/data/standard-security-handler/nopwd-aes-256bit-V5.pdf +0 -0
- data/test/data/standard-security-handler/nopwd-arc4-128bit-V2.pdf +0 -43
- data/test/data/standard-security-handler/nopwd-arc4-128bit-V4.pdf +0 -43
- data/test/data/standard-security-handler/nopwd-arc4-40bit-V1.pdf +0 -43
- data/test/data/standard-security-handler/ownerpwd-aes-128bit-V4.pdf +0 -0
- data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5.pdf +0 -43
- data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V2.pdf +0 -43
- data/test/data/standard-security-handler/ownerpwd-arc4-128bit-V4.pdf +0 -43
- data/test/data/standard-security-handler/ownerpwd-arc4-40bit-V1.pdf +0 -43
- data/test/data/standard-security-handler/userpwd-aes-128bit-V4.pdf +0 -43
- data/test/data/standard-security-handler/userpwd-aes-256bit-V5.pdf +0 -43
- data/test/data/standard-security-handler/userpwd-arc4-128bit-V2.pdf +0 -0
- data/test/data/standard-security-handler/userpwd-arc4-128bit-V4.pdf +0 -0
- data/test/data/standard-security-handler/userpwd-arc4-40bit-V1.pdf +0 -43
- data/test/hexapdf/common_tokenizer_tests.rb +0 -236
- data/test/hexapdf/content/common.rb +0 -39
- data/test/hexapdf/content/graphic_object/test_arc.rb +0 -93
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +0 -90
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +0 -79
- data/test/hexapdf/content/graphic_object/test_solid_arc.rb +0 -86
- data/test/hexapdf/content/test_canvas.rb +0 -1216
- data/test/hexapdf/content/test_color_space.rb +0 -164
- data/test/hexapdf/content/test_graphics_state.rb +0 -151
- data/test/hexapdf/content/test_operator.rb +0 -619
- data/test/hexapdf/content/test_parser.rb +0 -99
- data/test/hexapdf/content/test_processor.rb +0 -163
- data/test/hexapdf/content/test_transformation_matrix.rb +0 -64
- data/test/hexapdf/document/test_files.rb +0 -72
- data/test/hexapdf/document/test_fonts.rb +0 -60
- data/test/hexapdf/document/test_images.rb +0 -72
- data/test/hexapdf/document/test_pages.rb +0 -130
- data/test/hexapdf/encryption/common.rb +0 -87
- data/test/hexapdf/encryption/test_aes.rb +0 -129
- data/test/hexapdf/encryption/test_arc4.rb +0 -39
- data/test/hexapdf/encryption/test_fast_aes.rb +0 -17
- data/test/hexapdf/encryption/test_fast_arc4.rb +0 -12
- data/test/hexapdf/encryption/test_identity.rb +0 -21
- data/test/hexapdf/encryption/test_ruby_aes.rb +0 -23
- data/test/hexapdf/encryption/test_ruby_arc4.rb +0 -20
- data/test/hexapdf/encryption/test_security_handler.rb +0 -380
- data/test/hexapdf/encryption/test_standard_security_handler.rb +0 -322
- data/test/hexapdf/filter/common.rb +0 -53
- data/test/hexapdf/filter/test_ascii85_decode.rb +0 -59
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +0 -38
- data/test/hexapdf/filter/test_crypt.rb +0 -21
- data/test/hexapdf/filter/test_encryption.rb +0 -24
- data/test/hexapdf/filter/test_flate_decode.rb +0 -44
- data/test/hexapdf/filter/test_lzw_decode.rb +0 -52
- data/test/hexapdf/filter/test_predictor.rb +0 -219
- data/test/hexapdf/filter/test_run_length_decode.rb +0 -32
- data/test/hexapdf/font/cmap/test_parser.rb +0 -102
- data/test/hexapdf/font/cmap/test_writer.rb +0 -66
- data/test/hexapdf/font/encoding/test_base.rb +0 -45
- data/test/hexapdf/font/encoding/test_difference_encoding.rb +0 -29
- data/test/hexapdf/font/encoding/test_glyph_list.rb +0 -59
- data/test/hexapdf/font/encoding/test_zapf_dingbats_encoding.rb +0 -16
- data/test/hexapdf/font/test_cmap.rb +0 -104
- data/test/hexapdf/font/test_encoding.rb +0 -27
- data/test/hexapdf/font/test_invalid_glyph.rb +0 -34
- data/test/hexapdf/font/test_true_type_wrapper.rb +0 -186
- data/test/hexapdf/font/test_type1_wrapper.rb +0 -107
- data/test/hexapdf/font/true_type/common.rb +0 -17
- data/test/hexapdf/font/true_type/table/common.rb +0 -27
- data/test/hexapdf/font/true_type/table/test_cmap.rb +0 -47
- data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +0 -141
- data/test/hexapdf/font/true_type/table/test_directory.rb +0 -30
- data/test/hexapdf/font/true_type/table/test_glyf.rb +0 -58
- data/test/hexapdf/font/true_type/table/test_head.rb +0 -56
- data/test/hexapdf/font/true_type/table/test_hhea.rb +0 -26
- data/test/hexapdf/font/true_type/table/test_hmtx.rb +0 -30
- data/test/hexapdf/font/true_type/table/test_kern.rb +0 -61
- data/test/hexapdf/font/true_type/table/test_loca.rb +0 -33
- data/test/hexapdf/font/true_type/table/test_maxp.rb +0 -50
- data/test/hexapdf/font/true_type/table/test_name.rb +0 -76
- data/test/hexapdf/font/true_type/table/test_os2.rb +0 -55
- data/test/hexapdf/font/true_type/table/test_post.rb +0 -78
- data/test/hexapdf/font/true_type/test_builder.rb +0 -42
- data/test/hexapdf/font/true_type/test_font.rb +0 -116
- data/test/hexapdf/font/true_type/test_optimizer.rb +0 -26
- data/test/hexapdf/font/true_type/test_subsetter.rb +0 -73
- data/test/hexapdf/font/true_type/test_table.rb +0 -48
- data/test/hexapdf/font/type1/common.rb +0 -6
- data/test/hexapdf/font/type1/test_afm_parser.rb +0 -65
- data/test/hexapdf/font/type1/test_font.rb +0 -104
- data/test/hexapdf/font/type1/test_font_metrics.rb +0 -22
- data/test/hexapdf/font/type1/test_pfb_parser.rb +0 -37
- data/test/hexapdf/font_loader/test_from_configuration.rb +0 -43
- data/test/hexapdf/font_loader/test_from_file.rb +0 -36
- data/test/hexapdf/font_loader/test_standard14.rb +0 -33
- data/test/hexapdf/image_loader/test_jpeg.rb +0 -93
- data/test/hexapdf/image_loader/test_pdf.rb +0 -47
- data/test/hexapdf/image_loader/test_png.rb +0 -259
- data/test/hexapdf/layout/test_box.rb +0 -152
- data/test/hexapdf/layout/test_frame.rb +0 -350
- data/test/hexapdf/layout/test_image_box.rb +0 -73
- data/test/hexapdf/layout/test_inline_box.rb +0 -71
- data/test/hexapdf/layout/test_line.rb +0 -206
- data/test/hexapdf/layout/test_style.rb +0 -779
- data/test/hexapdf/layout/test_text_box.rb +0 -140
- data/test/hexapdf/layout/test_text_fragment.rb +0 -375
- data/test/hexapdf/layout/test_text_layouter.rb +0 -758
- data/test/hexapdf/layout/test_text_shaper.rb +0 -62
- data/test/hexapdf/layout/test_width_from_polygon.rb +0 -108
- data/test/hexapdf/task/test_dereference.rb +0 -51
- data/test/hexapdf/task/test_optimize.rb +0 -162
- data/test/hexapdf/test_composer.rb +0 -258
- data/test/hexapdf/test_configuration.rb +0 -93
- data/test/hexapdf/test_data_dir.rb +0 -32
- data/test/hexapdf/test_dictionary.rb +0 -340
- data/test/hexapdf/test_dictionary_fields.rb +0 -245
- data/test/hexapdf/test_document.rb +0 -641
- data/test/hexapdf/test_filter.rb +0 -100
- data/test/hexapdf/test_importer.rb +0 -106
- data/test/hexapdf/test_object.rb +0 -258
- data/test/hexapdf/test_parser.rb +0 -637
- data/test/hexapdf/test_pdf_array.rb +0 -169
- data/test/hexapdf/test_rectangle.rb +0 -73
- data/test/hexapdf/test_reference.rb +0 -50
- data/test/hexapdf/test_revision.rb +0 -188
- data/test/hexapdf/test_revisions.rb +0 -196
- data/test/hexapdf/test_serializer.rb +0 -195
- data/test/hexapdf/test_stream.rb +0 -274
- data/test/hexapdf/test_tokenizer.rb +0 -80
- data/test/hexapdf/test_type.rb +0 -18
- data/test/hexapdf/test_writer.rb +0 -140
- data/test/hexapdf/test_xref_section.rb +0 -61
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +0 -794
- data/test/hexapdf/type/acro_form/test_button_field.rb +0 -302
- data/test/hexapdf/type/acro_form/test_choice_field.rb +0 -220
- data/test/hexapdf/type/acro_form/test_field.rb +0 -247
- data/test/hexapdf/type/acro_form/test_form.rb +0 -353
- data/test/hexapdf/type/acro_form/test_signature_field.rb +0 -38
- data/test/hexapdf/type/acro_form/test_text_field.rb +0 -195
- data/test/hexapdf/type/acro_form/test_variable_text_field.rb +0 -77
- data/test/hexapdf/type/actions/test_launch.rb +0 -24
- data/test/hexapdf/type/actions/test_uri.rb +0 -23
- data/test/hexapdf/type/annotations/test_markup_annotation.rb +0 -22
- data/test/hexapdf/type/annotations/test_text.rb +0 -34
- data/test/hexapdf/type/annotations/test_widget.rb +0 -225
- data/test/hexapdf/type/test_annotation.rb +0 -97
- data/test/hexapdf/type/test_catalog.rb +0 -48
- data/test/hexapdf/type/test_cid_font.rb +0 -61
- data/test/hexapdf/type/test_file_specification.rb +0 -141
- data/test/hexapdf/type/test_font.rb +0 -67
- data/test/hexapdf/type/test_font_descriptor.rb +0 -61
- data/test/hexapdf/type/test_font_simple.rb +0 -176
- data/test/hexapdf/type/test_font_true_type.rb +0 -31
- data/test/hexapdf/type/test_font_type0.rb +0 -120
- data/test/hexapdf/type/test_font_type1.rb +0 -142
- data/test/hexapdf/type/test_font_type3.rb +0 -26
- data/test/hexapdf/type/test_form.rb +0 -120
- data/test/hexapdf/type/test_image.rb +0 -261
- data/test/hexapdf/type/test_info.rb +0 -9
- data/test/hexapdf/type/test_object_stream.rb +0 -117
- data/test/hexapdf/type/test_page.rb +0 -587
- data/test/hexapdf/type/test_page_tree_node.rb +0 -315
- data/test/hexapdf/type/test_resources.rb +0 -209
- data/test/hexapdf/type/test_trailer.rb +0 -116
- data/test/hexapdf/type/test_xref_stream.rb +0 -143
- data/test/hexapdf/utils/test_bit_field.rb +0 -63
- data/test/hexapdf/utils/test_bit_stream.rb +0 -69
- data/test/hexapdf/utils/test_graphics_helpers.rb +0 -37
- data/test/hexapdf/utils/test_lru_cache.rb +0 -22
- data/test/hexapdf/utils/test_object_hash.rb +0 -120
- data/test/hexapdf/utils/test_pdf_doc_encoding.rb +0 -18
- data/test/hexapdf/utils/test_sorted_tree_node.rb +0 -239
- data/test/test_helper.rb +0 -58
@@ -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-2021 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
|
@@ -56,7 +56,7 @@ module HexaPDF
|
|
56
56
|
# know all operators and their operands.
|
57
57
|
#
|
58
58
|
# This is rather tedious and therefore this class exists. It allows one to modify a content
|
59
|
-
# stream by invoking methods that should be familiar to anyone that has ever used a
|
59
|
+
# stream by invoking methods that should be familiar to anyone that has ever used a graphics
|
60
60
|
# API. There are methods for moving the current point, drawing lines and curves, setting the
|
61
61
|
# color, line width and so on.
|
62
62
|
#
|
@@ -65,6 +65,84 @@ module HexaPDF
|
|
65
65
|
# changes and serialization, with one exception: color setters don't invoke the corresponding
|
66
66
|
# operator implementation but directly work on the graphics state.
|
67
67
|
#
|
68
|
+
# === General Graphics State Manipulation Methods
|
69
|
+
#
|
70
|
+
# * #save_graphics_state
|
71
|
+
# * #restore_graphics_state
|
72
|
+
# * #fill_color
|
73
|
+
# * #stroke_color
|
74
|
+
# * #opacity
|
75
|
+
# * #rendering_intent
|
76
|
+
#
|
77
|
+
# === Transformation Methods
|
78
|
+
#
|
79
|
+
# * #transform
|
80
|
+
# * #translate
|
81
|
+
# * #scale
|
82
|
+
# * #rotate
|
83
|
+
# * #skew
|
84
|
+
#
|
85
|
+
# === Path Construction Methods
|
86
|
+
#
|
87
|
+
# * #move_to
|
88
|
+
# * #line_to
|
89
|
+
# * #curve_to
|
90
|
+
# * #rectangle
|
91
|
+
# * #line
|
92
|
+
# * #polyline
|
93
|
+
# * #polygon
|
94
|
+
# * #circle
|
95
|
+
# * #ellipse
|
96
|
+
# * #arc
|
97
|
+
# * #close_subpath
|
98
|
+
# * #end_path
|
99
|
+
#
|
100
|
+
# === Path Painting Methods
|
101
|
+
#
|
102
|
+
# * #fill
|
103
|
+
# * #stroke
|
104
|
+
# * #fill_stroke
|
105
|
+
# * #close_stroke
|
106
|
+
# * #close_fill_stroke
|
107
|
+
# * #clip_path
|
108
|
+
#
|
109
|
+
# === Path Related Graphics State Methods
|
110
|
+
#
|
111
|
+
# * #line_cap_style
|
112
|
+
# * #line_dash_pattern
|
113
|
+
# * #line_join_style
|
114
|
+
# * #line_width
|
115
|
+
# * #miter_limit
|
116
|
+
#
|
117
|
+
# === Text Related Methods
|
118
|
+
#
|
119
|
+
# * #begin_text
|
120
|
+
# * #end_text
|
121
|
+
# * #text
|
122
|
+
# * #show_glyphs
|
123
|
+
# * #show_glyphs_only
|
124
|
+
# * #text_cursor
|
125
|
+
# * #move_text_cursor
|
126
|
+
# * #font
|
127
|
+
# * #font_size
|
128
|
+
# * #character_spacing
|
129
|
+
# * #horizontal_scaling
|
130
|
+
# * #text_rise
|
131
|
+
# * #word_spacing
|
132
|
+
# * #leading
|
133
|
+
# * #text_matrix
|
134
|
+
# * #text_rendering_mode
|
135
|
+
#
|
136
|
+
# === Other Methods
|
137
|
+
#
|
138
|
+
# * #image
|
139
|
+
# * #xobject
|
140
|
+
# * #graphic_object
|
141
|
+
# * #draw
|
142
|
+
# * #marked_content_point
|
143
|
+
# * #marked_content_sequence
|
144
|
+
# * #end_marked_content_sequence
|
145
|
+
#
|
68
146
|
#
|
69
147
|
# == PDF Graphics
|
70
148
|
#
|
@@ -122,16 +200,6 @@ module HexaPDF
|
|
122
200
|
# In addition filling may be done using either the nonzero winding number rule or the even-odd
|
123
201
|
# rule.
|
124
202
|
#
|
125
|
-
#
|
126
|
-
# == Special Graphics State Methods
|
127
|
-
#
|
128
|
-
# These methods are only allowed when the current graphics object is :none, i.e. operations are
|
129
|
-
# done on the page description level.
|
130
|
-
#
|
131
|
-
# * #save_graphics_state
|
132
|
-
# * #restore_graphics_state
|
133
|
-
# * #transform, #rotate, #scale, #translate, #skew
|
134
|
-
#
|
135
203
|
# See: PDF1.7 s8, s9
|
136
204
|
class Canvas
|
137
205
|
|
@@ -154,8 +222,10 @@ module HexaPDF
|
|
154
222
|
# operations.
|
155
223
|
#
|
156
224
|
# In contrast to #contents, it is ensured that an open graphics object is closed and all saved
|
157
|
-
# graphics states are restored when the contents of the stream data object is read.
|
158
|
-
#
|
225
|
+
# graphics states are restored when the contents of the stream data object is read.
|
226
|
+
#
|
227
|
+
# *Note* that this means that reading the stream data object may change the state of the
|
228
|
+
# canvas!
|
159
229
|
attr_reader :stream_data
|
160
230
|
|
161
231
|
# The Content::GraphicsState object containing the current graphics state.
|
@@ -166,8 +236,8 @@ module HexaPDF
|
|
166
236
|
|
167
237
|
# The current graphics object.
|
168
238
|
#
|
169
|
-
# The graphics object should not be changed directly. It is automatically updated
|
170
|
-
#
|
239
|
+
# The graphics object should not be changed directly. It is automatically updated by the
|
240
|
+
# invoked methods.
|
171
241
|
#
|
172
242
|
# This attribute can have the following values:
|
173
243
|
#
|
@@ -189,9 +259,21 @@ module HexaPDF
|
|
189
259
|
attr_reader :current_point
|
190
260
|
|
191
261
|
# The operator name/implementation map used when invoking or serializing an operator.
|
262
|
+
#
|
263
|
+
# Defaults to Content::Operator::DEFAULT_OPERATORS.
|
192
264
|
attr_reader :operators
|
193
265
|
|
194
|
-
# Creates a new Canvas object for the given context object (either a Page or a
|
266
|
+
# Creates a new Canvas object for the given context object (either a HexaPDF::Type::Page or a
|
267
|
+
# HexaPDF::Type::Form).
|
268
|
+
#
|
269
|
+
# This method is usually not invoked directly but through HexaPDF::Type::Page#canvas or
|
270
|
+
# HexaPDF::Type::Form#canvas to make sure the contents of the canvas is properly assigned to
|
271
|
+
# the context object.
|
272
|
+
#
|
273
|
+
# Examples:
|
274
|
+
#
|
275
|
+
# doc = HexaPDF::Document.new
|
276
|
+
# canvas = doc.pages.add.canvas
|
195
277
|
def initialize(context)
|
196
278
|
@context = context
|
197
279
|
@operators = Operator::DEFAULT_OPERATORS.dup
|
@@ -214,6 +296,8 @@ module HexaPDF
|
|
214
296
|
end
|
215
297
|
|
216
298
|
# Returns the resource dictionary of the context object.
|
299
|
+
#
|
300
|
+
# See HexaPDF::Type::Resources
|
217
301
|
def resources
|
218
302
|
@context.resources
|
219
303
|
end
|
@@ -224,22 +308,29 @@ module HexaPDF
|
|
224
308
|
#
|
225
309
|
# Saves the current graphics state and returns self.
|
226
310
|
#
|
227
|
-
# If invoked without a block a corresponding call to #restore_graphics_state must be done
|
228
|
-
#
|
311
|
+
# If invoked without a block a corresponding call to #restore_graphics_state must be done to
|
312
|
+
# ensure proper nesting. Otherwise, i.e. when invoked with a block, the graphics state is
|
313
|
+
# automatically restored when the block is finished.
|
314
|
+
#
|
315
|
+
# Any saved graphics states are also restored when the content stream associated with the
|
316
|
+
# canvas is serialized to ensure proper nesting.
|
229
317
|
#
|
230
318
|
# Examples:
|
231
319
|
#
|
320
|
+
# #>pdf
|
232
321
|
# # With a block
|
233
322
|
# canvas.save_graphics_state do
|
234
|
-
# canvas.
|
235
|
-
# canvas.line(
|
323
|
+
# canvas.stroke_color("red") # After the block the color is reset
|
324
|
+
# canvas.line(20, 20, 70, 180).stroke
|
236
325
|
# end
|
326
|
+
# canvas.line(60, 20, 110, 180).stroke
|
237
327
|
#
|
238
328
|
# # Same without a block
|
239
|
-
# canvas.save_graphics_state
|
240
|
-
#
|
241
|
-
#
|
242
|
-
#
|
329
|
+
# canvas.save_graphics_state.
|
330
|
+
# stroke_color("red").
|
331
|
+
# line(100, 20, 150, 180).stroke.
|
332
|
+
# restore_graphics_state
|
333
|
+
# canvas.line(140, 20, 190, 180).stroke
|
243
334
|
#
|
244
335
|
# See: PDF1.7 s8.4.2, #restore_graphics_state
|
245
336
|
def save_graphics_state
|
@@ -286,10 +377,12 @@ module HexaPDF
|
|
286
377
|
#
|
287
378
|
# Examples:
|
288
379
|
#
|
380
|
+
# #>pdf
|
289
381
|
# canvas.transform(1, 0, 0, 1, 100, 100) do # Translate origin to (100, 100)
|
290
|
-
# canvas.
|
382
|
+
# canvas.stroke_color("red").
|
383
|
+
# line(0, 0, 100, 50).stroke # Actually from (100, 100) to (200, 150)
|
291
384
|
# end
|
292
|
-
# canvas.line(0, 0, 100,
|
385
|
+
# canvas.line(0, 0, 100, 50).stroke # Really from (0, 0) to (100, 50)
|
293
386
|
#
|
294
387
|
# See: PDF1.7 s8.3, s8.4.4
|
295
388
|
def transform(a, b, c, d, e, f)
|
@@ -313,20 +406,25 @@ module HexaPDF
|
|
313
406
|
# If invoked with a block, the rotation of the user space is only active during the block by
|
314
407
|
# saving and restoring the graphics state.
|
315
408
|
#
|
316
|
-
# Note that the origin of the coordinate system itself doesn't change
|
409
|
+
# Note that the origin of the coordinate system itself doesn't change even if the +origin+
|
410
|
+
# argument is given!
|
317
411
|
#
|
318
412
|
# origin::
|
319
413
|
# The point around which the user space should be rotated.
|
320
414
|
#
|
321
415
|
# Examples:
|
322
416
|
#
|
323
|
-
#
|
324
|
-
#
|
417
|
+
# #>pdf-center
|
418
|
+
# canvas.stroke_color("lightgrey").
|
419
|
+
# rectangle(0, 0, 60, 40).stroke
|
420
|
+
# canvas.rotate(45) do # Positive x-axis pointing to top-right corner
|
421
|
+
# canvas.stroke_color("red").
|
422
|
+
# rectangle(0, 0, 60, 40).stroke
|
325
423
|
# end
|
326
|
-
# canvas.line(0, 0, 100, 0) # Again from (0, 0) to (100, 0)
|
327
424
|
#
|
328
|
-
# canvas.rotate(
|
329
|
-
# canvas.
|
425
|
+
# canvas.rotate(-45, origin: [-50, -50]) do # Rotate around (-50,-50)
|
426
|
+
# canvas.stroke_color("blue").
|
427
|
+
# rectangle(0, 0, 60, 40).stroke
|
330
428
|
# end
|
331
429
|
#
|
332
430
|
# See: #transform
|
@@ -352,20 +450,25 @@ module HexaPDF
|
|
352
450
|
# If invoked with a block, the scaling is only active during the block by saving and
|
353
451
|
# restoring the graphics state.
|
354
452
|
#
|
355
|
-
# Note that the origin of the coordinate system itself doesn't change
|
453
|
+
# Note that the origin of the coordinate system itself doesn't change even if the +origin+
|
454
|
+
# argument is given!
|
356
455
|
#
|
357
456
|
# origin::
|
358
457
|
# The point from which the user space should be scaled.
|
359
458
|
#
|
360
459
|
# Examples:
|
361
460
|
#
|
362
|
-
#
|
363
|
-
#
|
461
|
+
# #>pdf-center
|
462
|
+
# canvas.stroke_color("lightgrey").
|
463
|
+
# rectangle(10, 10, 10, 10).stroke
|
464
|
+
# canvas.scale(4, 2) do # Scale from origin
|
465
|
+
# canvas.stroke_color("blue").
|
466
|
+
# rectangle(10, 10, 10, 10).stroke # Actually (40, 20) to (80, 40)
|
364
467
|
# end
|
365
|
-
# canvas.line(0, 0, 100, 0) # Again from (0, 0) to (100, 0)
|
366
468
|
#
|
367
|
-
# canvas.scale(2,
|
368
|
-
# canvas.
|
469
|
+
# canvas.scale(-2, 4, origin: [10, 10]) do # Scale from (10, 10)
|
470
|
+
# canvas.stroke_color("red").
|
471
|
+
# rectangle(10, 10, 10, 10).stroke # Actually (10, 10) to (-10, 40)
|
369
472
|
# end
|
370
473
|
#
|
371
474
|
# See: #transform
|
@@ -389,10 +492,12 @@ module HexaPDF
|
|
389
492
|
#
|
390
493
|
# Examples:
|
391
494
|
#
|
392
|
-
#
|
393
|
-
#
|
495
|
+
# #>pdf-center
|
496
|
+
# canvas.rectangle(0, 0, 40, 20).stroke # Rectangle from (0, 0) to (40, 20)
|
497
|
+
# canvas.translate(50, 50) do # Origin is now at (50, 50)
|
498
|
+
# canvas.stroke_color("red").
|
499
|
+
# rectangle(0, 0, 40, 20).stroke # Actually (50, 50) to (90, 70)
|
394
500
|
# end
|
395
|
-
# canvas.line(0, 0, 100, 0) # Again from (0, 0) to (100, 0)
|
396
501
|
#
|
397
502
|
# See: #transform
|
398
503
|
def translate(x, y, &block)
|
@@ -416,13 +521,17 @@ module HexaPDF
|
|
416
521
|
#
|
417
522
|
# Examples:
|
418
523
|
#
|
419
|
-
#
|
420
|
-
#
|
524
|
+
# #>pdf-center
|
525
|
+
# canvas.stroke_color("lightgrey").
|
526
|
+
# rectangle(10, 10, 40, 20).stroke
|
527
|
+
# canvas.skew(0, 30) do # Point (10, 10) is now actually (15, 10)
|
528
|
+
# canvas.stroke_color("blue").
|
529
|
+
# rectangle(10, 10, 40, 20).stroke # Now a parallelogram
|
421
530
|
# end
|
422
|
-
# canvas.line(0, 0, 100, 0) # Again from (0, 0) to (100, 0)
|
423
531
|
#
|
424
|
-
# canvas.skew(
|
425
|
-
# canvas.
|
532
|
+
# canvas.skew(30, 30, origin: [-50, 50]) do # Skew from (-50, 50)
|
533
|
+
# canvas.stroke_color("red").
|
534
|
+
# rectangle(-50, 50, 20, 20).stroke
|
426
535
|
# end
|
427
536
|
#
|
428
537
|
# See: #transform
|
@@ -453,14 +562,19 @@ module HexaPDF
|
|
453
562
|
#
|
454
563
|
# Examples:
|
455
564
|
#
|
456
|
-
#
|
565
|
+
# #>pdf
|
566
|
+
# canvas.line_width(10).
|
567
|
+
# line(10, 10, 10, 190).stroke
|
457
568
|
# canvas.line_width # => 10
|
458
569
|
# canvas.line_width = 5 # => 5
|
570
|
+
# canvas.line(60, 10, 60, 190).stroke
|
459
571
|
#
|
460
572
|
# canvas.line_width(10) do
|
461
573
|
# canvas.line_width # => 10
|
574
|
+
# canvas.line(110, 10, 110, 190).stroke
|
462
575
|
# end
|
463
576
|
# canvas.line_width # => 5
|
577
|
+
# canvas.line(160, 10, 160, 190).stroke
|
464
578
|
#
|
465
579
|
# See: PDF1.7 s8.4.3.2
|
466
580
|
def line_width(width = nil, &block)
|
@@ -473,10 +587,18 @@ module HexaPDF
|
|
473
587
|
# canvas.line_cap_style(style) => canvas
|
474
588
|
# canvas.line_cap_style(style) { block } => canvas
|
475
589
|
#
|
476
|
-
# The line cap style specifies how the ends of stroked open paths should look like.
|
477
|
-
#
|
478
|
-
#
|
479
|
-
#
|
590
|
+
# The line cap style specifies how the ends of stroked open paths should look like.
|
591
|
+
#
|
592
|
+
# The +style+ parameter can be one of:
|
593
|
+
#
|
594
|
+
# :butt or 0::
|
595
|
+
# Stroke is squared off at the endpoint of a path.
|
596
|
+
# :round or 1::
|
597
|
+
# A semicircular arc is drawn at the endpoint of a path.
|
598
|
+
# :projecting_square or 2::
|
599
|
+
# The stroke continues half the line width beyond the endpoint of a path.
|
600
|
+
#
|
601
|
+
# Note that the return value is always a normalized line cap style.
|
480
602
|
#
|
481
603
|
# Returns the current line cap style (see Content::GraphicsState#line_cap_style) when no
|
482
604
|
# argument is given. Otherwise sets the line cap style to the given +style+ and returns self.
|
@@ -487,6 +609,7 @@ module HexaPDF
|
|
487
609
|
#
|
488
610
|
# Examples:
|
489
611
|
#
|
612
|
+
# #>pdf
|
490
613
|
# canvas.line_cap_style(:butt)
|
491
614
|
# canvas.line_cap_style # => #<NamedValue @name=:butt, @value=0>
|
492
615
|
# canvas.line_cap_style = :round # => #<NamedValue @name=:round, @value=1>
|
@@ -496,7 +619,16 @@ module HexaPDF
|
|
496
619
|
# end
|
497
620
|
# canvas.line_cap_style # => #<NamedValue @name=:round, @value=1>
|
498
621
|
#
|
499
|
-
#
|
622
|
+
# # visual example
|
623
|
+
# [:butt, :round, :projecting_square].each_with_index do |style, index|
|
624
|
+
# canvas.line_cap_style(style).
|
625
|
+
# line_width(10).stroke_color("black").
|
626
|
+
# line(50 + index * 50, 30, 50 + index * 50, 170).stroke
|
627
|
+
# canvas.stroke_color("white").line_width(1).line_cap_style(:butt).
|
628
|
+
# line(50 + index * 50, 30, 50 + index * 50, 170).stroke
|
629
|
+
# end
|
630
|
+
#
|
631
|
+
# See: PDF1.7 s8.4.3.3, Content::LineCapStyle
|
500
632
|
def line_cap_style(style = nil, &block)
|
501
633
|
gs_getter_setter(:line_cap_style, :J, style && LineCapStyle.normalize(style), &block)
|
502
634
|
end
|
@@ -507,10 +639,19 @@ module HexaPDF
|
|
507
639
|
# canvas.line_join_style(style) => canvas
|
508
640
|
# canvas.line_join_style(style) { block } => canvas
|
509
641
|
#
|
510
|
-
# The line join style specifies the shape that is used at the corners of stroked paths.
|
511
|
-
#
|
512
|
-
#
|
513
|
-
#
|
642
|
+
# The line join style specifies the shape that is used at the corners of stroked paths.
|
643
|
+
#
|
644
|
+
# The +style+ parameter can be one of:
|
645
|
+
#
|
646
|
+
# :miter or 0::
|
647
|
+
# The outer lines of the two segments continue until the meet at an angle.
|
648
|
+
# :round or 1::
|
649
|
+
# An arc of a circle is drawn around the point where the segments meet.
|
650
|
+
# :bevel or 2::
|
651
|
+
# The two segments are finished with butt caps and the space between the ends is filled
|
652
|
+
# with a triangle.
|
653
|
+
#
|
654
|
+
# Note that the return value is always a normalized line join style.
|
514
655
|
#
|
515
656
|
# Returns the current line join style (see Content::GraphicsState#line_join_style) when no
|
516
657
|
# argument is given. Otherwise sets the line join style to the given +style+ and returns self.
|
@@ -521,6 +662,7 @@ module HexaPDF
|
|
521
662
|
#
|
522
663
|
# Examples:
|
523
664
|
#
|
665
|
+
# #>pdf
|
524
666
|
# canvas.line_join_style(:miter)
|
525
667
|
# canvas.line_join_style # => #<NamedValue @name=:miter, @value=0>
|
526
668
|
# canvas.line_join_style = :round # => #<NamedValue @name=:round, @value=1>
|
@@ -530,7 +672,16 @@ module HexaPDF
|
|
530
672
|
# end
|
531
673
|
# canvas.line_join_style # => #<NamedValue @name=:round, @value=1>
|
532
674
|
#
|
533
|
-
#
|
675
|
+
# # visual example
|
676
|
+
# [:miter, :round, :bevel].each_with_index do |style, index|
|
677
|
+
# canvas.line_join_style(style).
|
678
|
+
# line_width(10).stroke_color("black").
|
679
|
+
# polyline(20 + index * 60, 30, 40 + index * 60, 170, 60 + index * 60, 30).stroke
|
680
|
+
# canvas.stroke_color("white").line_width(1).line_join_style(:bevel).
|
681
|
+
# polyline(20 + index * 60, 30, 40 + index * 60, 170, 60 + index * 60, 30).stroke
|
682
|
+
# end
|
683
|
+
#
|
684
|
+
# See: PDF1.7 s8.4.3.4, Content::LineJoinStyle
|
534
685
|
def line_join_style(style = nil, &block)
|
535
686
|
gs_getter_setter(:line_join_style, :j, style && LineJoinStyle.normalize(style), &block)
|
536
687
|
end
|
@@ -554,6 +705,7 @@ module HexaPDF
|
|
554
705
|
#
|
555
706
|
# Examples:
|
556
707
|
#
|
708
|
+
# #>pdf
|
557
709
|
# canvas.miter_limit(10)
|
558
710
|
# canvas.miter_limit # => 10
|
559
711
|
# canvas.miter_limit = 5 # => 5
|
@@ -563,6 +715,13 @@ module HexaPDF
|
|
563
715
|
# end
|
564
716
|
# canvas.miter_limit # => 5
|
565
717
|
#
|
718
|
+
# # visual example
|
719
|
+
# [10, 5].each_with_index do |limit, index|
|
720
|
+
# canvas.miter_limit(limit)
|
721
|
+
# canvas.line_width(10).polyline(20 + index * 80, 30, 40 + index * 80, 170,
|
722
|
+
# 60 + index * 80, 30).stroke
|
723
|
+
# end
|
724
|
+
#
|
566
725
|
# See: PDF1.7 s8.4.3.5
|
567
726
|
def miter_limit(limit = nil, &block)
|
568
727
|
gs_getter_setter(:miter_limit, :M, limit, &block)
|
@@ -600,17 +759,25 @@ module HexaPDF
|
|
600
759
|
#
|
601
760
|
# Examples:
|
602
761
|
#
|
762
|
+
# #>pdf
|
603
763
|
# canvas.line_dash_pattern(10)
|
604
764
|
# canvas.line_dash_pattern # => LineDashPattern.new([10], 0)
|
605
765
|
# canvas.line_dash_pattern(10, 2)
|
606
766
|
# canvas.line_dash_pattern([5, 3, 1], 2)
|
607
|
-
# canvas.line_dash_pattern = LineDashPattern.new([5, 3, 1], 1)
|
767
|
+
# canvas.line_dash_pattern = HexaPDF::Content::LineDashPattern.new([5, 3, 1], 1)
|
608
768
|
#
|
609
769
|
# canvas.line_dash_pattern(10) do
|
610
770
|
# canvas.line_dash_pattern # => LineDashPattern.new([10], 0)
|
611
771
|
# end
|
612
772
|
# canvas.line_dash_pattern # => LineDashPattern.new([5, 3, 1], 1)
|
613
773
|
#
|
774
|
+
# # visual example
|
775
|
+
# [10, [10, 2], [[5, 3, 1], 2]].each_with_index do |pattern, index|
|
776
|
+
# canvas.line_dash_pattern(*pattern)
|
777
|
+
# canvas.line_width(10).line(50 + index * 50, 30, 50 + index * 50, 170).
|
778
|
+
# stroke
|
779
|
+
# end
|
780
|
+
#
|
614
781
|
# See: PDF1.7 s8.4.3.5, LineDashPattern
|
615
782
|
def line_dash_pattern(value = nil, phase = 0, &block)
|
616
783
|
gs_getter_setter(:line_dash_pattern, :d, value && LineDashPattern.normalize(value, phase),
|
@@ -675,6 +842,10 @@ module HexaPDF
|
|
675
842
|
# * Three numeric arguments specify an RGB color (see Content::ColorSpace::DeviceRGB::Color).
|
676
843
|
# * A string in the format "RRGGBB" where "RR" is the hexadecimal number for the red, "GG"
|
677
844
|
# for the green and "BB" for the blue color value also specifies an RGB color.
|
845
|
+
# * As does a string in the format "RGB" where "RR", "GG" and "BB" would be used as the
|
846
|
+
# hexadecimal numbers for the red, green and blue color values of an RGB color.
|
847
|
+
# * Any other string is treated as a CSS Color Module Level 3 color name, see
|
848
|
+
# https://www.w3.org/TR/css-color-3/#svg-color.
|
678
849
|
# * Four numeric arguments specify a CMYK color (see Content::ColorSpace::DeviceCMYK::Color).
|
679
850
|
# * A color object is used directly (normally used for color spaces other than DeviceRGB,
|
680
851
|
# DeviceCMYK and DeviceGray).
|
@@ -689,28 +860,36 @@ module HexaPDF
|
|
689
860
|
#
|
690
861
|
# Examples:
|
691
862
|
#
|
863
|
+
# #>pdf
|
864
|
+
# canvas.line_width(5)
|
865
|
+
#
|
692
866
|
# # With no arguments just returns the current color
|
693
867
|
# canvas.stroke_color # => DeviceGray.color(0.0)
|
694
868
|
#
|
695
869
|
# # Same gray color because integer values are normalized to the range of 0.0 to 1.0
|
696
|
-
# canvas.stroke_color(102)
|
697
|
-
# canvas.stroke_color(0.4)
|
870
|
+
# canvas.stroke_color(102).rectangle(10, 170, 20, 20).stroke
|
871
|
+
# canvas.stroke_color(0.4).rectangle(40, 170, 20, 20).stroke
|
698
872
|
#
|
699
|
-
# # Specifying RGB
|
700
|
-
# canvas.stroke_color(255, 255, 0)
|
701
|
-
# canvas.stroke_color(
|
873
|
+
# # Specifying RGB color yellow in all possible formats
|
874
|
+
# canvas.stroke_color(255, 255, 0).rectangle(10, 140, 20, 20).stroke
|
875
|
+
# canvas.stroke_color(1.0, 1.0, 0).rectangle(40, 140, 20, 20).stroke
|
876
|
+
# canvas.stroke_color("FFFF00").rectangle(70, 140, 20, 20).stroke
|
877
|
+
# canvas.stroke_color("FF0").rectangle(100, 140, 20, 20).stroke
|
878
|
+
# canvas.stroke_color("yellow").rectangle(130, 140, 20, 20).stroke
|
702
879
|
#
|
703
880
|
# # Specifying CMYK colors
|
704
|
-
# canvas.stroke_color(
|
881
|
+
# canvas.stroke_color(100, 100, 0, 60).rectangle(10, 110, 20, 20).stroke
|
882
|
+
# canvas.stroke_color(1.0, 1.0, 0, 0.6).rectangle(40, 110, 20, 20).stroke
|
705
883
|
#
|
706
|
-
# # Can use a color object directly
|
707
|
-
# color = HexaPDF::Content::ColorSpace::DeviceRGB.color(
|
708
|
-
# canvas.stroke_color(color)
|
884
|
+
# # Can use a color object directly, only numeric normalization is performed
|
885
|
+
# color = HexaPDF::Content::ColorSpace::DeviceRGB.new.color(0, 255, 0)
|
886
|
+
# canvas.stroke_color(color).rectangle(10, 80, 20, 20).stroke
|
709
887
|
#
|
710
888
|
# # An array argument is destructured - these calls are all equal
|
711
|
-
#
|
712
|
-
# canvas.stroke_color([
|
713
|
-
# canvas.stroke_color = [
|
889
|
+
# canvas.stroke_color(0, 255, 0).rectangle(40, 80, 20, 20).stroke
|
890
|
+
# canvas.stroke_color([0, 255, 0]).rectangle(70, 80, 20, 20).stroke
|
891
|
+
# canvas.stroke_color = [0, 255, 0]
|
892
|
+
# canvas.rectangle(100, 80, 20, 20).stroke
|
714
893
|
#
|
715
894
|
# # As usual, can be invoked with a block to limit the effects
|
716
895
|
# canvas.stroke_color(102) do
|
@@ -725,7 +904,7 @@ module HexaPDF
|
|
725
904
|
|
726
905
|
# The fill color defines the color used for non-stroking operations, i.e. for filling paths.
|
727
906
|
#
|
728
|
-
# Works exactly the same #stroke_color but for the fill color. See #stroke_color for
|
907
|
+
# Works exactly the same as #stroke_color but for the fill color. See #stroke_color for
|
729
908
|
# details on invocation and use.
|
730
909
|
def fill_color(*color, &block)
|
731
910
|
color_getter_setter(:fill_color, color, :rg, :g, :k, :cs, :scn, &block)
|
@@ -753,6 +932,7 @@ module HexaPDF
|
|
753
932
|
#
|
754
933
|
# Examples:
|
755
934
|
#
|
935
|
+
# #>pdf
|
756
936
|
# canvas.opacity(fill_alpha: 0.5)
|
757
937
|
# canvas.opacity # => {fill_alpha: 0.5, stroke_alpha: 1.0}
|
758
938
|
# canvas.opacity(fill_alpha: 0.4, stroke_alpha: 0.9)
|
@@ -763,6 +943,15 @@ module HexaPDF
|
|
763
943
|
# end
|
764
944
|
# canvas.opacity # => {fill_alpha: 0.4, stroke_alpha: 0.9}
|
765
945
|
#
|
946
|
+
# # visual example
|
947
|
+
# canvas.opacity(fill_alpha: 1, stroke_alpha: 1) do # background rectangle on right side
|
948
|
+
# canvas.fill_color("lightgrey").rectangle(100, 0, 100, 200).fill
|
949
|
+
# end
|
950
|
+
# canvas.opacity(fill_alpha: 0.5, stroke_alpha: 0.8). # foreground rectangle, with a thick
|
951
|
+
# line_width(20). # stroke that also overlays the
|
952
|
+
# fill_color("red").stroke_color("blue"). # inside of the rectangle, creating
|
953
|
+
# rectangle(20, 20, 160, 160).fill_stroke # multiple shadings due to opacity
|
954
|
+
#
|
766
955
|
# See: PDF1.7 s11.6.4.4
|
767
956
|
def opacity(fill_alpha: nil, stroke_alpha: nil)
|
768
957
|
if !fill_alpha.nil? || !stroke_alpha.nil?
|
@@ -796,7 +985,10 @@ module HexaPDF
|
|
796
985
|
#
|
797
986
|
# Examples:
|
798
987
|
#
|
799
|
-
# canvas.move_to(
|
988
|
+
# canvas.move_to(10, 50)
|
989
|
+
# canvas.current_point # => [10, 50]
|
990
|
+
#
|
991
|
+
# See: PDF1.7 s8.5.2.1
|
800
992
|
def move_to(x, y)
|
801
993
|
raise_unless_at_page_description_level_or_in_path
|
802
994
|
invoke2(:m, x, y)
|
@@ -813,7 +1005,13 @@ module HexaPDF
|
|
813
1005
|
#
|
814
1006
|
# Examples:
|
815
1007
|
#
|
816
|
-
#
|
1008
|
+
# #>pdf-center
|
1009
|
+
# canvas.move_to(10, 50).
|
1010
|
+
# line_to(80, 80)
|
1011
|
+
# canvas.current_point # => [80, 80]
|
1012
|
+
# canvas.stroke
|
1013
|
+
#
|
1014
|
+
# See: PDF1.7 s8.5.2.1
|
817
1015
|
def line_to(x, y)
|
818
1016
|
raise_unless_in_path
|
819
1017
|
invoke2(:l, x, y)
|
@@ -831,7 +1029,7 @@ module HexaPDF
|
|
831
1029
|
# point becomes the new current point.
|
832
1030
|
#
|
833
1031
|
# A Bezier curve consists of the start point, the end point and the two control points +p1+
|
834
|
-
# and +p2+. The start point is always the current point and the end point is specified as
|
1032
|
+
# and +p2+. The start point is always the current point and the end point is specified as the
|
835
1033
|
# +x+ and +y+ arguments.
|
836
1034
|
#
|
837
1035
|
# Additionally, either the first control point +p1+ or the second control +p2+ or both
|
@@ -841,9 +1039,15 @@ module HexaPDF
|
|
841
1039
|
#
|
842
1040
|
# Examples:
|
843
1041
|
#
|
844
|
-
#
|
845
|
-
# canvas.
|
846
|
-
#
|
1042
|
+
# #>pdf-center
|
1043
|
+
# canvas.move_to(10, 50).
|
1044
|
+
# curve_to(80, 80, p1: [10, 70], p2: [50, 100]).
|
1045
|
+
# curve_to(90, -20, p1: [50, 50]).
|
1046
|
+
# curve_to(-30, 60, p2: [-20, -40])
|
1047
|
+
# canvas.current_point # => [-30, 60]
|
1048
|
+
# canvas.stroke
|
1049
|
+
#
|
1050
|
+
# See: PDF1.7 s8.5.2.2
|
847
1051
|
def curve_to(x, y, p1: nil, p2: nil)
|
848
1052
|
raise_unless_in_path
|
849
1053
|
if p1 && p2
|
@@ -876,8 +1080,13 @@ module HexaPDF
|
|
876
1080
|
#
|
877
1081
|
# Examples:
|
878
1082
|
#
|
879
|
-
#
|
880
|
-
# canvas.rectangle(
|
1083
|
+
# #>pdf
|
1084
|
+
# canvas.rectangle(10, 110, 80, 50).stroke
|
1085
|
+
# canvas.rectangle(110, 110, 80, 50, radius: 10).stroke
|
1086
|
+
# canvas.rectangle(10, 10, 80, 0).stroke # Degraded: Just a line
|
1087
|
+
# canvas.rectangle(110, 10, 0, 0).stroke # Degraded: Draws nothing
|
1088
|
+
#
|
1089
|
+
# See: PDF1.7 s8.5.2.1
|
881
1090
|
def rectangle(x, y, width, height, radius: 0)
|
882
1091
|
raise_unless_at_page_description_level_or_in_path
|
883
1092
|
if radius == 0
|
@@ -895,6 +1104,17 @@ module HexaPDF
|
|
895
1104
|
#
|
896
1105
|
# Closes the current subpath by appending a straight line from the current point to the
|
897
1106
|
# start point of the subpath which also becomes the new current point.
|
1107
|
+
#
|
1108
|
+
# Examples:
|
1109
|
+
#
|
1110
|
+
# #>pdf
|
1111
|
+
# canvas.move_to(10, 10).
|
1112
|
+
# line_to(110, 10).
|
1113
|
+
# line_to(60, 60).
|
1114
|
+
# close_subpath. # Draws the line from (60, 60) to (10, 10)
|
1115
|
+
# stroke
|
1116
|
+
#
|
1117
|
+
# See: PDF1.7 s8.5.2.1
|
898
1118
|
def close_subpath
|
899
1119
|
raise_unless_in_path
|
900
1120
|
invoke0(:h)
|
@@ -911,7 +1131,8 @@ module HexaPDF
|
|
911
1131
|
#
|
912
1132
|
# Examples:
|
913
1133
|
#
|
914
|
-
#
|
1134
|
+
# #>pdf
|
1135
|
+
# canvas.line(10, 10, 100, 100).stroke
|
915
1136
|
def line(x0, y0, x1, y1)
|
916
1137
|
move_to(x0, y0)
|
917
1138
|
line_to(x1, y1)
|
@@ -926,7 +1147,8 @@ module HexaPDF
|
|
926
1147
|
#
|
927
1148
|
# Examples:
|
928
1149
|
#
|
929
|
-
#
|
1150
|
+
# #>pdf
|
1151
|
+
# canvas.polyline(50, 50, 150, 50, 150, 150, 50, 150, 50, 50).stroke
|
930
1152
|
def polyline(*points)
|
931
1153
|
check_poly_points(points)
|
932
1154
|
move_to(points[0], points[1])
|
@@ -950,8 +1172,10 @@ module HexaPDF
|
|
950
1172
|
#
|
951
1173
|
# Examples:
|
952
1174
|
#
|
953
|
-
#
|
954
|
-
# canvas.polygon(
|
1175
|
+
# #>pdf
|
1176
|
+
# canvas.polygon(10, 10, 90, 10, 70, 90, 20, 100).stroke
|
1177
|
+
# canvas.stroke_color("red").
|
1178
|
+
# polygon(130, 130, 150, 100, 170, 150, 130, 190, radius: 10).stroke
|
955
1179
|
def polygon(*points, radius: 0)
|
956
1180
|
if radius == 0
|
957
1181
|
polyline(*points)
|
@@ -959,7 +1183,9 @@ module HexaPDF
|
|
959
1183
|
check_poly_points(points)
|
960
1184
|
move_to(*point_on_line(points[0], points[1], points[2], points[3], distance: radius))
|
961
1185
|
points.concat(points[0, 4])
|
962
|
-
0.step(points.length - 6, 2)
|
1186
|
+
0.step(points.length - 6, 2) do |i|
|
1187
|
+
line_with_rounded_corner(*points[i, 6], in_radius: radius)
|
1188
|
+
end
|
963
1189
|
end
|
964
1190
|
close_subpath
|
965
1191
|
end
|
@@ -975,7 +1201,8 @@ module HexaPDF
|
|
975
1201
|
#
|
976
1202
|
# Examples:
|
977
1203
|
#
|
978
|
-
#
|
1204
|
+
# #>pdf
|
1205
|
+
# canvas.circle(100, 100, 30).stroke
|
979
1206
|
#
|
980
1207
|
# See: #arc (for approximation accuracy)
|
981
1208
|
def circle(cx, cy, radius)
|
@@ -994,11 +1221,13 @@ module HexaPDF
|
|
994
1221
|
#
|
995
1222
|
# Examples:
|
996
1223
|
#
|
1224
|
+
# #>pdf
|
997
1225
|
# # Ellipse aligned to x-axis and y-axis
|
998
|
-
# canvas.ellipse(
|
1226
|
+
# canvas.ellipse(50, 50, a: 20, b: 10).stroke
|
999
1227
|
#
|
1000
1228
|
# # Inclined ellipse
|
1001
|
-
# canvas.
|
1229
|
+
# canvas.stroke_color("red").
|
1230
|
+
# ellipse(150, 150, a: 20, b: 10, inclination: 30).stroke
|
1002
1231
|
#
|
1003
1232
|
# See: #arc (for approximation accuracy)
|
1004
1233
|
def ellipse(cx, cy, a:, b:, inclination: 0)
|
@@ -1032,7 +1261,7 @@ module HexaPDF
|
|
1032
1261
|
#
|
1033
1262
|
# +clockwise+::
|
1034
1263
|
# If +true+ the arc is drawn in clockwise direction, otherwise in counterclockwise
|
1035
|
-
# direction.
|
1264
|
+
# direction (default: false).
|
1036
1265
|
#
|
1037
1266
|
# +inclination+::
|
1038
1267
|
# Angle in degrees between the x-axis and the semi-major axis (default: 0)
|
@@ -1048,18 +1277,24 @@ module HexaPDF
|
|
1048
1277
|
#
|
1049
1278
|
# Examples:
|
1050
1279
|
#
|
1051
|
-
#
|
1052
|
-
# canvas.arc(
|
1053
|
-
# canvas.arc(
|
1280
|
+
# #>pdf
|
1281
|
+
# canvas.arc(50, 150, a: 10) # Circle with radius 10
|
1282
|
+
# canvas.arc(100, 150, a: 10, b: 5) # Ellipse with radii 10 and 5
|
1283
|
+
# canvas.arc(150, 150, a: 10, b: 5, inclination: 45) # The above ellipse inclined 45 degrees
|
1284
|
+
# canvas.stroke
|
1054
1285
|
#
|
1055
|
-
# # Circular and elliptical arcs from
|
1056
|
-
# canvas.
|
1057
|
-
# canvas.arc(
|
1286
|
+
# # Circular and elliptical arcs from 30 degrees to 160 degrees
|
1287
|
+
# canvas.stroke_color("red")
|
1288
|
+
# canvas.arc(50, 100, a: 10, start_angle: 30, end_angle: 160)
|
1289
|
+
# canvas.arc(100, 100, a: 10, b: 5, start_angle: 30, end_angle: 160)
|
1290
|
+
# canvas.stroke
|
1058
1291
|
#
|
1059
|
-
# # Arcs from 135 degrees to
|
1292
|
+
# # Arcs from 135 degrees to 30 degrees, the first in counterclockwise direction (i.e. the
|
1060
1293
|
# # big arc), the other in clockwise direction (i.e. the small arc)
|
1061
|
-
# canvas.
|
1062
|
-
# canvas.arc(
|
1294
|
+
# canvas.stroke_color("blue")
|
1295
|
+
# canvas.arc(50, 50, a: 10, start_angle: 135, end_angle: 30)
|
1296
|
+
# canvas.arc(100, 50, a: 10, start_angle: 135, end_angle: 30, clockwise: true)
|
1297
|
+
# canvas.stroke
|
1063
1298
|
#
|
1064
1299
|
# See: Content::GraphicObject::Arc
|
1065
1300
|
def arc(cx, cy, a:, b: a, start_angle: 0, end_angle: 360, clockwise: false, inclination: 0)
|
@@ -1070,6 +1305,62 @@ module HexaPDF
|
|
1070
1305
|
self
|
1071
1306
|
end
|
1072
1307
|
|
1308
|
+
# Used for calculating the optimal distance of the control points for
|
1309
|
+
# #line_with_rounded_corner.
|
1310
|
+
#
|
1311
|
+
# See: http://itc.ktu.lt/itc354/Riskus354.pdf, p373 right column
|
1312
|
+
KAPPA = 0.55191496 #:nodoc:
|
1313
|
+
|
1314
|
+
# :call-seq:
|
1315
|
+
# canvas.line_with_rounded_corner(x0 = current_point[0], y0 = current_point[1], x1, y1, x2, y2, in_radius:, out_radius: in_radius)
|
1316
|
+
#
|
1317
|
+
# Appends a line with a rounded corner at (x1, y1) from the current point. The end point of
|
1318
|
+
# the rounded corner (i.e. +out_radius+ units from (x1, y1) in the direction of (x2, y2))
|
1319
|
+
# becomes the current point. In degraded cases the corner point (x1, y1) becomes the current
|
1320
|
+
# point.
|
1321
|
+
#
|
1322
|
+
# The corner is specified by (x0, y0) which defaults to the #current_point of the path, (x1,
|
1323
|
+
# y1) and (x2, y2) - all of which need to be different points. The +in_radius+ specifies the
|
1324
|
+
# corner radius into the corner and the +out_radius+ the one out of the corner. Degraded
|
1325
|
+
# cases, like with (x0, y0) == (x1, y1), are handled gracefully.
|
1326
|
+
#
|
1327
|
+
# There has to be a current path when this method is invoked. For example, the current point
|
1328
|
+
# ould be estabilshed beforehand using #move_to.
|
1329
|
+
#
|
1330
|
+
# Examples:
|
1331
|
+
#
|
1332
|
+
# #>pdf
|
1333
|
+
# canvas.move_to(10, 180) # Both radii are the same
|
1334
|
+
# canvas.line_with_rounded_corner(180, 180, 180, 100, in_radius: 20)
|
1335
|
+
# canvas.move_to(10, 150) # Different radii
|
1336
|
+
# canvas.line_with_rounded_corner(180, 150, 180, 100, in_radius: 50, out_radius: 20)
|
1337
|
+
# canvas.move_to(10, 120) # One radius is zero, making it just a line
|
1338
|
+
# canvas.line_with_rounded_corner(180, 120, 150, 100, in_radius: 0, out_radius: 10)
|
1339
|
+
# canvas.stroke
|
1340
|
+
#
|
1341
|
+
# # Special effects when (x0, y0) is not the current point, like when the current point
|
1342
|
+
# # would be equal to the corner point
|
1343
|
+
# canvas.rectangle(10, 10, 60, 60, radius: 60).stroke
|
1344
|
+
# canvas.rectangle(110, 10, 60, 60, radius: 70).stroke
|
1345
|
+
def line_with_rounded_corner(x0 = current_point[0], y0 = current_point[1], x1, y1, x2, y2,
|
1346
|
+
in_radius:, out_radius: in_radius)
|
1347
|
+
if in_radius == 0 || out_radius == 0
|
1348
|
+
line_to(x1, y1)
|
1349
|
+
else
|
1350
|
+
p0 = point_on_line(x1, y1, x0, y0, distance: in_radius)
|
1351
|
+
p3 = point_on_line(x1, y1, x2, y2, distance: out_radius)
|
1352
|
+
p1 = point_on_line(p0[0], p0[1], x1, y1, distance: KAPPA * in_radius)
|
1353
|
+
p2 = point_on_line(p3[0], p3[1], x1, y1, distance: KAPPA * out_radius)
|
1354
|
+
if p0[0].finite? && p3[0].finite?
|
1355
|
+
line_to(*p0)
|
1356
|
+
curve_to(p3[0], p3[1], p1: p1, p2: p2)
|
1357
|
+
else
|
1358
|
+
line_to(x1, y1)
|
1359
|
+
end
|
1360
|
+
end
|
1361
|
+
self
|
1362
|
+
end
|
1363
|
+
|
1073
1364
|
# :call-seq:
|
1074
1365
|
# canvas.graphic_object(obj, **options) => obj
|
1075
1366
|
# canvas.graphic_object(name, **options) => graphic_object
|
@@ -1082,8 +1373,12 @@ module HexaPDF
|
|
1082
1373
|
#
|
1083
1374
|
# Examples:
|
1084
1375
|
#
|
1085
|
-
#
|
1086
|
-
# canvas.
|
1376
|
+
# #>pdf
|
1377
|
+
# obj = canvas.graphic_object(:solid_arc, cx: 100, cy: 100, inner_a: 20, inner_b: 10,
|
1378
|
+
# outer_a: 50, outer_b: 40, end_angle: 135)
|
1379
|
+
# canvas.draw(obj).stroke
|
1380
|
+
#
|
1381
|
+
# See: Content::GraphicObject
|
1087
1382
|
def graphic_object(obj, **options)
|
1088
1383
|
unless obj.respond_to?(:configure)
|
1089
1384
|
obj = context.document.config.constantize('graphic_object.map', obj)
|
@@ -1098,11 +1393,9 @@ module HexaPDF
|
|
1098
1393
|
#
|
1099
1394
|
# Draws the given graphic object on the canvas.
|
1100
1395
|
#
|
1101
|
-
#
|
1102
|
-
#
|
1103
|
-
# Examples:
|
1396
|
+
# This is the same as "graphic_object(obj_or_name, **options).draw(self)".
|
1104
1397
|
#
|
1105
|
-
#
|
1398
|
+
# See #graphic_object for details on the arguments and invocation.
|
1106
1399
|
def draw(name, **options)
|
1107
1400
|
graphic_object(name, **options).draw(self)
|
1108
1401
|
self
|
@@ -1113,6 +1406,12 @@ module HexaPDF
|
|
1113
1406
|
#
|
1114
1407
|
# Strokes the path.
|
1115
1408
|
#
|
1409
|
+
# Examples:
|
1410
|
+
#
|
1411
|
+
# #>pdf
|
1412
|
+
# canvas.polyline(10, 10, 120, 40, 50, 160)
|
1413
|
+
# canvas.stroke
|
1414
|
+
#
|
1116
1415
|
# See: PDF1.7 s8.5.3.1, s8.5.3.2
|
1117
1416
|
def stroke
|
1118
1417
|
raise_unless_in_path_or_clipping_path
|
@@ -1125,6 +1424,12 @@ module HexaPDF
|
|
1125
1424
|
#
|
1126
1425
|
# Closes the last subpath and then strokes the path.
|
1127
1426
|
#
|
1427
|
+
# Examples:
|
1428
|
+
#
|
1429
|
+
# #>pdf
|
1430
|
+
# canvas.polyline(10, 10, 120, 40, 50, 160) # No line from the top to the left
|
1431
|
+
# canvas.close_stroke
|
1432
|
+
#
|
1128
1433
|
# See: PDF1.7 s8.5.3.1, s8.5.3.2
|
1129
1434
|
def close_stroke
|
1130
1435
|
raise_unless_in_path_or_clipping_path
|
@@ -1138,10 +1443,21 @@ module HexaPDF
|
|
1138
1443
|
# Fills the path using the given rule.
|
1139
1444
|
#
|
1140
1445
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1141
|
-
# +:even_odd+ to use the even-odd rule for determining which regions to fill in.
|
1446
|
+
# +:even_odd+ to use the even-odd rule for determining which regions to fill in. Details on
|
1447
|
+
# how these rules work are found in the PDF 1.7 spec section 8.5.3.3 or via Internet search.
|
1142
1448
|
#
|
1143
1449
|
# Any open subpaths are implicitly closed before being filled.
|
1144
1450
|
#
|
1451
|
+
# Examples:
|
1452
|
+
#
|
1453
|
+
# #>pdf
|
1454
|
+
# canvas.polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90)
|
1455
|
+
# canvas.fill
|
1456
|
+
#
|
1457
|
+
# canvas.fill_color("red")
|
1458
|
+
# canvas.polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190)
|
1459
|
+
# canvas.fill(:even_odd)
|
1460
|
+
#
|
1145
1461
|
# See: PDF1.7 s8.5.3.1, s8.5.3.3
|
1146
1462
|
def fill(rule = :nonzero)
|
1147
1463
|
raise_unless_in_path_or_clipping_path
|
@@ -1155,9 +1471,23 @@ module HexaPDF
|
|
1155
1471
|
# Fills and then strokes the path using the given rule.
|
1156
1472
|
#
|
1157
1473
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1158
|
-
# +:even_odd+ to use the even-odd rule for determining which regions to fill in.
|
1474
|
+
# +:even_odd+ to use the even-odd rule for determining which regions to fill in. Details on
|
1475
|
+
# how these rules work are found in the PDF 1.7 spec section 8.5.3.3 or via Internet search.
|
1159
1476
|
#
|
1160
|
-
#
|
1477
|
+
# Note that any open subpaths are *not* closed!
|
1478
|
+
#
|
1479
|
+
# Examples:
|
1480
|
+
#
|
1481
|
+
# #>pdf
|
1482
|
+
# canvas.stroke_color("green").line_width(3)
|
1483
|
+
# canvas.polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90)
|
1484
|
+
# canvas.fill_stroke # Note the missing stroke from the top corner
|
1485
|
+
#
|
1486
|
+
# canvas.fill_color("red")
|
1487
|
+
# canvas.polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190)
|
1488
|
+
# canvas.fill_stroke(:even_odd) # Note the missing stroke from the top corner
|
1489
|
+
#
|
1490
|
+
# See: PDF1.7 s8.5.3.1, s8.5.3.3
|
1161
1491
|
def fill_stroke(rule = :nonzero)
|
1162
1492
|
raise_unless_in_path_or_clipping_path
|
1163
1493
|
invoke0(rule == :nonzero ? :B : :'B*')
|
@@ -1170,7 +1500,19 @@ module HexaPDF
|
|
1170
1500
|
# Closes the last subpath and then fills and strokes the path using the given rule.
|
1171
1501
|
#
|
1172
1502
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1173
|
-
# +:even_odd+ to use the even-odd rule for determining which regions to fill in.
|
1503
|
+
# +:even_odd+ to use the even-odd rule for determining which regions to fill in. Details on
|
1504
|
+
# how these rules work are found in the PDF 1.7 spec section 8.5.3.3 or via Internet search.
|
1505
|
+
#
|
1506
|
+
# Examples:
|
1507
|
+
#
|
1508
|
+
# #>pdf
|
1509
|
+
# canvas.stroke_color("green").line_width(3)
|
1510
|
+
# canvas.polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90)
|
1511
|
+
# canvas.close_fill_stroke
|
1512
|
+
#
|
1513
|
+
# canvas.fill_color("red")
|
1514
|
+
# canvas.polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190)
|
1515
|
+
# canvas.close_fill_stroke(:even_odd)
|
1174
1516
|
#
|
1175
1517
|
# See: PDF1.7 s8.5.3
|
1176
1518
|
def close_fill_stroke(rule = :nonzero)
|
@@ -1187,7 +1529,12 @@ module HexaPDF
|
|
1187
1529
|
# This method is normally used in conjunction with the clipping path methods to define the
|
1188
1530
|
# clipping.
|
1189
1531
|
#
|
1190
|
-
#
|
1532
|
+
# Examples:
|
1533
|
+
#
|
1534
|
+
# canvas.line(10, 10, 100, 100)
|
1535
|
+
# canvas.end_path # Nothing to see here!
|
1536
|
+
#
|
1537
|
+
# See: PDF1.7 s8.5.3.1, #clip_path
|
1191
1538
|
def end_path
|
1192
1539
|
raise_unless_in_path_or_clipping_path
|
1193
1540
|
invoke0(:n)
|
@@ -1201,11 +1548,24 @@ module HexaPDF
|
|
1201
1548
|
#
|
1202
1549
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1203
1550
|
# +:even_odd+ to use the even-odd rule for determining which regions lie inside the clipping
|
1204
|
-
# path.
|
1551
|
+
# path. Details on how these rules work are found in the PDF 1.7 spec section 8.5.3.3 or via
|
1552
|
+
# Internet search.
|
1553
|
+
#
|
1554
|
+
# The initial clipping path includes the entire canvas. Once the clipping path is reduced to a
|
1555
|
+
# subset of the canvas, there is no way to enlarge it. To restrict the effect of this method,
|
1556
|
+
# use #save_graphics_state before modifying the clipping path.
|
1205
1557
|
#
|
1206
1558
|
# Note that the current path cannot be modified after invoking this method! This means that
|
1207
1559
|
# one of the path painting methods or #end_path must be called immediately afterwards.
|
1208
1560
|
#
|
1561
|
+
# Examples:
|
1562
|
+
#
|
1563
|
+
# #>pdf
|
1564
|
+
# canvas.ellipse(100, 100, a: 50, b: 30). # Restrict operations to this intersecting path
|
1565
|
+
# ellipse(100, 100, a: 30, b: 50). # where the inside is not part of it
|
1566
|
+
# clip_path(:even_odd).end_path
|
1567
|
+
# canvas.rectangle(0, 0, 200, 200).fill # Fills everything inside the clipping path
|
1568
|
+
#
|
1209
1569
|
# See: PDF1.7 s8.5.4
|
1210
1570
|
def clip_path(rule = :nonzero)
|
1211
1571
|
raise_unless_in_path
|
@@ -1245,15 +1605,19 @@ module HexaPDF
|
|
1245
1605
|
#
|
1246
1606
|
# Examples:
|
1247
1607
|
#
|
1248
|
-
#
|
1249
|
-
# canvas.xobject(
|
1608
|
+
# #>pdf
|
1609
|
+
# canvas.xobject(machu_picchu, at: [10, 10], width: 90) # bottom left
|
1250
1610
|
#
|
1251
|
-
# File.new(
|
1252
|
-
#
|
1253
|
-
# end
|
1611
|
+
# file = File.new(machu_picchu, 'rb') # top left
|
1612
|
+
# canvas.xobject(file, at: [10, 110], height: 50)
|
1254
1613
|
#
|
1255
|
-
# image =
|
1256
|
-
# canvas.xobject(image, at: [
|
1614
|
+
# image = doc.images.add(machu_picchu)
|
1615
|
+
# canvas.xobject(image, at: [110, 10], width: 50, height: 90) # bottom right
|
1616
|
+
#
|
1617
|
+
# form = doc.add({Type: :XObject, Subtype: :Form, BBox: [0, 0, 100, 100]})
|
1618
|
+
# form.canvas.line(10, 10, 90, 90).stroke
|
1619
|
+
# canvas.line_width = 20
|
1620
|
+
# canvas.xobject(form, at: [100, 100]) # top right
|
1257
1621
|
#
|
1258
1622
|
# See: PDF1.7 s8.8, s.8.10.1
|
1259
1623
|
def xobject(obj, at:, width: nil, height: nil)
|
@@ -1298,6 +1662,7 @@ module HexaPDF
|
|
1298
1662
|
#
|
1299
1663
|
# Examples:
|
1300
1664
|
#
|
1665
|
+
# #>pdf
|
1301
1666
|
# canvas.character_spacing(0.25)
|
1302
1667
|
# canvas.character_spacing # => 0.25
|
1303
1668
|
# canvas.character_spacing = 0.5 # => 0.5
|
@@ -1307,6 +1672,13 @@ module HexaPDF
|
|
1307
1672
|
# end
|
1308
1673
|
# canvas.character_spacing # => 0.5
|
1309
1674
|
#
|
1675
|
+
# # visual example
|
1676
|
+
# canvas.font("Helvetica", size: 10)
|
1677
|
+
# canvas.character_spacing = 0 # initial value
|
1678
|
+
# canvas.text("This is an example text.", at: [10, 150])
|
1679
|
+
# canvas.character_spacing = 3
|
1680
|
+
# canvas.text("This is an example text.", at: [10, 100])
|
1681
|
+
#
|
1310
1682
|
# See: PDF1.7 s9.3.2
|
1311
1683
|
def character_spacing(amount = nil, &bk)
|
1312
1684
|
gs_getter_setter(:character_spacing, :Tc, amount, &bk)
|
@@ -1323,8 +1695,8 @@ module HexaPDF
|
|
1323
1695
|
# writing positive values increase the distance between two words, whereas for vertical
|
1324
1696
|
# writing negative values increase the distance.
|
1325
1697
|
#
|
1326
|
-
#
|
1327
|
-
# any other font, for example a TrueType font, this property has no effect.
|
1698
|
+
# *Important*: In HexaPDF only the standard 14 PDF Type1 fonts support this property! When
|
1699
|
+
# using any other font, for example a TrueType font, this property has no effect.
|
1328
1700
|
#
|
1329
1701
|
# Returns the current word spacing value (see Content::GraphicsState#word_spacing) when no
|
1330
1702
|
# argument is given. Otherwise sets the word spacing using the +amount+ argument and returns
|
@@ -1335,6 +1707,7 @@ module HexaPDF
|
|
1335
1707
|
#
|
1336
1708
|
# Examples:
|
1337
1709
|
#
|
1710
|
+
# #>pdf
|
1338
1711
|
# canvas.word_spacing(0.25)
|
1339
1712
|
# canvas.word_spacing # => 0.25
|
1340
1713
|
# canvas.word_spacing = 0.5 # => 0.5
|
@@ -1344,6 +1717,13 @@ module HexaPDF
|
|
1344
1717
|
# end
|
1345
1718
|
# canvas.word_spacing # => 0.5
|
1346
1719
|
#
|
1720
|
+
# # visual example
|
1721
|
+
# canvas.font("Helvetica", size: 10)
|
1722
|
+
# canvas.word_spacing = 0 # initial value
|
1723
|
+
# canvas.text("This is an example text.", at: [10, 150])
|
1724
|
+
# canvas.word_spacing = 10
|
1725
|
+
# canvas.text("This is an example text.", at: [10, 100])
|
1726
|
+
#
|
1347
1727
|
# See: PDF1.7 s9.3.3
|
1348
1728
|
def word_spacing(amount = nil, &bk)
|
1349
1729
|
gs_getter_setter(:word_spacing, :Tw, amount, &bk)
|
@@ -1357,7 +1737,7 @@ module HexaPDF
|
|
1357
1737
|
#
|
1358
1738
|
# The horizontal scaling adjusts the width of text character glyphs by stretching or
|
1359
1739
|
# compressing them in the horizontal direction. The value is specified as percent of the
|
1360
|
-
# normal width.
|
1740
|
+
# normal width, so 100 means no scaling.
|
1361
1741
|
#
|
1362
1742
|
# Returns the current horizontal scaling value (see Content::GraphicsState#horizontal_scaling)
|
1363
1743
|
# when no argument is given. Otherwise sets the horizontal scaling using the +percent+
|
@@ -1369,6 +1749,7 @@ module HexaPDF
|
|
1369
1749
|
#
|
1370
1750
|
# Examples:
|
1371
1751
|
#
|
1752
|
+
# #>pdf
|
1372
1753
|
# canvas.horizontal_scaling(50) # each glyph has only 50% width
|
1373
1754
|
# canvas.horizontal_scaling # => 50
|
1374
1755
|
# canvas.horizontal_scaling = 125 # => 125
|
@@ -1378,6 +1759,13 @@ module HexaPDF
|
|
1378
1759
|
# end
|
1379
1760
|
# canvas.horizontal_scaling # => 125
|
1380
1761
|
#
|
1762
|
+
# # visual example
|
1763
|
+
# canvas.font("Helvetica", size: 10)
|
1764
|
+
# canvas.horizontal_scaling = 100 # initial value
|
1765
|
+
# canvas.text("This is an example text.", at: [10, 150])
|
1766
|
+
# canvas.horizontal_scaling = 50
|
1767
|
+
# canvas.text("This is an example text.", at: [10, 100])
|
1768
|
+
#
|
1381
1769
|
# See: PDF1.7 s9.3.4
|
1382
1770
|
def horizontal_scaling(amount = nil, &bk)
|
1383
1771
|
gs_getter_setter(:horizontal_scaling, :Tz, amount, &bk)
|
@@ -1389,7 +1777,12 @@ module HexaPDF
|
|
1389
1777
|
# canvas.leading(amount) => canvas
|
1390
1778
|
# canvas.leading(amount) { block } => canvas
|
1391
1779
|
#
|
1392
|
-
# The leading specifies the vertical distance between the baselines of adjacent text lines.
|
1780
|
+
# The leading specifies the vertical distance between the baselines of adjacent text lines. It
|
1781
|
+
# defaults to 0 if not changed.
|
1782
|
+
#
|
1783
|
+
# It is *only* used by HexaPDF when invoking #move_text_cursor with +offset+ set to +nil+.
|
1784
|
+
# There are other PDF content stream operators that would be effected but those are not used
|
1785
|
+
# by the canvas.
|
1393
1786
|
#
|
1394
1787
|
# Returns the current leading value (see Content::GraphicsState#leading) when no argument is
|
1395
1788
|
# given. Otherwise sets the leading using the +amount+ argument and returns self. The setter
|
@@ -1400,6 +1793,7 @@ module HexaPDF
|
|
1400
1793
|
#
|
1401
1794
|
# Examples:
|
1402
1795
|
#
|
1796
|
+
# #>pdf
|
1403
1797
|
# canvas.leading(14.5)
|
1404
1798
|
# canvas.leading # => 14.5
|
1405
1799
|
# canvas.leading = 10 # => 10
|
@@ -1409,7 +1803,12 @@ module HexaPDF
|
|
1409
1803
|
# end
|
1410
1804
|
# canvas.leading # => 10
|
1411
1805
|
#
|
1412
|
-
#
|
1806
|
+
# # visual example
|
1807
|
+
# canvas.font("Helvetica", size: 10)
|
1808
|
+
# canvas.leading = 15
|
1809
|
+
# canvas.text("This is an example text.\nwith a second\nand thrid line", at: [10, 150])
|
1810
|
+
#
|
1811
|
+
# See: PDF1.7 s9.3.5, #move_text_cursor
|
1413
1812
|
def leading(amount = nil, &bk)
|
1414
1813
|
gs_getter_setter(:leading, :TL, amount, &bk)
|
1415
1814
|
end
|
@@ -1436,6 +1835,7 @@ module HexaPDF
|
|
1436
1835
|
#
|
1437
1836
|
# Examples:
|
1438
1837
|
#
|
1838
|
+
# #>pdf
|
1439
1839
|
# canvas.text_rendering_mode(:fill)
|
1440
1840
|
# canvas.text_rendering_mode # => #<NamedValue @name=:fill, @value = 0>
|
1441
1841
|
# canvas.text_rendering_mode = :stroke # => #<NamedValue @name=:stroke, @value = 1>
|
@@ -1445,7 +1845,15 @@ module HexaPDF
|
|
1445
1845
|
# end
|
1446
1846
|
# canvas.text_rendering_mode # => #<NamedValue @name=:stroke, @value = 1>
|
1447
1847
|
#
|
1448
|
-
#
|
1848
|
+
# # visual example
|
1849
|
+
# canvas.font("Helvetica", size: 25)
|
1850
|
+
# canvas.stroke_color("green")
|
1851
|
+
# [:fill, :stroke, :fill_stroke, :invisible].each_with_index do |trm, index|
|
1852
|
+
# canvas.text_rendering_mode = trm
|
1853
|
+
# canvas.text("#{trm} text.", at: [20, 150 - 30 * index])
|
1854
|
+
# end
|
1855
|
+
#
|
1856
|
+
# See: PDF1.7 s9.3.6, Content::GraphicsState::TextRenderingMode
|
1449
1857
|
def text_rendering_mode(m = nil, &bk)
|
1450
1858
|
gs_getter_setter(:text_rendering_mode, :Tr, m && TextRenderingMode.normalize(m), &bk)
|
1451
1859
|
end
|
@@ -1468,6 +1876,7 @@ module HexaPDF
|
|
1468
1876
|
#
|
1469
1877
|
# Examples:
|
1470
1878
|
#
|
1879
|
+
# #>pdf
|
1471
1880
|
# canvas.text_rise(5)
|
1472
1881
|
# canvas.text_rise # => 5
|
1473
1882
|
# canvas.text_rise = 10 # => 10
|
@@ -1477,6 +1886,15 @@ module HexaPDF
|
|
1477
1886
|
# end
|
1478
1887
|
# canvas.text_rise # => 10
|
1479
1888
|
#
|
1889
|
+
# # visual example
|
1890
|
+
# canvas.font("Helvetica", size: 10)
|
1891
|
+
# canvas.text_rise = 0 # Set the default value
|
1892
|
+
# canvas.text("Hello", at: [20, 150])
|
1893
|
+
# canvas.text_rise = 10
|
1894
|
+
# canvas.text("from up here")
|
1895
|
+
# canvas.text_rise = -10
|
1896
|
+
# canvas.text("and also down here")
|
1897
|
+
#
|
1480
1898
|
# See: PDF1.7 s9.3.7
|
1481
1899
|
def text_rise(amount = nil, &bk)
|
1482
1900
|
gs_getter_setter(:text_rise, :Ts, amount, &bk)
|
@@ -1491,6 +1909,9 @@ module HexaPDF
|
|
1491
1909
|
# If +force+ is +true+ and the current graphics object is already a text object, it is ended
|
1492
1910
|
# and a new text object is begun.
|
1493
1911
|
#
|
1912
|
+
# It is not necessary to invoke this method manually in most cases since it is automatically
|
1913
|
+
# called when needed by other methods, i.e. the #text method.
|
1914
|
+
#
|
1494
1915
|
# See: PDF1.7 s9.4.1
|
1495
1916
|
def begin_text(force_new: false)
|
1496
1917
|
raise_unless_at_page_description_level_or_in_text
|
@@ -1504,6 +1925,9 @@ module HexaPDF
|
|
1504
1925
|
#
|
1505
1926
|
# Ends the current text object.
|
1506
1927
|
#
|
1928
|
+
# It is not necessary to invoke this method manually in most cases since it is automatically
|
1929
|
+
# called when needed by other methods, i.e. when creating a new path.
|
1930
|
+
#
|
1507
1931
|
# See: PDF1.7 s9.4.1
|
1508
1932
|
def end_text
|
1509
1933
|
raise_unless_at_page_description_level_or_in_text
|
@@ -1522,10 +1946,19 @@ module HexaPDF
|
|
1522
1946
|
# c d 0
|
1523
1947
|
# e f 1
|
1524
1948
|
#
|
1949
|
+
# If the current graphics object is not a text object, #begin_text is automatically called
|
1950
|
+
# because the text matrix is only available within a text object.
|
1951
|
+
#
|
1525
1952
|
# Examples:
|
1526
1953
|
#
|
1527
|
-
#
|
1528
|
-
# canvas.
|
1954
|
+
# #>pdf
|
1955
|
+
# canvas.font("Helvetica", size: 10)
|
1956
|
+
# canvas.begin_text # Not necessary
|
1957
|
+
# canvas.text_matrix(1, 0, 0, 1, 50, 100) # Translate text origin to (50, 100)
|
1958
|
+
# canvas.text("This is some text")
|
1959
|
+
#
|
1960
|
+
# canvas.text_matrix(2, 1, 3, 0.5, 50, 50)
|
1961
|
+
# canvas.text("This is some text")
|
1529
1962
|
#
|
1530
1963
|
# See: PDF1.7 s9.4.2
|
1531
1964
|
def text_matrix(a, b, c, d, e, f)
|
@@ -1555,7 +1988,24 @@ module HexaPDF
|
|
1555
1988
|
# offset from the start of the current line (the origin of the text line matrix) by
|
1556
1989
|
# +offset+.
|
1557
1990
|
#
|
1558
|
-
#
|
1991
|
+
# If the current graphics object is not a text object, #begin_text is automatically called
|
1992
|
+
# because the text matrix is only available within a text object.
|
1993
|
+
#
|
1994
|
+
# Examples:
|
1995
|
+
#
|
1996
|
+
# #>pdf
|
1997
|
+
# canvas.font("Helvetica", size: 10)
|
1998
|
+
# canvas.move_text_cursor(offset: [30, 150])
|
1999
|
+
# canvas.text("Absolutely positioned at (30, 150)")
|
2000
|
+
#
|
2001
|
+
# canvas.move_text_cursor(offset: [20, -15], absolute: false)
|
2002
|
+
# canvas.text("Relative offset (20, -15)")
|
2003
|
+
#
|
2004
|
+
# canvas.leading(30)
|
2005
|
+
# canvas.move_text_cursor
|
2006
|
+
# canvas.text("Text on next line with leading=30")
|
2007
|
+
#
|
2008
|
+
# See: PDF1.7 s9.4.2, #show_glyphs
|
1559
2009
|
def move_text_cursor(offset: nil, absolute: true)
|
1560
2010
|
begin_text
|
1561
2011
|
if offset
|
@@ -1577,6 +2027,18 @@ module HexaPDF
|
|
1577
2027
|
#
|
1578
2028
|
# Note that this method can only be called while the current graphic object is a text object
|
1579
2029
|
# since the text matrix is otherwise undefined.
|
2030
|
+
#
|
2031
|
+
# Examples:
|
2032
|
+
#
|
2033
|
+
# #>pdf
|
2034
|
+
# canvas.font("Helvetica", size: 10)
|
2035
|
+
# canvas.text("Some sample text", at: [30, 150])
|
2036
|
+
# pos = canvas.text_cursor # Cursor is directly after the text
|
2037
|
+
# canvas.line_width(0.5).stroke_color("red").
|
2038
|
+
# polyline(pos[0], pos[1] + 10, pos[0], pos[1], pos[0] + 10, pos[1]).stroke
|
2039
|
+
# canvas.text("Last cursor: #{pos.map! {|f| f.round(2)}.join(", ")}", at: [30, 100])
|
2040
|
+
#
|
2041
|
+
# See: #move_text_cursor
|
1580
2042
|
def text_cursor
|
1581
2043
|
raise_unless_in_text
|
1582
2044
|
graphics_state.tm.evaluate(0, 0)
|
@@ -1586,26 +2048,34 @@ module HexaPDF
|
|
1586
2048
|
# canvas.font => current_font
|
1587
2049
|
# canvas.font(name, size: nil, **options) => canvas
|
1588
2050
|
#
|
1589
|
-
# Specifies the font that should be used when showing text.
|
2051
|
+
# Specifies the font and optional the font size that should be used when showing text.
|
1590
2052
|
#
|
1591
|
-
# A valid font size need to be provided on the first invocation, otherwise an error is raised
|
2053
|
+
# A valid font size need to be provided on the first invocation, otherwise an error is raised
|
2054
|
+
# (this is due to how setting a font works with PDFs).
|
1592
2055
|
#
|
1593
|
-
#
|
1594
|
-
# the font!
|
2056
|
+
# If +size+ is specified, the #font_size method is invoked with it as argument.
|
1595
2057
|
#
|
1596
|
-
#
|
1597
|
-
#
|
1598
|
-
#
|
2058
|
+
# All other options are passed on to the font loaders (see HexaPDF::FontLoader) that are used
|
2059
|
+
# for loading the specified font. One standard keyword argument for fonts is +:variant+ which
|
2060
|
+
# specifies the font variant to use, with standard values of :none, :italic, :bold and
|
2061
|
+
# :bold_italic.
|
1599
2062
|
#
|
1600
|
-
# Returns the current font object when no argument is given.
|
2063
|
+
# Returns the current font object when no argument is given. *Note* that this is the font
|
2064
|
+
# object itself, not the PDF dictionary representing the font.
|
1601
2065
|
#
|
1602
2066
|
# Examples:
|
1603
2067
|
#
|
1604
|
-
#
|
2068
|
+
# #>pdf
|
2069
|
+
# canvas.font("Times", variant: :bold, size: 10)
|
1605
2070
|
# canvas.font # => font object
|
1606
2071
|
# canvas.font = "Times"
|
1607
2072
|
#
|
1608
|
-
#
|
2073
|
+
# # visual example
|
2074
|
+
# canvas.text("Times at size 10", at: [10, 150])
|
2075
|
+
# canvas.font("Times", variant: :bold_italic, size: 15)
|
2076
|
+
# canvas.text("Times bold+italic at size 15", at: [10, 100])
|
2077
|
+
#
|
2078
|
+
# See: PDF1.7 s9.2.2, #font_size
|
1609
2079
|
def font(name = nil, size: nil, **options)
|
1610
2080
|
if name
|
1611
2081
|
@font = (name.respond_to?(:pdf_object) ? name : context.document.fonts.add(name, **options))
|
@@ -1629,17 +2099,27 @@ module HexaPDF
|
|
1629
2099
|
#
|
1630
2100
|
# Specifies the font size.
|
1631
2101
|
#
|
1632
|
-
# Note that an error is raised if no font has been set before
|
2102
|
+
# Note that an error is raised if no font has been set before via #font (this is due to how
|
2103
|
+
# setting font and font size works in PDF).
|
1633
2104
|
#
|
1634
|
-
# Returns the current font size when no argument is given.
|
2105
|
+
# Returns the current font size when no argument is given. The setter version can also
|
2106
|
+
# be called in the font_size= form.
|
1635
2107
|
#
|
1636
2108
|
# Examples:
|
1637
2109
|
#
|
2110
|
+
# #>pdf
|
2111
|
+
# canvas.font("Helvetica", size: 10) # Necessary only the first time
|
1638
2112
|
# canvas.font_size(12)
|
1639
2113
|
# canvas.font_size # => 12
|
1640
|
-
# canvas.font_size =
|
2114
|
+
# canvas.font_size = 10
|
2115
|
+
#
|
2116
|
+
# # visual example
|
2117
|
+
# 6.step(to: 20, by: 2).each_with_index do |size, index|
|
2118
|
+
# canvas.font_size(size)
|
2119
|
+
# canvas.text("Text in size #{size}", at: [15, 180 - index * 20])
|
2120
|
+
# end
|
1641
2121
|
#
|
1642
|
-
# See: PDF1.7 s9.2.2
|
2122
|
+
# See: PDF1.7 s9.2.2, #font
|
1643
2123
|
def font_size(size = nil)
|
1644
2124
|
if size
|
1645
2125
|
unless @font
|
@@ -1657,26 +2137,30 @@ module HexaPDF
|
|
1657
2137
|
# canvas.text(text) -> canvas
|
1658
2138
|
# canvas.text(text, at: [x, y]) -> canvas
|
1659
2139
|
#
|
1660
|
-
# Shows the given text string.
|
2140
|
+
# Shows the given text string, either at the current or the provided position.
|
1661
2141
|
#
|
1662
2142
|
# If no position is provided, the text is positioned at the current position of the text
|
1663
|
-
# cursor (
|
2143
|
+
# cursor (see #text_cursor).
|
1664
2144
|
#
|
1665
2145
|
# The text string may contain any valid Unicode newline separator and if so, multiple lines
|
1666
|
-
# are shown, using #leading for offsetting the lines.
|
2146
|
+
# are shown, using #leading for offsetting the lines. If no leading has been set, a leading
|
2147
|
+
# equal to the font size will be set..
|
1667
2148
|
#
|
1668
2149
|
# Note that there are no provisions to make sure that all text is visible! So if the text
|
1669
2150
|
# string is too long, it will just flow off the page and be cut off.
|
1670
2151
|
#
|
1671
2152
|
# Examples:
|
1672
2153
|
#
|
2154
|
+
# #>pdf
|
1673
2155
|
# canvas.font('Times', size: 12)
|
1674
|
-
# canvas.text("This is a \n multiline text", at: [
|
2156
|
+
# canvas.text("This is a \n multiline text", at: [15, 150]) # Sets leading=12
|
2157
|
+
# canvas.text(". Some more text\nafter the newline.") # Starts right after the last text
|
1675
2158
|
#
|
1676
|
-
# See: http://www.unicode.org/reports/tr18/#Line_Boundaries
|
2159
|
+
# See: #leading, http://www.unicode.org/reports/tr18/#Line_Boundaries
|
1677
2160
|
def text(text, at: nil)
|
1678
2161
|
raise_unless_font_set
|
1679
2162
|
move_text_cursor(offset: at) if at
|
2163
|
+
leading(font_size) if leading == 0
|
1680
2164
|
lines = text.split(/\u{D A}|(?!\u{D A})[\u{A}-\u{D}\u{85}\u{2028}\u{2029}]/, -1)
|
1681
2165
|
lines.each_with_index do |str, index|
|
1682
2166
|
show_glyphs(@font.decode_utf8(str))
|
@@ -1698,8 +2182,19 @@ module HexaPDF
|
|
1698
2182
|
# method.
|
1699
2183
|
#
|
1700
2184
|
# The text matrix is updated to correctly represent the graphics state after the invocation.
|
2185
|
+
# Since this is a compute intensive operation, use #show_glyphs_only if you don't need a
|
2186
|
+
# correct text matrix.
|
1701
2187
|
#
|
1702
2188
|
# This method is usually not invoked directly but by higher level methods like #text.
|
2189
|
+
#
|
2190
|
+
# Examples:
|
2191
|
+
#
|
2192
|
+
# #>pdf
|
2193
|
+
# canvas.font("Helvetica", size: 10)
|
2194
|
+
# glyphs = canvas.font.decode_utf8("Some text here")
|
2195
|
+
# canvas.move_text_cursor(offset: [15, 100])
|
2196
|
+
# canvas.show_glyphs(glyphs)
|
2197
|
+
# canvas.text(canvas.text_cursor.map(&:to_i).join(", "), at: [15, 80])
|
1703
2198
|
def show_glyphs(glyphs)
|
1704
2199
|
return if glyphs.empty?
|
1705
2200
|
raise_unless_font_set
|
@@ -1736,7 +2231,16 @@ module HexaPDF
|
|
1736
2231
|
#
|
1737
2232
|
# *Warning*: Since this method doesn't update the text matrix, all following results from
|
1738
2233
|
# #text_cursor and other methods using the current text matrix are invalid until the next call
|
1739
|
-
#
|
2234
|
+
# that sets the text matrix.
|
2235
|
+
#
|
2236
|
+
# Examples:
|
2237
|
+
#
|
2238
|
+
# #>pdf
|
2239
|
+
# canvas.font("Helvetica", size: 10)
|
2240
|
+
# glyphs = canvas.font.decode_utf8("Some text here")
|
2241
|
+
# canvas.move_text_cursor(offset: [15, 100])
|
2242
|
+
# canvas.show_glyphs_only(glyphs)
|
2243
|
+
# canvas.text(canvas.text_cursor.map(&:to_i).join(", "), at: [15, 80])
|
1740
2244
|
def show_glyphs_only(glyphs)
|
1741
2245
|
return if glyphs.empty?
|
1742
2246
|
raise_unless_font_set
|
@@ -1794,9 +2298,9 @@ module HexaPDF
|
|
1794
2298
|
# Inserts a marked-content sequence, optionally associated with a property list.
|
1795
2299
|
#
|
1796
2300
|
# A marked-content sequence is used to identify a sequence of complete graphics objects in the
|
1797
|
-
# content stream for later use by other applications. The symbol +tag+ is
|
1798
|
-
# identify the role of the marked-content sequence and should be registered
|
1799
|
-
# conflicts.
|
2301
|
+
# content stream for later use by other applications, e.g. for tagged PDF. The symbol +tag+ is
|
2302
|
+
# used to uniquely identify the role of the marked-content sequence and should be registered
|
2303
|
+
# with ISO to avoid conflicts.
|
1800
2304
|
#
|
1801
2305
|
# The optional +property_list+ argument can either be a valid PDF dictionary or a symbol
|
1802
2306
|
# referencing an already used property list in the resource dictionary's /Properties
|
@@ -1806,7 +2310,7 @@ module HexaPDF
|
|
1806
2310
|
# done. Otherwise the marked-content sequence automatically ends when the block is finished.
|
1807
2311
|
#
|
1808
2312
|
# Although the PDF specification would allow using marked-content sequences inside text
|
1809
|
-
# objects, this is prohibited.
|
2313
|
+
# objects, this is prohibited in HexaPDF.
|
1810
2314
|
#
|
1811
2315
|
# Examples:
|
1812
2316
|
#
|
@@ -1850,9 +2354,12 @@ module HexaPDF
|
|
1850
2354
|
|
1851
2355
|
# Creates a color object from the given color specification. See #stroke_color for details
|
1852
2356
|
# on the possible color specifications.
|
2357
|
+
#
|
2358
|
+
# This utility method is meant for use by higher-level methods that need to convert a color
|
2359
|
+
# specification into a color object for this Canvas object.
|
1853
2360
|
def color_from_specification(spec)
|
1854
2361
|
if spec.length == 1 && spec[0].kind_of?(String)
|
1855
|
-
|
2362
|
+
ColorSpace.device_color_from_specification(spec)
|
1856
2363
|
elsif spec.length == 1 && spec[0].respond_to?(:color_space)
|
1857
2364
|
spec[0]
|
1858
2365
|
else
|
@@ -2040,22 +2547,6 @@ module HexaPDF
|
|
2040
2547
|
end
|
2041
2548
|
end
|
2042
2549
|
|
2043
|
-
# Used for calculating the optimal distance of the control points.
|
2044
|
-
#
|
2045
|
-
# See: http://itc.ktu.lt/itc354/Riskus354.pdf, p373 right column
|
2046
|
-
KAPPA = 0.55191496 #:nodoc:
|
2047
|
-
|
2048
|
-
# Appends a line with a rounded corner from the current point. The corner is specified by
|
2049
|
-
# the three points (x0, y0), (x1, y1) and (x2, y2) where (x1, y1) is the corner point.
|
2050
|
-
def line_with_rounded_corner(x0, y0, x1, y1, x2, y2, radius)
|
2051
|
-
p0 = point_on_line(x1, y1, x0, y0, distance: radius)
|
2052
|
-
p3 = point_on_line(x1, y1, x2, y2, distance: radius)
|
2053
|
-
p1 = point_on_line(p0[0], p0[1], x1, y1, distance: KAPPA * radius)
|
2054
|
-
p2 = point_on_line(p3[0], p3[1], x1, y1, distance: KAPPA * radius)
|
2055
|
-
line_to(p0[0], p0[1])
|
2056
|
-
curve_to(p3[0], p3[1], p1: p1, p2: p2)
|
2057
|
-
end
|
2058
|
-
|
2059
2550
|
end
|
2060
2551
|
|
2061
2552
|
end
|