hexapdf 0.11.9 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|