hexapdf 0.11.9 → 0.13.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 +157 -0
- data/LICENSE +1 -1
- data/examples/001-hello_world.rb +1 -1
- data/examples/002-graphics.rb +1 -1
- data/examples/003-arcs.rb +1 -1
- data/examples/004-optimizing.rb +1 -1
- data/examples/005-merging.rb +1 -1
- data/examples/006-standard_pdf_fonts.rb +1 -1
- data/examples/007-truetype.rb +1 -1
- data/examples/008-show_char_bboxes.rb +1 -1
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +1 -1
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +1 -1
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +1 -1
- data/examples/016-frame_automatic_box_placement.rb +1 -1
- data/examples/017-frame_text_flow.rb +1 -1
- data/examples/018-composer.rb +1 -1
- data/examples/019-acro_form.rb +51 -0
- data/lib/hexapdf.rb +1 -1
- data/lib/hexapdf/cli.rb +3 -1
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +22 -11
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/form.rb +240 -0
- data/lib/hexapdf/cli/image2pdf.rb +3 -2
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +52 -3
- data/lib/hexapdf/cli/inspect.rb +31 -9
- data/lib/hexapdf/cli/merge.rb +2 -2
- 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/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +81 -11
- data/lib/hexapdf/content.rb +3 -1
- data/lib/hexapdf/content/canvas.rb +5 -18
- data/lib/hexapdf/content/color_space.rb +111 -32
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +4 -4
- 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/graphics_state.rb +1 -1
- data/lib/hexapdf/content/operator.rb +9 -9
- data/lib/hexapdf/content/parser.rb +18 -5
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +5 -5
- data/lib/hexapdf/dictionary_fields.rb +2 -10
- data/lib/hexapdf/document.rb +45 -17
- data/lib/hexapdf/document/files.rb +1 -2
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/pages.rb +3 -14
- data/lib/hexapdf/encryption.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 +2 -2
- 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 +2 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +2 -1
- data/lib/hexapdf/error.rb +1 -1
- data/lib/hexapdf/filter.rb +3 -3
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.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/{jpx_decode.rb → pass_through.rb} +5 -5
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/font/cmap.rb +2 -5
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +1 -1
- data/lib/hexapdf/font/encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/base.rb +9 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +7 -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/invalid_glyph.rb +1 -1
- data/lib/hexapdf/font/true_type.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.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 +2 -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 +3 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +54 -51
- data/lib/hexapdf/font/type1.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_wrapper.rb +68 -52
- data/lib/hexapdf/font_loader.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/image_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 +4 -3
- data/lib/hexapdf/importer.rb +2 -4
- data/lib/hexapdf/layout.rb +1 -1
- data/lib/hexapdf/layout/box.rb +1 -1
- 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 +2 -2
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +24 -24
- 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 +4 -3
- data/lib/hexapdf/layout/width_from_polygon.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 +32 -27
- data/lib/hexapdf/parser.rb +69 -6
- data/lib/hexapdf/pdf_array.rb +10 -3
- data/lib/hexapdf/rectangle.rb +31 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +2 -1
- data/lib/hexapdf/revisions.rb +30 -22
- data/lib/hexapdf/serializer.rb +2 -2
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +7 -5
- data/lib/hexapdf/tokenizer.rb +5 -4
- data/lib/hexapdf/type.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +7 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +405 -0
- data/lib/hexapdf/type/acro_form/button_field.rb +305 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
- data/lib/hexapdf/type/acro_form/field.rb +250 -17
- data/lib/hexapdf/type/acro_form/form.rb +159 -7
- data/lib/hexapdf/type/acro_form/text_field.rb +187 -0
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +122 -0
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions.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 +4 -3
- data/lib/hexapdf/type/annotation.rb +73 -3
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/annotations/link.rb +2 -2
- 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 +238 -2
- data/lib/hexapdf/type/catalog.rb +23 -3
- 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 +2 -2
- data/lib/hexapdf/type/font.rb +18 -1
- data/lib/hexapdf/type/font_descriptor.rb +2 -2
- data/lib/hexapdf/type/font_simple.rb +4 -2
- data/lib/hexapdf/type/font_true_type.rb +7 -3
- data/lib/hexapdf/type/font_type0.rb +2 -2
- data/lib/hexapdf/type/font_type1.rb +16 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +12 -2
- 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 +5 -3
- 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 +36 -12
- data/lib/hexapdf/type/page_tree_node.rb +37 -16
- data/lib/hexapdf/type/resources.rb +17 -3
- data/lib/hexapdf/type/trailer.rb +4 -6
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +1 -1
- data/lib/hexapdf/utils/bit_field.rb +38 -24
- 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 +19 -16
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/test/hexapdf/common_tokenizer_tests.rb +6 -1
- data/test/hexapdf/content/common.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_arc.rb +4 -4
- data/test/hexapdf/content/test_canvas.rb +3 -3
- data/test/hexapdf/content/test_color_space.rb +71 -8
- data/test/hexapdf/content/test_operator.rb +22 -22
- data/test/hexapdf/content/test_parser.rb +14 -0
- data/test/hexapdf/document/test_fonts.rb +1 -1
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/encryption/test_aes.rb +4 -4
- data/test/hexapdf/encryption/test_standard_security_handler.rb +11 -11
- data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
- data/test/hexapdf/font/encoding/test_base.rb +10 -0
- data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
- data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
- data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
- data/test/hexapdf/layout/test_style.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +3 -4
- data/test/hexapdf/test_configuration.rb +2 -2
- data/test/hexapdf/test_dictionary.rb +3 -1
- data/test/hexapdf/test_dictionary_fields.rb +2 -2
- data/test/hexapdf/test_document.rb +16 -4
- data/test/hexapdf/test_object.rb +44 -26
- data/test/hexapdf/test_parser.rb +125 -55
- data/test/hexapdf/test_pdf_array.rb +7 -0
- data/test/hexapdf/test_rectangle.rb +14 -0
- data/test/hexapdf/test_revision.rb +3 -0
- data/test/hexapdf/test_revisions.rb +35 -0
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +521 -0
- data/test/hexapdf/type/acro_form/test_button_field.rb +281 -0
- data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
- data/test/hexapdf/type/acro_form/test_field.rb +163 -6
- data/test/hexapdf/type/acro_form/test_form.rb +189 -22
- data/test/hexapdf/type/acro_form/test_text_field.rb +121 -0
- data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
- data/test/hexapdf/type/annotations/test_text.rb +1 -1
- data/test/hexapdf/type/annotations/test_widget.rb +199 -0
- data/test/hexapdf/type/test_annotation.rb +45 -0
- data/test/hexapdf/type/test_catalog.rb +18 -0
- data/test/hexapdf/type/test_font.rb +5 -0
- data/test/hexapdf/type/test_font_simple.rb +2 -1
- data/test/hexapdf/type/test_font_true_type.rb +6 -0
- data/test/hexapdf/type/test_font_type1.rb +8 -0
- data/test/hexapdf/type/test_form.rb +19 -1
- data/test/hexapdf/type/test_image.rb +7 -0
- data/test/hexapdf/type/test_page.rb +45 -7
- data/test/hexapdf/type/test_page_tree_node.rb +62 -12
- data/test/hexapdf/type/test_resources.rb +20 -0
- data/test/hexapdf/type/test_trailer.rb +4 -0
- data/test/hexapdf/utils/test_bit_field.rb +15 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -9
- data/test/test_helper.rb +1 -1
- metadata +34 -21
- data/lib/hexapdf/filter/dct_decode.rb +0 -60
|
@@ -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-2020 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-2020 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-2020 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-2020 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
|
|
@@ -68,9 +68,10 @@ module HexaPDF
|
|
|
68
68
|
text_fragment.clear_cache
|
|
69
69
|
end
|
|
70
70
|
if text_fragment.style.font_features[:kern] && font.wrapped_font.features.include?(:kern)
|
|
71
|
-
|
|
71
|
+
case font.font_type
|
|
72
|
+
when :TrueType
|
|
72
73
|
process_true_type_kerning(text_fragment)
|
|
73
|
-
|
|
74
|
+
when :Type1
|
|
74
75
|
process_type1_kerning(text_fragment)
|
|
75
76
|
end
|
|
76
77
|
text_fragment.clear_cache
|
|
@@ -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-2020 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-2020 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-2020 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
|
data/lib/hexapdf/object.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-2020 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
|
|
@@ -122,9 +122,6 @@ module HexaPDF
|
|
|
122
122
|
|
|
123
123
|
include Comparable
|
|
124
124
|
|
|
125
|
-
# A list of classes whose objects cannot be duplicated.
|
|
126
|
-
NOT_DUPLICATABLE_CLASSES = [NilClass, FalseClass, TrueClass, Symbol, Integer, Float].freeze
|
|
127
|
-
|
|
128
125
|
# :call-seq:
|
|
129
126
|
# HexaPDF::Object.deep_copy(object) -> copy
|
|
130
127
|
#
|
|
@@ -132,15 +129,13 @@ module HexaPDF
|
|
|
132
129
|
def self.deep_copy(object)
|
|
133
130
|
case object
|
|
134
131
|
when Hash
|
|
135
|
-
object.
|
|
132
|
+
object.transform_values {|value| deep_copy(value) }
|
|
136
133
|
when Array
|
|
137
134
|
object.map {|o| deep_copy(o) }
|
|
138
135
|
when HexaPDF::Object
|
|
139
136
|
(object.indirect? || object.must_be_indirect? ? object : deep_copy(object.value))
|
|
140
137
|
when HexaPDF::Reference
|
|
141
138
|
object
|
|
142
|
-
when *NOT_DUPLICATABLE_CLASSES
|
|
143
|
-
object
|
|
144
139
|
else
|
|
145
140
|
object.dup
|
|
146
141
|
end
|
|
@@ -251,29 +246,31 @@ module HexaPDF
|
|
|
251
246
|
end
|
|
252
247
|
|
|
253
248
|
# :call-seq:
|
|
254
|
-
# obj.validate(auto_correct: true)
|
|
255
|
-
# obj.validate(auto_correct: true) {|msg, correctable| block } -> true or false
|
|
249
|
+
# obj.validate(auto_correct: true) -> true or false
|
|
250
|
+
# obj.validate(auto_correct: true) {|msg, correctable, obj| block } -> true or false
|
|
256
251
|
#
|
|
257
|
-
# Validates the object
|
|
258
|
-
#
|
|
259
|
-
# its documentation for more information.
|
|
252
|
+
# Validates the object, optionally corrects problems when the option +auto_correct+ is set and
|
|
253
|
+
# returns +true+ if the object is deemed valid and +false+ otherwise.
|
|
260
254
|
#
|
|
261
255
|
# If a block is given, it is called on validation problems with a problem description and
|
|
262
|
-
# whether the problem is correctable.
|
|
256
|
+
# whether the problem is automatically correctable. The third argument to the block is usually
|
|
257
|
+
# this object but may be another object if during auto-correction a new object was created and
|
|
258
|
+
# validated.
|
|
263
259
|
#
|
|
264
|
-
#
|
|
260
|
+
# The validation routine itself has to be implemented in the #perform_validation method - see
|
|
261
|
+
# its documentation for more information.
|
|
265
262
|
#
|
|
266
263
|
# *Note*: Even if the return value is +true+ there may be problems since HexaPDF doesn't
|
|
267
264
|
# currently implement the full PDF spec. However, if the return value is +false+, there is
|
|
268
265
|
# certainly a problem!
|
|
269
266
|
def validate(auto_correct: true)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
true
|
|
267
|
+
result = true
|
|
268
|
+
perform_validation do |msg, correctable, object|
|
|
269
|
+
yield(msg, correctable, object || self) if block_given?
|
|
270
|
+
result = false unless correctable
|
|
271
|
+
return false unless auto_correct
|
|
276
272
|
end
|
|
273
|
+
result
|
|
277
274
|
end
|
|
278
275
|
|
|
279
276
|
# Makes a deep copy of the source PDF object and resets the object identifier.
|
|
@@ -339,17 +336,25 @@ module HexaPDF
|
|
|
339
336
|
# are also performed!
|
|
340
337
|
#
|
|
341
338
|
# When the validation routine finds that the object is invalid, it has to yield a problem
|
|
342
|
-
# description and whether the problem can be corrected.
|
|
343
|
-
#
|
|
344
|
-
#
|
|
339
|
+
# description and whether the problem can be corrected. An optional third argument may contain
|
|
340
|
+
# the object that gets validated if it is different from this object (may happen when
|
|
341
|
+
# auto-correction is used).
|
|
342
|
+
#
|
|
343
|
+
# After yielding, the problem has to be corrected if it is correctable. If it is not correctable
|
|
344
|
+
# and not correcting would lead to exceptions the method has to return early.
|
|
345
345
|
#
|
|
346
|
-
# Here is a sample validation routine for
|
|
346
|
+
# Here is a sample validation routine for a dictionary object type:
|
|
347
347
|
#
|
|
348
348
|
# def perform_validation
|
|
349
349
|
# super
|
|
350
|
-
#
|
|
351
|
-
#
|
|
352
|
-
#
|
|
350
|
+
#
|
|
351
|
+
# if value[:SomeKey].length != 7
|
|
352
|
+
# yield("Length of /SomeKey is invalid")
|
|
353
|
+
# # No need to return early here because following check doesn't rely on /SomeKey
|
|
354
|
+
# end
|
|
355
|
+
#
|
|
356
|
+
# if value[:OtherKey] % 2 == 0
|
|
357
|
+
# yield("/OtherKey needs to contain an odd number of elements")
|
|
353
358
|
# end
|
|
354
359
|
# end
|
|
355
360
|
def perform_validation(&block)
|
data/lib/hexapdf/parser.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-2020 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
|
|
@@ -59,6 +59,7 @@ module HexaPDF
|
|
|
59
59
|
@tokenizer = Tokenizer.new(io)
|
|
60
60
|
@document = document
|
|
61
61
|
@object_stream_data = {}
|
|
62
|
+
@reconstructed_revision = nil
|
|
62
63
|
retrieve_pdf_header_offset_and_version
|
|
63
64
|
end
|
|
64
65
|
|
|
@@ -86,6 +87,8 @@ module HexaPDF
|
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
@document.wrap(obj, oid: oid, gen: gen, stream: stream)
|
|
90
|
+
rescue HexaPDF::MalformedPDFError
|
|
91
|
+
reconstructed_revision.object(xref_entry)
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
# Parses the indirect object at the specified offset.
|
|
@@ -235,14 +238,14 @@ module HexaPDF
|
|
|
235
238
|
@tokenizer.skip_whitespace
|
|
236
239
|
start.upto(start + number_of_entries - 1) do |oid|
|
|
237
240
|
pos, gen, type = @tokenizer.next_xref_entry do |matched_size|
|
|
238
|
-
maybe_raise("Invalid cross-reference
|
|
239
|
-
force: matched_size
|
|
241
|
+
maybe_raise("Invalid cross-reference entry", pos: @tokenizer.pos,
|
|
242
|
+
force: !matched_size)
|
|
240
243
|
end
|
|
241
244
|
if xref.entry?(oid)
|
|
242
245
|
next
|
|
243
246
|
elsif type == 'n'
|
|
244
247
|
if pos == 0 || gen > 65535
|
|
245
|
-
maybe_raise("Invalid in use cross-reference entry
|
|
248
|
+
maybe_raise("Invalid in use cross-reference entry",
|
|
246
249
|
pos: @tokenizer.pos)
|
|
247
250
|
xref.add_free_entry(oid, gen)
|
|
248
251
|
else
|
|
@@ -281,7 +284,8 @@ module HexaPDF
|
|
|
281
284
|
@io.seek(0, IO::SEEK_END)
|
|
282
285
|
step_size = 1024
|
|
283
286
|
pos = @io.pos
|
|
284
|
-
eof_not_found =
|
|
287
|
+
eof_not_found = pos == 0
|
|
288
|
+
startxref_missing = false
|
|
285
289
|
|
|
286
290
|
while pos != 0
|
|
287
291
|
@io.pos = [pos - step_size, 0].max
|
|
@@ -312,6 +316,11 @@ module HexaPDF
|
|
|
312
316
|
@startxref_offset = lines[eof_index - 1].to_i
|
|
313
317
|
end
|
|
314
318
|
|
|
319
|
+
# Returns the reconstructed revision.
|
|
320
|
+
def reconstructed_revision
|
|
321
|
+
@reconstructed_revision ||= reconstruct_revision
|
|
322
|
+
end
|
|
323
|
+
|
|
315
324
|
# Returns the PDF version number that is stored in the file header.
|
|
316
325
|
#
|
|
317
326
|
# See: PDF1.7 s7.5.2
|
|
@@ -333,10 +342,64 @@ module HexaPDF
|
|
|
333
342
|
# See: PDF1.7 s7.5.2, ADB1.7 sH.3-3.4.1
|
|
334
343
|
def retrieve_pdf_header_offset_and_version
|
|
335
344
|
@io.seek(0)
|
|
336
|
-
@header_offset = @io.read(1024).index(/%PDF-(\d\.\d)/) || 0
|
|
345
|
+
@header_offset = (@io.read(1024) || '').index(/%PDF-(\d\.\d)/) || 0
|
|
337
346
|
@header_version = $1
|
|
338
347
|
end
|
|
339
348
|
|
|
349
|
+
# Tries to reconstruct the PDF document's main cross-reference table by serially parsing the
|
|
350
|
+
# file and returning a Revision object for loading the found objects.
|
|
351
|
+
#
|
|
352
|
+
# If the file contains multiple cross-reference sections, all objects will be put into a single
|
|
353
|
+
# cross-reference table, later objects overwriting prior ones.
|
|
354
|
+
def reconstruct_revision
|
|
355
|
+
raise unless @document.config['parser.try_xref_reconstruction']
|
|
356
|
+
msg = "#{$!} - trying cross-reference table reconstruction"
|
|
357
|
+
@document.config['parser.on_correctable_error'].call(@document, msg, @tokenizer.pos)
|
|
358
|
+
|
|
359
|
+
xref = XRefSection.new
|
|
360
|
+
@tokenizer.pos = 0
|
|
361
|
+
while true
|
|
362
|
+
pos = @tokenizer.pos
|
|
363
|
+
@tokenizer.scan_until(/(\n|\r\n?)+|\z/)
|
|
364
|
+
next_new_line_pos = @tokenizer.pos
|
|
365
|
+
@tokenizer.pos = pos
|
|
366
|
+
|
|
367
|
+
token = @tokenizer.next_token rescue nil
|
|
368
|
+
if token.kind_of?(Integer)
|
|
369
|
+
gen = @tokenizer.next_token rescue nil
|
|
370
|
+
tok = @tokenizer.next_token rescue nil
|
|
371
|
+
if @tokenizer.pos > next_new_line_pos
|
|
372
|
+
@tokenizer.pos = next_new_line_pos
|
|
373
|
+
elsif gen.kind_of?(Integer) && tok.kind_of?(Tokenizer::Token) && tok == 'obj'
|
|
374
|
+
xref.add_in_use_entry(token, gen, pos)
|
|
375
|
+
@tokenizer.scan_until(/(?:\n|\r\n?)endobj\b/)
|
|
376
|
+
end
|
|
377
|
+
elsif token.kind_of?(Tokenizer::Token) && token == 'trailer'
|
|
378
|
+
obj = @tokenizer.next_object rescue nil
|
|
379
|
+
# Use last trailer found in case of multiple revisions but use first trailer in case of
|
|
380
|
+
# linearized file.
|
|
381
|
+
trailer = obj if obj.kind_of?(Hash) && (obj.key?(:Prev) || trailer.nil?)
|
|
382
|
+
elsif token == Tokenizer::NO_MORE_TOKENS
|
|
383
|
+
break
|
|
384
|
+
else
|
|
385
|
+
@tokenizer.pos = next_new_line_pos
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
trailer&.delete(:Prev) # no need for this and may wreak havoc
|
|
390
|
+
if !trailer || trailer.empty?
|
|
391
|
+
raise_malformed("Could not reconstruct malformed PDF because trailer was not found", pos: 0)
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
loader = lambda do |xref_entry|
|
|
395
|
+
obj, oid, gen, stream = parse_indirect_object(xref_entry.pos)
|
|
396
|
+
@document.wrap(obj, oid: oid, gen: gen, stream: stream)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
Revision.new(@document.wrap(trailer, type: :XXTrailer), xref_section: xref,
|
|
400
|
+
loader: loader)
|
|
401
|
+
end
|
|
402
|
+
|
|
340
403
|
# Raises a HexaPDF::MalformedPDFError with the given message and source position.
|
|
341
404
|
def raise_malformed(msg, pos: nil)
|
|
342
405
|
raise HexaPDF::MalformedPDFError.new(msg, pos: pos)
|
data/lib/hexapdf/pdf_array.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-2020 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
|
|
@@ -83,7 +83,7 @@ module HexaPDF
|
|
|
83
83
|
# subclasses) and the given data has not (including subclasses), the data is stored inside the
|
|
84
84
|
# HexaPDF::Object.
|
|
85
85
|
def []=(index, data)
|
|
86
|
-
if value[index].
|
|
86
|
+
if value[index].instance_of?(HexaPDF::Object) && !data.kind_of?(HexaPDF::Object) &&
|
|
87
87
|
!data.kind_of?(HexaPDF::Reference)
|
|
88
88
|
value[index].value = data
|
|
89
89
|
else
|
|
@@ -113,6 +113,13 @@ module HexaPDF
|
|
|
113
113
|
value.delete_at(index)
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
# Deletes all values from the PDFArray that are equal to the given object.
|
|
117
|
+
#
|
|
118
|
+
# Returns the last deleted item, or +nil+ if no matching item is found.
|
|
119
|
+
def delete(object)
|
|
120
|
+
value.delete(object)
|
|
121
|
+
end
|
|
122
|
+
|
|
116
123
|
# :call-seq:
|
|
117
124
|
# array.slice!(index) -> obj or nil
|
|
118
125
|
# array.slice!(start, length) -> new_array or nil
|
|
@@ -196,7 +203,7 @@ module HexaPDF
|
|
|
196
203
|
data = document.deref(data)
|
|
197
204
|
value[index] = data if index
|
|
198
205
|
end
|
|
199
|
-
if data.
|
|
206
|
+
if data.instance_of?(HexaPDF::Object) || (data.kind_of?(HexaPDF::Object) && data.value.nil?)
|
|
200
207
|
data = data.value
|
|
201
208
|
end
|
|
202
209
|
data
|
data/lib/hexapdf/rectangle.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-2020 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
|
|
@@ -59,31 +59,61 @@ module HexaPDF
|
|
|
59
59
|
self[0]
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
# Sets the x-coordinate of the bottom-left corner to the given value.
|
|
63
|
+
def left=(x)
|
|
64
|
+
value[0] = x
|
|
65
|
+
end
|
|
66
|
+
|
|
62
67
|
# Returns the x-coordinate of the top-right corner.
|
|
63
68
|
def right
|
|
64
69
|
self[2]
|
|
65
70
|
end
|
|
66
71
|
|
|
72
|
+
# Sets the x-coordinate of the top-right corner to the given value.
|
|
73
|
+
def right=(x)
|
|
74
|
+
value[2] = x
|
|
75
|
+
end
|
|
76
|
+
|
|
67
77
|
# Returns the y-coordinate of the bottom-left corner.
|
|
68
78
|
def bottom
|
|
69
79
|
self[1]
|
|
70
80
|
end
|
|
71
81
|
|
|
82
|
+
# Sets the y-coordinate of the bottom-left corner to the given value.
|
|
83
|
+
def bottom=(y)
|
|
84
|
+
value[1] = y
|
|
85
|
+
end
|
|
86
|
+
|
|
72
87
|
# Returns the y-coordinate of the top-right corner.
|
|
73
88
|
def top
|
|
74
89
|
self[3]
|
|
75
90
|
end
|
|
76
91
|
|
|
92
|
+
# Sets the y-coordinate of the top-right corner to the given value.
|
|
93
|
+
def top=(y)
|
|
94
|
+
value[3] = y
|
|
95
|
+
end
|
|
96
|
+
|
|
77
97
|
# Returns the width of the rectangle.
|
|
78
98
|
def width
|
|
79
99
|
self[2] - self[0]
|
|
80
100
|
end
|
|
81
101
|
|
|
102
|
+
# Sets the width of the rectangle to the given value.
|
|
103
|
+
def width=(val)
|
|
104
|
+
self[2] = self[0] + val
|
|
105
|
+
end
|
|
106
|
+
|
|
82
107
|
# Returns the height of the rectangle.
|
|
83
108
|
def height
|
|
84
109
|
self[3] - self[1]
|
|
85
110
|
end
|
|
86
111
|
|
|
112
|
+
# Sets the height of the rectangle to the given value.
|
|
113
|
+
def height=(val)
|
|
114
|
+
self[3] = self[1] + val
|
|
115
|
+
end
|
|
116
|
+
|
|
87
117
|
# Compares this rectangle to +other+ like in Object#== but also allows comparison to simple
|
|
88
118
|
# arrays if the rectangle is a direct object.
|
|
89
119
|
def ==(other)
|
data/lib/hexapdf/reference.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-2020 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
|
data/lib/hexapdf/revision.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-2020 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
|
|
@@ -172,6 +172,7 @@ module HexaPDF
|
|
|
172
172
|
|
|
173
173
|
obj = object(ref_or_oid)
|
|
174
174
|
obj.data.value = nil
|
|
175
|
+
obj.document = nil
|
|
175
176
|
if mark_as_free
|
|
176
177
|
add_without_check(HexaPDF::Object.new(nil, oid: obj.oid, gen: obj.gen))
|
|
177
178
|
else
|