hexapdf 0.11.7 → 0.12.2
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 +121 -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 +18 -9
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/form.rb +240 -0
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +1 -1
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +66 -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 +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/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 +1 -1
- data/lib/hexapdf/dictionary_fields.rb +1 -1
- data/lib/hexapdf/document.rb +14 -5
- 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/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 +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 +7 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -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 +1 -1
- 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 +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_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 +1 -1
- 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 +1 -1
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +1 -1
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +1 -1
- data/lib/hexapdf/layout/text_shaper.rb +1 -1
- data/lib/hexapdf/layout/width_from_polygon.rb +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 +2 -2
- data/lib/hexapdf/parser.rb +4 -3
- data/lib/hexapdf/pdf_array.rb +1 -1
- 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 +1 -1
- 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 +1 -1
- data/lib/hexapdf/tokenizer.rb +1 -1
- 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 +401 -0
- data/lib/hexapdf/type/acro_form/button_field.rb +300 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
- data/lib/hexapdf/type/acro_form/field.rb +220 -17
- data/lib/hexapdf/type/acro_form/form.rb +157 -7
- data/lib/hexapdf/type/acro_form/text_field.rb +186 -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 +1 -1
- 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 +239 -2
- data/lib/hexapdf/type/catalog.rb +21 -1
- data/lib/hexapdf/type/cid_font.rb +1 -1
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +1 -1
- data/lib/hexapdf/type/font.rb +18 -1
- data/lib/hexapdf/type/font_descriptor.rb +2 -2
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_true_type.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type1.rb +16 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +10 -1
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +3 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/names.rb +1 -1
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/page.rb +20 -5
- data/lib/hexapdf/type/page_tree_node.rb +8 -11
- data/lib/hexapdf/type/resources.rb +16 -3
- data/lib/hexapdf/type/trailer.rb +2 -3
- 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 +1 -1
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/test/hexapdf/content/common.rb +2 -2
- 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_security_handler.rb +4 -0
- 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/test_document.rb +12 -0
- data/test/hexapdf/test_parser.rb +10 -0
- data/test/hexapdf/test_rectangle.rb +14 -0
- data/test/hexapdf/test_revision.rb +3 -0
- data/test/hexapdf/test_serializer.rb +3 -3
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +515 -0
- data/test/hexapdf/type/acro_form/test_button_field.rb +276 -0
- data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
- data/test/hexapdf/type/acro_form/test_field.rb +124 -6
- data/test/hexapdf/type/acro_form/test_form.rb +189 -22
- data/test/hexapdf/type/acro_form/test_text_field.rb +119 -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_type1.rb +8 -0
- data/test/hexapdf/type/test_form.rb +18 -0
- data/test/hexapdf/type/test_image.rb +7 -0
- data/test/hexapdf/type/test_page.rb +37 -6
- data/test/hexapdf/type/test_page_tree_node.rb +20 -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 +13 -1
- data/test/test_helper.rb +1 -1
- metadata +38 -18
- data/lib/hexapdf/filter/dct_decode.rb +0 -60
data/lib/hexapdf/cli/files.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
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
|
+
#
|
|
3
|
+
#--
|
|
4
|
+
# This file is part of HexaPDF.
|
|
5
|
+
#
|
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
+
# Copyright (C) 2014-2020 Thomas Leitner
|
|
8
|
+
#
|
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
16
|
+
#
|
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
20
|
+
# License for more details.
|
|
21
|
+
#
|
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
|
24
|
+
#
|
|
25
|
+
# The interactive user interfaces in modified source and object code
|
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
|
28
|
+
#
|
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
|
31
|
+
# is created or manipulated using HexaPDF.
|
|
32
|
+
#
|
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
|
35
|
+
#++
|
|
36
|
+
|
|
37
|
+
require 'hexapdf/cli/command'
|
|
38
|
+
require 'strscan'
|
|
39
|
+
|
|
40
|
+
module HexaPDF
|
|
41
|
+
module CLI
|
|
42
|
+
|
|
43
|
+
# Processes a PDF that contains an interactive form (AcroForm).
|
|
44
|
+
class Form < Command
|
|
45
|
+
|
|
46
|
+
def initialize #:nodoc:
|
|
47
|
+
super('form', takes_commands: false)
|
|
48
|
+
short_desc("Show form fields and fill out a form")
|
|
49
|
+
long_desc(<<~EOF)
|
|
50
|
+
Use this command to process interactive PDF forms.
|
|
51
|
+
|
|
52
|
+
If the the output file name is not given, all form fields are listed in page order. Use
|
|
53
|
+
the global --verbose option to show additional information like field type and location.
|
|
54
|
+
|
|
55
|
+
If the output file name is given, the fields can be interactively filled out. By
|
|
56
|
+
additionally using the --template option, the data for the fields is read from the given
|
|
57
|
+
template file instead of the standard input.
|
|
58
|
+
EOF
|
|
59
|
+
|
|
60
|
+
options.on("--password PASSWORD", "-p", String,
|
|
61
|
+
"The password for decryption. Use - for reading from standard input.") do |pwd|
|
|
62
|
+
@password = (pwd == '-' ? read_password : pwd)
|
|
63
|
+
end
|
|
64
|
+
options.on("--template TEMPLATE_FILE", "-t TEMPLATE_FILE",
|
|
65
|
+
"Use the template file for the field values") do |template|
|
|
66
|
+
@template = template
|
|
67
|
+
end
|
|
68
|
+
options.on("--[no-]viewer-override", "Let the PDF viewer override the visual " \
|
|
69
|
+
"appearance. Default: use setting from input PDF") do |need_appearances|
|
|
70
|
+
@need_appearances = need_appearances
|
|
71
|
+
end
|
|
72
|
+
options.on("--[no-]incremental-save", "Append the changes instead of rewriting the " \
|
|
73
|
+
"whole file. Default: true") do |incremental|
|
|
74
|
+
@incremental = incremental
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@password = nil
|
|
78
|
+
@template = nil
|
|
79
|
+
@need_appearances = nil
|
|
80
|
+
@incremental = true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def execute(in_file, out_file = nil) #:nodoc:
|
|
84
|
+
maybe_raise_on_existing_file(out_file) if out_file
|
|
85
|
+
with_document(in_file, password: @password, out_file: out_file,
|
|
86
|
+
incremental: @incremental) do |doc|
|
|
87
|
+
if !doc.acro_form
|
|
88
|
+
raise "This PDF doesn't contain an interactive form"
|
|
89
|
+
elsif out_file
|
|
90
|
+
doc.acro_form[:NeedAppearances] = @need_appearances unless @need_appearances.nil?
|
|
91
|
+
if @template
|
|
92
|
+
fill_form_with_template(doc)
|
|
93
|
+
else
|
|
94
|
+
fill_form(doc)
|
|
95
|
+
end
|
|
96
|
+
else
|
|
97
|
+
list_form_fields(doc)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
# Lists all terminal form fields.
|
|
105
|
+
def list_form_fields(doc)
|
|
106
|
+
current_page_index = -1
|
|
107
|
+
each_field(doc) do |_page, page_index, field, widget|
|
|
108
|
+
if current_page_index != page_index
|
|
109
|
+
puts "Page #{page_index + 1}"
|
|
110
|
+
current_page_index = page_index
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
field_name = field.full_field_name +
|
|
114
|
+
(field.alternate_field_name ? " (#{field.alternate_field_name})" : '')
|
|
115
|
+
concrete_field_type = field.concrete_field_type
|
|
116
|
+
nice_field_type = concrete_field_type.to_s.split('_').map(&:capitalize).join(' ')
|
|
117
|
+
position = "(#{widget[:Rect].left}, #{widget[:Rect].bottom})"
|
|
118
|
+
|
|
119
|
+
puts " #{field_name}"
|
|
120
|
+
if command_parser.verbosity_info?
|
|
121
|
+
printf(" └─ %-22s | %-20s\n", nice_field_type, position)
|
|
122
|
+
end
|
|
123
|
+
puts " └─ #{field.field_value.inspect}"
|
|
124
|
+
if command_parser.verbosity_info?
|
|
125
|
+
if field.field_type == :Ch
|
|
126
|
+
puts " └─ Options: #{field.option_items.map(&:inspect).join(', ')}"
|
|
127
|
+
elsif concrete_field_type == :radio_button
|
|
128
|
+
puts " └─ Options: #{field.radio_button_values.map(&:inspect).join(', ')}"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Fills out the form by interactively asking the user for field values.
|
|
135
|
+
def fill_form(doc)
|
|
136
|
+
current_page_index = -1
|
|
137
|
+
each_field(doc) do |_page, page_index, field, _widget|
|
|
138
|
+
if current_page_index != page_index
|
|
139
|
+
puts "Page #{page_index + 1}"
|
|
140
|
+
current_page_index = page_index
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
field_name = field.full_field_name +
|
|
144
|
+
(field.alternate_field_name ? " (#{field.alternate_field_name})" : '')
|
|
145
|
+
concrete_field_type = field.concrete_field_type
|
|
146
|
+
|
|
147
|
+
puts " #{field_name}"
|
|
148
|
+
puts " └─ Current value: #{field.field_value.inspect}"
|
|
149
|
+
|
|
150
|
+
if field.field_type == :Ch
|
|
151
|
+
puts " └─ Possible values: #{field.option_items.map(&:inspect).join(', ')}"
|
|
152
|
+
elsif concrete_field_type == :radio_button
|
|
153
|
+
puts " └─ Possible values: #{field.radio_button_values.map(&:inspect).join(', ')}"
|
|
154
|
+
elsif concrete_field_type == :check_box
|
|
155
|
+
puts " └─ Possible values: y(es), t(rue); n(o), f(alse)"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
begin
|
|
159
|
+
print " └─ New value: "
|
|
160
|
+
value = $stdin.readline.chomp
|
|
161
|
+
next if value.empty?
|
|
162
|
+
apply_field_value(field, value)
|
|
163
|
+
rescue HexaPDF::Error => e
|
|
164
|
+
puts " ⚠ #{e.message}"
|
|
165
|
+
retry
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Fills out the form using the data from the provided template file.
|
|
171
|
+
def fill_form_with_template(doc)
|
|
172
|
+
data = parse_template
|
|
173
|
+
form = doc.acro_form
|
|
174
|
+
data.each do |name, value|
|
|
175
|
+
field = form.field_by_name(name)
|
|
176
|
+
raise "Field '#{name}' not found in input PDF" unless field
|
|
177
|
+
apply_field_value(field, value)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Parses the data from the given template file.
|
|
182
|
+
def parse_template
|
|
183
|
+
data = {}
|
|
184
|
+
scanner = StringScanner.new(File.read(@template))
|
|
185
|
+
until scanner.eos?
|
|
186
|
+
field_name = scanner.scan(/(\\:|[^:])*?:/)
|
|
187
|
+
break unless field_name
|
|
188
|
+
field_name.gsub!(/\\:/, ':')
|
|
189
|
+
field_value = scanner.scan(/.*?(?=^\S|\z)/m)
|
|
190
|
+
data[field_name.chop] = field_value.strip.gsub(/^\s*/, '') if field_value
|
|
191
|
+
end
|
|
192
|
+
if !scanner.eos? && command_parser.verbosity_warning?
|
|
193
|
+
$stderr.puts "Warning: Some template could not be parsed"
|
|
194
|
+
end
|
|
195
|
+
data
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Applies the given value to the field.
|
|
199
|
+
def apply_field_value(field, value)
|
|
200
|
+
case field.concrete_field_type
|
|
201
|
+
when :single_line_text_field
|
|
202
|
+
field.field_value = value
|
|
203
|
+
when :combo_box, :list_box
|
|
204
|
+
field.field_value = value
|
|
205
|
+
when :editable_combo_box
|
|
206
|
+
field.field_value = value
|
|
207
|
+
when :check_box
|
|
208
|
+
unless value.match?(/y(es)?|t(rue)?|f(alse)?|n(o)/)
|
|
209
|
+
raise HexaPDF::Error, "Invalid input, use one of the possible values"
|
|
210
|
+
end
|
|
211
|
+
field.field_value = value.match?(/y(es)?|t(rue)?/)
|
|
212
|
+
when :radio_button
|
|
213
|
+
field.field_value = value.intern
|
|
214
|
+
else
|
|
215
|
+
raise "Field type not yet supported"
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Iterates over all non-push button fields in page order. If a field appears on multiple
|
|
220
|
+
# pages, it is only yielded on the first page.
|
|
221
|
+
def each_field(doc) # :yields: page, page_index, field
|
|
222
|
+
seen = {}
|
|
223
|
+
|
|
224
|
+
doc.pages.each_with_index do |page, page_index|
|
|
225
|
+
page[:Annots]&.each do |annotation|
|
|
226
|
+
next unless annotation[:Subtype] == :Widget
|
|
227
|
+
field = annotation.form_field
|
|
228
|
+
next if field.concrete_field_type == :push_button
|
|
229
|
+
unless seen[field]
|
|
230
|
+
yield(page, page_index, field, annotation)
|
|
231
|
+
seen[field] = true
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
end
|
|
240
|
+
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-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/cli/images.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/cli/info.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/cli/inspect.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/cli/merge.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/cli/modify.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/cli/optimize.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/cli/split.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
|
|
@@ -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/composer.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
|
|
@@ -297,7 +297,7 @@ module HexaPDF
|
|
|
297
297
|
style ||= base_style
|
|
298
298
|
style = style.dup.update(**options) unless options.empty?
|
|
299
299
|
style.font(base_style.font) unless style.font?
|
|
300
|
-
style.font(@document.fonts.add(style.font)) unless style.font.respond_to?(:
|
|
300
|
+
style.font(@document.fonts.add(style.font)) unless style.font.respond_to?(:pdf_object)
|
|
301
301
|
style
|
|
302
302
|
end
|
|
303
303
|
|
|
@@ -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
|
|
@@ -48,8 +48,9 @@ module HexaPDF
|
|
|
48
48
|
# easily be changed.
|
|
49
49
|
#
|
|
50
50
|
# Some options are defined as global options because they are needed on the class level - see
|
|
51
|
-
# HexaPDF::GlobalConfiguration. Other options can be configured for
|
|
52
|
-
# allow to fine-tune some behavior - see
|
|
51
|
+
# HexaPDF::GlobalConfiguration[index.html#GlobalConfiguration]. Other options can be configured for
|
|
52
|
+
# individual documents as they allow to fine-tune some behavior - see
|
|
53
|
+
# HexaPDF::DefaultDocumentConfiguration[index.html#DefaultDocumentConfiguration].
|
|
53
54
|
#
|
|
54
55
|
# A configuration option name is dot-separted to provide a hierarchy of option names. For
|
|
55
56
|
# example, io.chunk_size.
|
|
@@ -144,6 +145,43 @@ module HexaPDF
|
|
|
144
145
|
#
|
|
145
146
|
# The following options are provided:
|
|
146
147
|
#
|
|
148
|
+
# acro_form.appearance_generator::
|
|
149
|
+
# The class that should be used for generating appearances for AcroForm fields. If the value is
|
|
150
|
+
# a String, it should contain the name of a constant to such a class.
|
|
151
|
+
#
|
|
152
|
+
# See HexaPDF::Type::AcroForm::AppearanceGenerator
|
|
153
|
+
#
|
|
154
|
+
# acro_form.create_appearances::
|
|
155
|
+
# A boolean specifying whether an AcroForm field's appearances should automatically be
|
|
156
|
+
# generated if they are missing.
|
|
157
|
+
#
|
|
158
|
+
# acro_form.text_field.default_width::
|
|
159
|
+
# A number specifying the default width of AcroForm text fields which should be auto-sized.
|
|
160
|
+
#
|
|
161
|
+
# acro_form.default_font_size::
|
|
162
|
+
# A number specifying the default font size of AcroForm text fields which should be auto-sized.
|
|
163
|
+
#
|
|
164
|
+
# acro_form.fallback_font::
|
|
165
|
+
# The font that should be used when a variable text field references a font that cannot be used.
|
|
166
|
+
#
|
|
167
|
+
# Can either be the name of a font, like 'Helvetica', or an array consisting of the font name
|
|
168
|
+
# and a hash of font options, like ['Helvetica', variant: :italic]. If set to +nil+, the use of
|
|
169
|
+
# the fallback font is disabled.
|
|
170
|
+
#
|
|
171
|
+
# Default is 'Helvetica'.
|
|
172
|
+
#
|
|
173
|
+
# acro_form.on_invalid_value::
|
|
174
|
+
# Callback hook when an invalid value is set for certain types of AcroForm fields.
|
|
175
|
+
#
|
|
176
|
+
# The value needs to be an object that responds to \#call(field, value) where +field+ is the
|
|
177
|
+
# AcroForm field on which the value is set and +value+ is the invalid value. The returned value
|
|
178
|
+
# is used instead of the invalid value.
|
|
179
|
+
#
|
|
180
|
+
# The default implementation raises an error.
|
|
181
|
+
#
|
|
182
|
+
# acro_form.text_field.default_width::
|
|
183
|
+
# A number specifying the default width of AcroForm text fields which should be auto-sized.
|
|
184
|
+
#
|
|
147
185
|
# document.auto_decrypt::
|
|
148
186
|
# A boolean determining whether the document should be decrypted automatically when parsed.
|
|
149
187
|
#
|
|
@@ -307,7 +345,16 @@ module HexaPDF
|
|
|
307
345
|
# task.map::
|
|
308
346
|
# A mapping from task names to callable task objects. See HexaPDF::Task for more information.
|
|
309
347
|
DefaultDocumentConfiguration =
|
|
310
|
-
Configuration.new('
|
|
348
|
+
Configuration.new('acro_form.appearance_generator' => 'HexaPDF::Type::AcroForm::AppearanceGenerator',
|
|
349
|
+
'acro_form.create_appearances' => true,
|
|
350
|
+
'acro_form.default_font_size' => 10,
|
|
351
|
+
'acro_form.fallback_font' => 'Helvetica',
|
|
352
|
+
'acro_form.on_invalid_value' => proc do |field, value|
|
|
353
|
+
raise HexaPDF::Error, "Invalid value #{value.inspect} for " \
|
|
354
|
+
"#{field.concrete_field_type} field #{field.full_field_name}"
|
|
355
|
+
end,
|
|
356
|
+
'acro_form.text_field.default_width' => 100,
|
|
357
|
+
'document.auto_decrypt' => true,
|
|
311
358
|
'encryption.aes' => 'HexaPDF::Encryption::FastAES',
|
|
312
359
|
'encryption.arc4' => 'HexaPDF::Encryption::FastARC4',
|
|
313
360
|
'encryption.filter_map' => {
|
|
@@ -326,12 +373,12 @@ module HexaPDF
|
|
|
326
373
|
Fl: 'HexaPDF::Filter::FlateDecode',
|
|
327
374
|
RunLengthDecode: 'HexaPDF::Filter::RunLengthDecode',
|
|
328
375
|
RL: 'HexaPDF::Filter::RunLengthDecode',
|
|
329
|
-
CCITTFaxDecode:
|
|
330
|
-
CCF:
|
|
331
|
-
JBIG2Decode:
|
|
332
|
-
DCTDecode: 'HexaPDF::Filter::
|
|
333
|
-
DCT: 'HexaPDF::Filter::
|
|
334
|
-
JPXDecode: 'HexaPDF::Filter::
|
|
376
|
+
CCITTFaxDecode: 'HexaPDF::Filter::PassThrough',
|
|
377
|
+
CCF: 'HexaPDF::Filter::PassThrough',
|
|
378
|
+
JBIG2Decode: 'HexaPDF::Filter::PassThrough',
|
|
379
|
+
DCTDecode: 'HexaPDF::Filter::PassThrough',
|
|
380
|
+
DCT: 'HexaPDF::Filter::PassThrough',
|
|
381
|
+
JPXDecode: 'HexaPDF::Filter::PassThrough',
|
|
335
382
|
Crypt: nil,
|
|
336
383
|
Encryption: 'HexaPDF::Filter::Encryption',
|
|
337
384
|
},
|
|
@@ -447,10 +494,13 @@ module HexaPDF
|
|
|
447
494
|
Action: 'HexaPDF::Type::Action',
|
|
448
495
|
XXLaunchActionWinParameters: 'HexaPDF::Type::Actions::Launch::WinParameters',
|
|
449
496
|
Annot: 'HexaPDF::Type::Annotation',
|
|
450
|
-
XXAppearanceCharacteristics:
|
|
497
|
+
XXAppearanceCharacteristics: \
|
|
498
|
+
'HexaPDF::Type::Annotations::Widget::AppearanceCharacteristics',
|
|
451
499
|
XXIconFit: 'HexaPDF::Type::IconFit',
|
|
452
500
|
XXAcroForm: 'HexaPDF::Type::AcroForm::Form',
|
|
453
501
|
XXAcroFormField: 'HexaPDF::Type::AcroForm::Field',
|
|
502
|
+
XXAppearanceDictionary: 'HexaPDF::Type::Annotation::AppearanceDictionary',
|
|
503
|
+
Border: 'HexaPDF::Type::Annotation::Border',
|
|
454
504
|
},
|
|
455
505
|
'object.subtype_map' => {
|
|
456
506
|
nil => {
|
|
@@ -492,6 +542,11 @@ module HexaPDF
|
|
|
492
542
|
Link: 'HexaPDF::Type::Annotations::Link',
|
|
493
543
|
Widget: 'HexaPDF::Type::Annotations::Widget',
|
|
494
544
|
},
|
|
545
|
+
XXAcroFormField: {
|
|
546
|
+
Tx: 'HexaPDF::Type::AcroForm::TextField',
|
|
547
|
+
Btn: 'HexaPDF::Type::AcroForm::ButtonField',
|
|
548
|
+
Ch: 'HexaPDF::Type::AcroForm::ChoiceField',
|
|
549
|
+
},
|
|
495
550
|
})
|
|
496
551
|
|
|
497
552
|
end
|