hexapdf 0.11.8 → 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +126 -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 +1 -1
- 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 +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 +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/common_tokenizer_tests.rb +5 -0
- 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_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +522 -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 +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
|