hexapdf 0.46.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +342 -16
- data/LICENSE +1 -1
- data/README.md +9 -8
- data/examples/009-text_layouter_alignment.rb +4 -0
- data/examples/010-text_layouter_inline_boxes.rb +4 -0
- data/examples/011-text_layouter_line_wrapping.rb +4 -0
- data/examples/012-text_layouter_styling.rb +9 -4
- data/examples/013-text_layouter_shapes.rb +5 -0
- data/examples/015-boxes.rb +3 -0
- data/examples/016-frame_automatic_box_placement.rb +3 -0
- data/examples/017-frame_text_flow.rb +3 -0
- data/examples/022-outline.rb +5 -1
- data/examples/{028-frame_mask_mode.rb → 028-composer_mask_mode.rb} +3 -3
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +65 -65
- data/lib/hexapdf/cli/debug_info.rb +98 -0
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +11 -6
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +19 -4
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +24 -8
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/modify.rb +1 -2
- data/lib/hexapdf/cli/optimize.rb +6 -6
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/usage.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/cli.rb +20 -2
- data/lib/hexapdf/composer.rb +22 -1
- data/lib/hexapdf/configuration.rb +56 -1
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/content/canvas_composer.rb +1 -1
- data/lib/hexapdf/content/color_space.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphics_state.rb +2 -2
- data/lib/hexapdf/content/operator.rb +1 -1
- data/lib/hexapdf/content/parser.rb +22 -23
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +8 -2
- data/lib/hexapdf/dictionary_fields.rb +2 -2
- data/lib/hexapdf/digital_signature/cms_handler.rb +19 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +1 -1
- data/lib/hexapdf/digital_signature/signature.rb +2 -2
- data/lib/hexapdf/digital_signature/signatures.rb +1 -1
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +3 -3
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -2
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +25 -5
- data/lib/hexapdf/digital_signature/signing.rb +1 -1
- data/lib/hexapdf/digital_signature/verification_result.rb +1 -1
- data/lib/hexapdf/digital_signature.rb +1 -1
- data/lib/hexapdf/document/annotations.rb +220 -0
- data/lib/hexapdf/document/destinations.rb +1 -1
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/layout.rb +95 -16
- data/lib/hexapdf/document/metadata.rb +11 -4
- data/lib/hexapdf/document/pages.rb +1 -1
- data/lib/hexapdf/document.rb +52 -9
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/arc4.rb +3 -3
- data/lib/hexapdf/encryption/fast_aes.rb +1 -1
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +4 -2
- data/lib/hexapdf/encryption/standard_security_handler.rb +40 -29
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/error.rb +12 -4
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/crypt.rb +1 -1
- data/lib/hexapdf/filter/encryption.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +1 -1
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +59 -5
- data/lib/hexapdf/font/cmap.rb +18 -7
- data/lib/hexapdf/font/encoding/base.rb +28 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +1 -1
- data/lib/hexapdf/font/true_type/builder.rb +1 -1
- data/lib/hexapdf/font/true_type/font.rb +1 -1
- data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
- data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
- data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
- data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
- data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
- data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
- data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
- data/lib/hexapdf/font/true_type/table/name.rb +1 -1
- data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type/table.rb +7 -2
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +51 -16
- data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
- data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/font.rb +1 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
- data/lib/hexapdf/font/type1.rb +1 -1
- data/lib/hexapdf/font/type1_wrapper.rb +3 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
- data/lib/hexapdf/font_loader/from_file.rb +1 -1
- data/lib/hexapdf/font_loader/standard14.rb +1 -1
- data/lib/hexapdf/font_loader/variant_from_name.rb +1 -1
- data/lib/hexapdf/font_loader.rb +1 -1
- data/lib/hexapdf/image_loader/jpeg.rb +1 -1
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +2 -2
- data/lib/hexapdf/layout/box.rb +6 -1
- data/lib/hexapdf/layout/box_fitter.rb +1 -1
- data/lib/hexapdf/layout/column_box.rb +1 -1
- data/lib/hexapdf/layout/container_box.rb +64 -29
- data/lib/hexapdf/layout/frame.rb +1 -1
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/inline_box.rb +1 -1
- data/lib/hexapdf/layout/line.rb +1 -1
- data/lib/hexapdf/layout/list_box.rb +1 -1
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/page_style.rb +1 -1
- data/lib/hexapdf/layout/style.rb +133 -22
- data/lib/hexapdf/layout/table_box.rb +86 -14
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +13 -2
- data/lib/hexapdf/layout/text_layouter.rb +1 -1
- data/lib/hexapdf/layout/text_shaper.rb +1 -1
- data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
- data/lib/hexapdf/layout.rb +1 -1
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +4 -4
- data/lib/hexapdf/parser.rb +36 -7
- data/lib/hexapdf/pdf_array.rb +26 -4
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +2 -2
- data/lib/hexapdf/revision.rb +7 -3
- data/lib/hexapdf/revisions.rb +1 -1
- data/lib/hexapdf/serializer.rb +8 -8
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/merge_acro_form.rb +164 -0
- data/lib/hexapdf/task/optimize.rb +5 -5
- data/lib/hexapdf/task/pdfa.rb +1 -1
- data/lib/hexapdf/task.rb +2 -1
- data/lib/hexapdf/test_utils.rb +3 -2
- data/lib/hexapdf/tokenizer.rb +52 -44
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +66 -13
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +6 -2
- data/lib/hexapdf/type/acro_form/form.rb +23 -32
- data/lib/hexapdf/type/acro_form/java_script_actions.rb +10 -3
- data/lib/hexapdf/type/acro_form/signature_field.rb +19 -8
- data/lib/hexapdf/type/acro_form/text_field.rb +10 -3
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +13 -5
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +2 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +2 -1
- data/lib/hexapdf/type/actions/launch.rb +6 -2
- data/lib/hexapdf/type/actions/set_ocg_state.rb +1 -1
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +78 -3
- data/lib/hexapdf/type/annotations/appearance_generator.rb +426 -0
- data/lib/hexapdf/type/annotations/border_effect.rb +99 -0
- data/lib/hexapdf/type/annotations/border_styling.rb +160 -0
- data/lib/hexapdf/type/annotations/circle.rb +65 -0
- data/lib/hexapdf/type/annotations/interior_color.rb +84 -0
- data/lib/hexapdf/type/annotations/line.rb +334 -0
- data/lib/hexapdf/type/annotations/line_ending_styling.rb +208 -0
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +15 -3
- data/lib/hexapdf/type/annotations/polygon.rb +64 -0
- data/lib/hexapdf/type/annotations/polygon_polyline.rb +109 -0
- data/lib/hexapdf/type/annotations/polyline.rb +64 -0
- data/lib/hexapdf/type/annotations/square.rb +65 -0
- data/lib/hexapdf/type/annotations/square_circle.rb +77 -0
- data/lib/hexapdf/type/annotations/text.rb +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +56 -118
- data/lib/hexapdf/type/annotations.rb +13 -1
- data/lib/hexapdf/type/catalog.rb +5 -2
- data/lib/hexapdf/type/cid_font.rb +6 -3
- data/lib/hexapdf/type/cmap.rb +58 -0
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +18 -15
- data/lib/hexapdf/type/font.rb +1 -1
- data/lib/hexapdf/type/font_descriptor.rb +5 -4
- data/lib/hexapdf/type/font_simple.rb +4 -2
- data/lib/hexapdf/type/font_true_type.rb +3 -1
- data/lib/hexapdf/type/font_type0.rb +2 -2
- data/lib/hexapdf/type/font_type1.rb +19 -1
- data/lib/hexapdf/type/font_type3.rb +1 -2
- data/lib/hexapdf/type/form.rb +8 -5
- data/lib/hexapdf/type/graphics_state_parameter.rb +8 -5
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +9 -5
- data/lib/hexapdf/type/info.rb +3 -3
- data/lib/hexapdf/type/mark_information.rb +3 -3
- data/lib/hexapdf/type/marked_content_reference.rb +59 -0
- data/lib/hexapdf/type/measure.rb +57 -0
- data/lib/hexapdf/type/metadata.rb +1 -1
- data/lib/hexapdf/type/names.rb +1 -1
- data/lib/hexapdf/type/namespace.rb +57 -0
- data/lib/hexapdf/type/object_reference.rb +57 -0
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/optional_content_configuration.rb +2 -2
- data/lib/hexapdf/type/optional_content_group.rb +1 -1
- data/lib/hexapdf/type/optional_content_membership.rb +2 -2
- data/lib/hexapdf/type/optional_content_properties.rb +1 -1
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/output_intent.rb +1 -1
- data/lib/hexapdf/type/page.rb +6 -4
- data/lib/hexapdf/type/page_label.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +13 -9
- data/lib/hexapdf/type/struct_elem.rb +72 -0
- data/lib/hexapdf/type/struct_tree_root.rb +64 -0
- data/lib/hexapdf/type/trailer.rb +1 -1
- data/lib/hexapdf/type/viewer_preferences.rb +5 -4
- data/lib/hexapdf/type/xref_stream.rb +1 -1
- data/lib/hexapdf/type.rb +8 -1
- data/lib/hexapdf/utils/bit_field.rb +1 -1
- data/lib/hexapdf/utils/bit_stream.rb +1 -1
- data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
- data/lib/hexapdf/utils/lru_cache.rb +1 -1
- data/lib/hexapdf/utils/math_helpers.rb +1 -1
- data/lib/hexapdf/utils/object_hash.rb +1 -1
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/utils/sorted_tree_node.rb +17 -4
- data/lib/hexapdf/utils.rb +1 -1
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +3 -2
- data/lib/hexapdf/xref_section.rb +25 -6
- data/lib/hexapdf.rb +1 -1
- data/test/data/standard-security-handler/bothpwd-aes-256bit-V5-R5.pdf +43 -0
- data/test/data/standard-security-handler/nopwd-aes-256bit-V5-R5.pdf +44 -0
- data/test/data/standard-security-handler/ownerpwd-aes-256bit-V5-R5.pdf +43 -0
- data/test/data/standard-security-handler/userpwd-aes-256bit-V5-R5.pdf +0 -0
- data/test/hexapdf/common_tokenizer_tests.rb +7 -7
- data/test/hexapdf/content/test_graphics_state.rb +2 -3
- data/test/hexapdf/content/test_operator.rb +4 -5
- data/test/hexapdf/digital_signature/common.rb +6 -1
- data/test/hexapdf/digital_signature/signing/test_default_handler.rb +6 -1
- data/test/hexapdf/digital_signature/signing/test_timestamp_handler.rb +12 -0
- data/test/hexapdf/digital_signature/test_cms_handler.rb +25 -15
- data/test/hexapdf/digital_signature/test_handler.rb +2 -3
- data/test/hexapdf/digital_signature/test_pkcs1_handler.rb +1 -2
- data/test/hexapdf/digital_signature/test_signature.rb +7 -0
- data/test/hexapdf/digital_signature/test_signatures.rb +12 -7
- data/test/hexapdf/document/test_annotations.rb +75 -0
- data/test/hexapdf/document/test_layout.rb +38 -10
- data/test/hexapdf/document/test_metadata.rb +13 -1
- data/test/hexapdf/encryption/common.rb +1 -1
- data/test/hexapdf/encryption/test_aes.rb +1 -1
- data/test/hexapdf/encryption/test_arc4.rb +2 -2
- data/test/hexapdf/encryption/test_security_handler.rb +8 -6
- data/test/hexapdf/encryption/test_standard_security_handler.rb +7 -3
- data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
- data/test/hexapdf/filter/test_flate_decode.rb +2 -3
- data/test/hexapdf/font/cmap/test_writer.rb +73 -16
- data/test/hexapdf/font/encoding/test_base.rb +20 -0
- data/test/hexapdf/font/encoding/test_glyph_list.rb +1 -1
- data/test/hexapdf/font/test_true_type_wrapper.rb +31 -5
- data/test/hexapdf/font/test_type1_wrapper.rb +8 -1
- data/test/hexapdf/font/true_type/test_table.rb +12 -0
- data/test/hexapdf/layout/test_box.rb +8 -2
- data/test/hexapdf/layout/test_container_box.rb +34 -6
- data/test/hexapdf/layout/test_list_box.rb +7 -7
- data/test/hexapdf/layout/test_page_style.rb +1 -1
- data/test/hexapdf/layout/test_style.rb +46 -12
- data/test/hexapdf/layout/test_table_box.rb +66 -16
- data/test/hexapdf/layout/test_text_box.rb +0 -6
- data/test/hexapdf/layout/test_text_fragment.rb +3 -3
- data/test/hexapdf/layout/test_text_layouter.rb +4 -2
- data/test/hexapdf/task/test_merge_acro_form.rb +104 -0
- data/test/hexapdf/task/test_optimize.rb +3 -1
- data/test/hexapdf/test_composer.rb +15 -0
- data/test/hexapdf/test_dictionary.rb +15 -0
- data/test/hexapdf/test_dictionary_fields.rb +1 -0
- data/test/hexapdf/test_document.rb +26 -8
- data/test/hexapdf/test_filter.rb +1 -1
- data/test/hexapdf/test_importer.rb +7 -0
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_parser.rb +87 -18
- data/test/hexapdf/test_pdf_array.rb +36 -3
- data/test/hexapdf/test_revision.rb +27 -6
- data/test/hexapdf/test_revisions.rb +1 -1
- data/test/hexapdf/test_serializer.rb +4 -4
- data/test/hexapdf/test_stream.rb +1 -2
- data/test/hexapdf/test_tokenizer.rb +1 -1
- data/test/hexapdf/test_writer.rb +22 -8
- data/test/hexapdf/test_xref_section.rb +15 -0
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +118 -26
- data/test/hexapdf/type/acro_form/test_button_field.rb +7 -6
- data/test/hexapdf/type/acro_form/test_field.rb +10 -0
- data/test/hexapdf/type/acro_form/test_form.rb +32 -9
- data/test/hexapdf/type/acro_form/test_java_script_actions.rb +21 -0
- data/test/hexapdf/type/acro_form/test_signature_field.rb +3 -1
- data/test/hexapdf/type/acro_form/test_text_field.rb +7 -1
- data/test/hexapdf/type/acro_form/test_variable_text_field.rb +14 -1
- data/test/hexapdf/type/actions/test_launch.rb +6 -2
- data/test/hexapdf/type/annotations/test_appearance_generator.rb +608 -0
- data/test/hexapdf/type/annotations/test_border_effect.rb +59 -0
- data/test/hexapdf/type/annotations/test_border_styling.rb +114 -0
- data/test/hexapdf/type/annotations/test_interior_color.rb +37 -0
- data/test/hexapdf/type/annotations/test_line.rb +144 -0
- data/test/hexapdf/type/annotations/test_line_ending_styling.rb +42 -0
- data/test/hexapdf/type/annotations/test_polygon_polyline.rb +29 -0
- data/test/hexapdf/type/annotations/test_widget.rb +47 -81
- data/test/hexapdf/type/test_annotation.rb +58 -0
- data/test/hexapdf/type/test_font_type1.rb +20 -1
- data/test/hexapdf/type/test_form.rb +7 -1
- data/test/hexapdf/type/test_image.rb +1 -1
- data/test/hexapdf/type/test_page.rb +7 -1
- data/test/hexapdf/type/test_page_tree_node.rb +2 -2
- data/test/hexapdf/type/test_resources.rb +3 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +18 -7
- data/test/test_helper.rb +7 -0
- metadata +69 -9
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -40,9 +40,7 @@ module HexaPDF
|
|
|
40
40
|
module Font
|
|
41
41
|
class CMap
|
|
42
42
|
|
|
43
|
-
# Creates a CMap file.
|
|
44
|
-
#
|
|
45
|
-
# Currently only ToUnicode CMaps are supported.
|
|
43
|
+
# Creates a CMap file, either a ToUnicode CMap or a CID CMap.
|
|
46
44
|
class Writer
|
|
47
45
|
|
|
48
46
|
# Maximum number of entries in one section.
|
|
@@ -74,6 +72,28 @@ module HexaPDF
|
|
|
74
72
|
to_unicode_template % result.chop!
|
|
75
73
|
end
|
|
76
74
|
|
|
75
|
+
# Returns a CID CMap for the given input code to CID mapping which needs to be sorted by
|
|
76
|
+
# input codes.
|
|
77
|
+
#
|
|
78
|
+
# Note that the returned CMap always uses a 16-bit input code space!
|
|
79
|
+
def create_cid_cmap(mapping)
|
|
80
|
+
return cid_template % '' if mapping.empty?
|
|
81
|
+
|
|
82
|
+
chars, ranges = compute_section_entries(mapping)
|
|
83
|
+
|
|
84
|
+
result = create_sections("cidchar", chars.size / 2) do |index|
|
|
85
|
+
index *= 2
|
|
86
|
+
sprintf("<%04X>", chars[index]) << " #{chars[index + 1]}\n"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
result << create_sections("cidrange", ranges.size / 3) do |index|
|
|
90
|
+
index *= 3
|
|
91
|
+
sprintf("<%04X><%04X>", ranges[index], ranges[index + 1]) << " #{ranges[index + 2]}\n"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
cid_template % result.chop!
|
|
95
|
+
end
|
|
96
|
+
|
|
77
97
|
private
|
|
78
98
|
|
|
79
99
|
# Computes the entries for the "char" and "range" sections based on the given mapping.
|
|
@@ -146,7 +166,7 @@ module HexaPDF
|
|
|
146
166
|
result
|
|
147
167
|
end
|
|
148
168
|
|
|
149
|
-
# Returns the
|
|
169
|
+
# Returns the template for a ToUnicode CMap.
|
|
150
170
|
def to_unicode_template
|
|
151
171
|
<<~TEMPLATE
|
|
152
172
|
/CIDInit /ProcSet findresource begin
|
|
@@ -170,6 +190,40 @@ module HexaPDF
|
|
|
170
190
|
TEMPLATE
|
|
171
191
|
end
|
|
172
192
|
|
|
193
|
+
# Returns the template for a CID CMap.
|
|
194
|
+
def cid_template
|
|
195
|
+
<<~TEMPLATE
|
|
196
|
+
%%!PS-Adobe-3.0 Resource-CMap
|
|
197
|
+
%%%%DocumentNeededResources: ProcSet (CIDInit)
|
|
198
|
+
%%%%IncludeResource: ProcSet (CIDInit)
|
|
199
|
+
%%%%BeginResource: CMap (Custom)
|
|
200
|
+
%%%%Title: (Custom Adobe Identity 0)
|
|
201
|
+
%%%%Version: 1
|
|
202
|
+
/CIDInit /ProcSet findresource begin
|
|
203
|
+
12 dict begin
|
|
204
|
+
begincmap
|
|
205
|
+
/CIDSystemInfo 3 dict dup begin
|
|
206
|
+
/Registry (Adobe) def
|
|
207
|
+
/Ordering (Identity) def
|
|
208
|
+
/Supplement 0 def
|
|
209
|
+
end def
|
|
210
|
+
/CMapName /Custom def
|
|
211
|
+
/CMapType 1 def
|
|
212
|
+
/CMapVersion 1 def
|
|
213
|
+
/WMode 0 def
|
|
214
|
+
1 begincodespacerange
|
|
215
|
+
<0000> <FFFF>
|
|
216
|
+
endcodespacerange
|
|
217
|
+
%s
|
|
218
|
+
endcmap
|
|
219
|
+
CMapName currentdict /CMap defineresource pop
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
%%%%EndResource
|
|
223
|
+
%%%%EOF
|
|
224
|
+
TEMPLATE
|
|
225
|
+
end
|
|
226
|
+
|
|
173
227
|
end
|
|
174
228
|
|
|
175
229
|
end
|
data/lib/hexapdf/font/cmap.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -85,6 +85,13 @@ module HexaPDF
|
|
|
85
85
|
Writer.new.create_to_unicode_cmap(mapping)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
# Returns a string containing a CID CMap that represents the given code to CID mapping.
|
|
89
|
+
#
|
|
90
|
+
# See: Writer#create_cid_cmap
|
|
91
|
+
def self.create_cid_cmap(mapping)
|
|
92
|
+
Writer.new.create_cid_cmap(mapping)
|
|
93
|
+
end
|
|
94
|
+
|
|
88
95
|
# The registry part of the CMap version.
|
|
89
96
|
attr_accessor :registry
|
|
90
97
|
|
|
@@ -136,10 +143,13 @@ module HexaPDF
|
|
|
136
143
|
# An error is raised if the string contains invalid bytes.
|
|
137
144
|
def read_codes(string)
|
|
138
145
|
codes = []
|
|
139
|
-
bytes = string.
|
|
146
|
+
bytes = string.bytes
|
|
147
|
+
length = bytes.length
|
|
148
|
+
i = 0
|
|
140
149
|
|
|
141
|
-
|
|
142
|
-
byte = bytes
|
|
150
|
+
while i < length
|
|
151
|
+
byte = bytes[i]
|
|
152
|
+
i += 1
|
|
143
153
|
code = 0
|
|
144
154
|
|
|
145
155
|
found = @codespace_ranges.any? do |first_byte_range, rest_ranges|
|
|
@@ -147,9 +157,10 @@ module HexaPDF
|
|
|
147
157
|
|
|
148
158
|
code = (code << 8) + byte
|
|
149
159
|
valid = rest_ranges.all? do |range|
|
|
150
|
-
|
|
151
|
-
byte = bytes
|
|
152
|
-
|
|
160
|
+
if i < length
|
|
161
|
+
byte = bytes[i]
|
|
162
|
+
i += 1
|
|
163
|
+
else
|
|
153
164
|
raise HexaPDF::Error, "Missing bytes while reading codes via CMap"
|
|
154
165
|
end
|
|
155
166
|
code = (code << 8) + byte
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -81,6 +81,33 @@ module HexaPDF
|
|
|
81
81
|
@code_to_name.key(name)
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
# Returns the encoding in a compact array form.
|
|
85
|
+
#
|
|
86
|
+
# If the optional +base_encoding+ argument is specified, all codes that have the same value
|
|
87
|
+
# in the base encoding are ignored.
|
|
88
|
+
#
|
|
89
|
+
# The returned array is of the form:
|
|
90
|
+
#
|
|
91
|
+
# code1 name1 name2 ... code2 name3 name4 ...
|
|
92
|
+
#
|
|
93
|
+
# This means that name1 is associated with code1, name2 with code1 + 1 and so on.
|
|
94
|
+
#
|
|
95
|
+
# See: PDF 2.0 s9.6.5.1
|
|
96
|
+
def to_compact_array(base_encoding: nil)
|
|
97
|
+
result = []
|
|
98
|
+
last_code = -3
|
|
99
|
+
@code_to_name.sort.each do |code, name|
|
|
100
|
+
next if base_encoding&.name(code) == name
|
|
101
|
+
if last_code + 1 == code
|
|
102
|
+
result << name
|
|
103
|
+
else
|
|
104
|
+
result << code << name
|
|
105
|
+
end
|
|
106
|
+
last_code = code
|
|
107
|
+
end
|
|
108
|
+
result
|
|
109
|
+
end
|
|
110
|
+
|
|
84
111
|
end
|
|
85
112
|
|
|
86
113
|
end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -63,7 +63,12 @@ module HexaPDF
|
|
|
63
63
|
|
|
64
64
|
# Calculates the checksum for the given data.
|
|
65
65
|
def self.calculate_checksum(data)
|
|
66
|
-
|
|
66
|
+
checksum = 0
|
|
67
|
+
if (remainder_length = data.length % 4) != 0
|
|
68
|
+
checksum = (data[-remainder_length, remainder_length] << "\0" * (4 - remainder_length)).
|
|
69
|
+
unpack1('N')
|
|
70
|
+
end
|
|
71
|
+
checksum + data.unpack('N*').inject(0) {|sum, long| sum + long } % 2**32
|
|
67
72
|
end
|
|
68
73
|
|
|
69
74
|
# The TrueType font object associated with this table.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# This file is part of HexaPDF.
|
|
5
5
|
#
|
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
-
# Copyright (C) 2014-
|
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
|
8
8
|
#
|
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
|
@@ -57,6 +57,10 @@ module HexaPDF
|
|
|
57
57
|
class TrueTypeWrapper
|
|
58
58
|
|
|
59
59
|
# Represents a single glyph of the wrapped font.
|
|
60
|
+
#
|
|
61
|
+
# Since some characters/strings may be mapped to the same glyph id by the font's builtin cmap
|
|
62
|
+
# table, it is possible that different Glyph instances with the same #id but different #str
|
|
63
|
+
# exist.
|
|
60
64
|
class Glyph
|
|
61
65
|
|
|
62
66
|
# The associated TrueTypeWrapper object.
|
|
@@ -152,6 +156,7 @@ module HexaPDF
|
|
|
152
156
|
@id_to_glyph = {}
|
|
153
157
|
@codepoint_to_glyph = {}
|
|
154
158
|
@encoded_glyphs = {}
|
|
159
|
+
@last_char_code = 0
|
|
155
160
|
end
|
|
156
161
|
|
|
157
162
|
# Returns the type of the font, i.e. :TrueType.
|
|
@@ -179,14 +184,15 @@ module HexaPDF
|
|
|
179
184
|
!@subsetter.nil?
|
|
180
185
|
end
|
|
181
186
|
|
|
182
|
-
# Returns a Glyph object for the given glyph ID.
|
|
187
|
+
# Returns a Glyph object for the given glyph ID and +str+ pair.
|
|
183
188
|
#
|
|
184
|
-
# The optional argument +str+ should be the string representation of the glyph.
|
|
185
|
-
#
|
|
189
|
+
# The optional argument +str+ should be the string representation of the glyph. It is possible
|
|
190
|
+
# that multiple strings map to the same glyph (e.g. hyphen and soft-hyphen could be
|
|
191
|
+
# represented by the same glyph).
|
|
186
192
|
#
|
|
187
193
|
# Note: Although this method is public, it should normally not be used by application code!
|
|
188
194
|
def glyph(id, str = nil)
|
|
189
|
-
@id_to_glyph[id] ||=
|
|
195
|
+
@id_to_glyph[[id, str]] ||=
|
|
190
196
|
if id >= 0 && id < @wrapped_font[:maxp].num_glyphs
|
|
191
197
|
Glyph.new(self, id, str || (+'' << (@cmap.gid_to_code(id) || 0xFFFD)))
|
|
192
198
|
else
|
|
@@ -228,14 +234,17 @@ module HexaPDF
|
|
|
228
234
|
|
|
229
235
|
# Encodes the glyph and returns the code string.
|
|
230
236
|
def encode(glyph)
|
|
231
|
-
(@encoded_glyphs[glyph
|
|
237
|
+
(@encoded_glyphs[glyph] ||=
|
|
232
238
|
begin
|
|
233
239
|
raise HexaPDF::MissingGlyphError.new(glyph) if glyph.kind_of?(InvalidGlyph)
|
|
234
|
-
if @subsetter
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
240
|
+
@subsetter.use_glyph(glyph.id) if @subsetter
|
|
241
|
+
@last_char_code += 1
|
|
242
|
+
# Handle codes for ASCII characters \r (13), (, ) (40, 41) and \ (92) specially so that
|
|
243
|
+
# they never appear in the output (PDF serialization would need to escape them)
|
|
244
|
+
if @last_char_code == 13 || @last_char_code == 40 || @last_char_code == 92
|
|
245
|
+
@last_char_code += (@last_char_code == 40 ? 2 : 1)
|
|
238
246
|
end
|
|
247
|
+
[[@last_char_code].pack('n'), @last_char_code]
|
|
239
248
|
end)[0]
|
|
240
249
|
end
|
|
241
250
|
|
|
@@ -286,14 +295,16 @@ module HexaPDF
|
|
|
286
295
|
Supplement: 0},
|
|
287
296
|
CIDToGIDMap: :Identity})
|
|
288
297
|
dict = document.add({Type: :Font, Subtype: :Type0, BaseFont: cid_font[:BaseFont],
|
|
289
|
-
|
|
298
|
+
DescendantFonts: [cid_font]})
|
|
290
299
|
dict.font_wrapper = self
|
|
291
300
|
|
|
292
301
|
document.register_listener(:complete_objects) do
|
|
302
|
+
next if dict.null?
|
|
293
303
|
update_font_name(dict)
|
|
294
304
|
embed_font(dict, document)
|
|
295
305
|
complete_width_information(dict)
|
|
296
306
|
create_to_unicode_cmap(dict, document)
|
|
307
|
+
add_encoding_information_cmap(dict, document)
|
|
297
308
|
end
|
|
298
309
|
|
|
299
310
|
dict
|
|
@@ -306,7 +317,7 @@ module HexaPDF
|
|
|
306
317
|
return unless @subsetter
|
|
307
318
|
|
|
308
319
|
tag = +''
|
|
309
|
-
data = @encoded_glyphs.each_with_object(''.b) {|(
|
|
320
|
+
data = @encoded_glyphs.each_with_object(''.b) {|(g, v), s| s << g.id.to_s << v[0] }
|
|
310
321
|
hash = Digest::MD5.hexdigest(data << @wrapped_font.font_name).to_i(16)
|
|
311
322
|
while hash != 0 && tag.length < 6
|
|
312
323
|
hash, mod = hash.divmod(UPPERCASE_LETTERS.length)
|
|
@@ -336,8 +347,8 @@ module HexaPDF
|
|
|
336
347
|
# Adds the /DW and /W fields to the CIDFont dictionary.
|
|
337
348
|
def complete_width_information(dict)
|
|
338
349
|
default_width = glyph(3, " ").width.to_i
|
|
339
|
-
widths = @encoded_glyphs.reject {|
|
|
340
|
-
[(@subsetter ? @subsetter.subset_glyph_id(id) : id),
|
|
350
|
+
widths = @encoded_glyphs.reject {|g, _| g.width == default_width }.map do |g, _|
|
|
351
|
+
[(@subsetter ? @subsetter.subset_glyph_id(g.id) : g.id), g.width]
|
|
341
352
|
end.sort!
|
|
342
353
|
dict[:DescendantFonts].first.set_widths(widths, default_width: default_width)
|
|
343
354
|
end
|
|
@@ -346,9 +357,10 @@ module HexaPDF
|
|
|
346
357
|
# correctly.
|
|
347
358
|
def create_to_unicode_cmap(dict, document)
|
|
348
359
|
stream = HexaPDF::StreamData.new do
|
|
349
|
-
mapping = @encoded_glyphs.
|
|
360
|
+
mapping = @encoded_glyphs.map do |glyph, (_, char_code)|
|
|
350
361
|
# Using 0xFFFD as mentioned in Adobe #5411, last line before section 1.5
|
|
351
|
-
|
|
362
|
+
# TODO: glyph.str assumed to consist of single char, No support for multiple chars
|
|
363
|
+
[char_code, glyph.str.ord || 0xFFFD]
|
|
352
364
|
end.sort_by!(&:first)
|
|
353
365
|
HexaPDF::Font::CMap.create_to_unicode_cmap(mapping)
|
|
354
366
|
end
|
|
@@ -357,6 +369,29 @@ module HexaPDF
|
|
|
357
369
|
dict[:ToUnicode] = stream_obj
|
|
358
370
|
end
|
|
359
371
|
|
|
372
|
+
# Adds the /Encoding entry to the +dict+.
|
|
373
|
+
#
|
|
374
|
+
# This can either be the identity mapping or, if some Unicode codepoints are mapped to the
|
|
375
|
+
# same glyph, a custom CMap.
|
|
376
|
+
def add_encoding_information_cmap(dict, document)
|
|
377
|
+
mapping = @encoded_glyphs.map do |glyph, (_, char_code)|
|
|
378
|
+
# Using 0xFFFD as mentioned in Adobe #5411, last line before section 1.5
|
|
379
|
+
[char_code, (@subsetter ? @subsetter.subset_glyph_id(glyph.id) : glyph.id)]
|
|
380
|
+
end.sort_by!(&:first)
|
|
381
|
+
if mapping.all? {|char_code, cid| char_code == cid }
|
|
382
|
+
dict[:Encoding] = :'Identity-H'
|
|
383
|
+
else
|
|
384
|
+
stream = HexaPDF::StreamData.new { HexaPDF::Font::CMap.create_cid_cmap(mapping) }
|
|
385
|
+
stream_obj = document.add({Type: :CMap,
|
|
386
|
+
CMapName: :Custom,
|
|
387
|
+
CIDSystemInfo: {Registry: "Adobe", Ordering: "Identity",
|
|
388
|
+
Supplement: 0},
|
|
389
|
+
}, stream: stream)
|
|
390
|
+
stream_obj.set_filter(:FlateDecode)
|
|
391
|
+
dict[:Encoding] = stream_obj
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
360
395
|
end
|
|
361
396
|
|
|
362
397
|
end
|