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
|
@@ -0,0 +1,186 @@
|
|
|
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/error'
|
|
38
|
+
require 'hexapdf/type/acro_form/variable_text_field'
|
|
39
|
+
|
|
40
|
+
module HexaPDF
|
|
41
|
+
module Type
|
|
42
|
+
module AcroForm
|
|
43
|
+
|
|
44
|
+
# AcroForm text fields provide a box or space to fill-in data entered from keyboard. The text
|
|
45
|
+
# may be restricted to a single line or can span multiple lines.
|
|
46
|
+
#
|
|
47
|
+
# == Type Specific Field Flags
|
|
48
|
+
#
|
|
49
|
+
# :multiline:: If set, the text field may contain multiple lines.
|
|
50
|
+
#
|
|
51
|
+
# :password:: The field is a password field. This changes the behaviour of the PDF reader
|
|
52
|
+
# application to not echo the input text and to not store it in the PDF file.
|
|
53
|
+
#
|
|
54
|
+
# :file_select:: The text field represents a file selection control where the input text is
|
|
55
|
+
# the path to a file.
|
|
56
|
+
#
|
|
57
|
+
# :do_not_spell_check:: The text should not be spell-checked.
|
|
58
|
+
#
|
|
59
|
+
# :do_not_scroll:: The text field should not scroll (horizontally for single-line fields and
|
|
60
|
+
# vertically for multiline fields) to accomodate more text than fits into the
|
|
61
|
+
# annotation rectangle. This means that no more text can be entered once the
|
|
62
|
+
# field is full.
|
|
63
|
+
#
|
|
64
|
+
# :comb:: The field is divided into /MaxLen equally spaced positions (so /MaxLen needs to be
|
|
65
|
+
# set). This is useful, for example, when entering things like social security
|
|
66
|
+
# numbers which always have the same length.
|
|
67
|
+
#
|
|
68
|
+
# :rich_text:: The field is a rich text field.
|
|
69
|
+
#
|
|
70
|
+
# See: PDF1.7 s12.7.4.3
|
|
71
|
+
class TextField < VariableTextField
|
|
72
|
+
|
|
73
|
+
define_field :MaxLen, type: Integer
|
|
74
|
+
|
|
75
|
+
# All inheritable dictionary fields for text fields.
|
|
76
|
+
INHERITABLE_FIELDS = (superclass::INHERITABLE_FIELDS + [:MaxLen]).freeze
|
|
77
|
+
|
|
78
|
+
# Updated list of field flags.
|
|
79
|
+
FLAGS_BIT_MAPPING = superclass::FLAGS_BIT_MAPPING.merge(
|
|
80
|
+
{
|
|
81
|
+
multiline: 12,
|
|
82
|
+
password: 13,
|
|
83
|
+
file_select: 20,
|
|
84
|
+
do_not_spell_check: 22,
|
|
85
|
+
do_not_scroll: 23,
|
|
86
|
+
comb: 24,
|
|
87
|
+
rich_text: 25,
|
|
88
|
+
}
|
|
89
|
+
).freeze
|
|
90
|
+
|
|
91
|
+
# Returns the field value, i.e. the text contents of the field, or +nil+ if no value is set.
|
|
92
|
+
#
|
|
93
|
+
# Note that modifying the returned value *might not* modify the text contents in case it is
|
|
94
|
+
# stored as stream! So always use #field_value= to set the field value.
|
|
95
|
+
def field_value
|
|
96
|
+
return unless value[:V]
|
|
97
|
+
self[:V].kind_of?(String) ? self[:V] : self[:V].stream
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Sets the field value, i.e. the text contents of the field, to the given string.
|
|
101
|
+
#
|
|
102
|
+
# Note that for single line text fields, all whitespace characters are changed to simple
|
|
103
|
+
# spaces.
|
|
104
|
+
def field_value=(str)
|
|
105
|
+
if flagged?(:password)
|
|
106
|
+
raise HexaPDF::Error, "Storing a field value for a password field is not allowed"
|
|
107
|
+
end
|
|
108
|
+
str = str.gsub(/[[:space:]]/, ' ') if concrete_field_type == :single_line_text_field
|
|
109
|
+
self[:V] = str
|
|
110
|
+
update_widgets
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Returns the default field value.
|
|
114
|
+
#
|
|
115
|
+
# See: #field_value
|
|
116
|
+
def default_field_value
|
|
117
|
+
self[:DV].kind_of?(String) ? self[:DV] : self[:DV].stream
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Sets the default field value.
|
|
121
|
+
#
|
|
122
|
+
# See: #field_value=
|
|
123
|
+
def default_field_value=(str)
|
|
124
|
+
self[:DV] = str
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Returns the concrete text field type, either :single_line_text_field,
|
|
128
|
+
# :multiline_text_field, :password_field, :file_select_field, :comb_text_field or
|
|
129
|
+
# :rich_text_field.
|
|
130
|
+
def concrete_field_type
|
|
131
|
+
if flagged?(:multiline)
|
|
132
|
+
:multiline_text_field
|
|
133
|
+
elsif flagged?(:password)
|
|
134
|
+
:password_field
|
|
135
|
+
elsif flagged?(:file_select)
|
|
136
|
+
:file_select_field
|
|
137
|
+
elsif flagged?(:comb)
|
|
138
|
+
:comb_text_field
|
|
139
|
+
elsif flagged?(:rich_text)
|
|
140
|
+
:rich_text_field
|
|
141
|
+
else
|
|
142
|
+
:single_line_text_field
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Creates appropriate appearances for all widgets.
|
|
147
|
+
#
|
|
148
|
+
# For information on how this is done see AppearanceGenerator.
|
|
149
|
+
#
|
|
150
|
+
# Note that an appearance for a text field widget is *always* created even if there is an
|
|
151
|
+
# existing one to make sure the current field value is properly represented.
|
|
152
|
+
def create_appearances
|
|
153
|
+
appearance_generator_class = document.config.constantize('acro_form.appearance_generator')
|
|
154
|
+
each_widget do |widget|
|
|
155
|
+
appearance_generator_class.new(widget).create_text_appearances
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Updates the widgets so that they reflect the current field value.
|
|
160
|
+
def update_widgets
|
|
161
|
+
create_appearances
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
private
|
|
165
|
+
|
|
166
|
+
def perform_validation #:nodoc:
|
|
167
|
+
if field_type != :Tx
|
|
168
|
+
yield("Field /FT of AcroForm text field has to be :Tx", true)
|
|
169
|
+
self[:FT] = :Tx
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
super
|
|
173
|
+
|
|
174
|
+
if self[:V] && !(self[:V].kind_of?(String) || self[:V].kind_of?(HexaPDF::Stream))
|
|
175
|
+
yield("Text field doesn't contain text but #{self[:V].class} object")
|
|
176
|
+
end
|
|
177
|
+
if (max_len = self[:MaxLen]) && field_value.length > max_len
|
|
178
|
+
yield("Text contents of field '#{full_field_name}' is too long")
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
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/dictionary'
|
|
38
|
+
require 'hexapdf/stream'
|
|
39
|
+
require 'hexapdf/error'
|
|
40
|
+
require 'hexapdf/content/parser'
|
|
41
|
+
|
|
42
|
+
module HexaPDF
|
|
43
|
+
module Type
|
|
44
|
+
module AcroForm
|
|
45
|
+
|
|
46
|
+
# An AcroForm variable text field defines how text that it is not known at generation time
|
|
47
|
+
# should be rendered. For example, AcroForm text fields (normally) don't have an initial
|
|
48
|
+
# value; the value is entered by the user and needs to be rendered correctly by the PDF
|
|
49
|
+
# reader.
|
|
50
|
+
#
|
|
51
|
+
# See: PDF1.7 s12.7.3.3
|
|
52
|
+
class VariableTextField < Field
|
|
53
|
+
|
|
54
|
+
define_field :DA, type: String
|
|
55
|
+
define_field :Q, type: Integer, default: 0, allowed_values: [0, 1, 2]
|
|
56
|
+
define_field :DS, type: String, version: '1.5'
|
|
57
|
+
define_field :RV, type: [String, Stream], version: '1.5'
|
|
58
|
+
|
|
59
|
+
# All inheritable dictionary fields for text fields.
|
|
60
|
+
INHERITABLE_FIELDS = (superclass::INHERITABLE_FIELDS + [:DA, :Q]).freeze
|
|
61
|
+
|
|
62
|
+
UNSET_ARG = ::Object.new # :nodoc:
|
|
63
|
+
|
|
64
|
+
# :call-seq:
|
|
65
|
+
# field.text_alignment -> alignment
|
|
66
|
+
# field.text_alignment(alignment) -> field
|
|
67
|
+
#
|
|
68
|
+
# Sets or returns the text alignment that should be used when displaying text.
|
|
69
|
+
#
|
|
70
|
+
# With no argument, the current text alignment is returned. When a value is provided, the
|
|
71
|
+
# text alignment is set accordingly.
|
|
72
|
+
#
|
|
73
|
+
# The alignment value is one of :left, :center or :right.
|
|
74
|
+
def text_alignment(alignment = UNSET_ARG)
|
|
75
|
+
if alignment == UNSET_ARG
|
|
76
|
+
case self[:Q]
|
|
77
|
+
when 0 then :left
|
|
78
|
+
when 1 then :center
|
|
79
|
+
when 2 then :right
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
self[:Q] = case alignment
|
|
83
|
+
when :left then 0
|
|
84
|
+
when :center then 1
|
|
85
|
+
when :right then 2
|
|
86
|
+
else
|
|
87
|
+
raise ArgumentError, "Invalid variable text field alignment #{alignment}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Sets the default appearance string using the provided values.
|
|
93
|
+
#
|
|
94
|
+
# The default argument values are a sane default. If +font_size+ is set to 0, the font size
|
|
95
|
+
# is calculated using the height/width of the field.
|
|
96
|
+
def set_default_appearance_string(font: 'Helvetica', font_size: 0)
|
|
97
|
+
name = document.acro_form(create: true).default_resources.
|
|
98
|
+
add_font(document.fonts.add(font).pdf_object)
|
|
99
|
+
self[:DA] = "0 g /#{name} #{font_size} Tf"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Parses the default appearance string and returns an array containing [font_name,
|
|
103
|
+
# font_size].
|
|
104
|
+
#
|
|
105
|
+
# The default appearance string is taken from the field or, if not set, the default
|
|
106
|
+
# appearance string of the form.
|
|
107
|
+
def parse_default_appearance_string
|
|
108
|
+
da = self[:DA] || (document.acro_form && document.acro_form[:DA])
|
|
109
|
+
raise HexaPDF::Error, "No default appearance string set" unless da
|
|
110
|
+
|
|
111
|
+
font_params = nil
|
|
112
|
+
HexaPDF::Content::Parser.parse(da) do |obj, params|
|
|
113
|
+
font_params = params.dup if obj == :Tf
|
|
114
|
+
end
|
|
115
|
+
font_params
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
data/lib/hexapdf/type/action.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/type/actions.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
|
|
@@ -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
|
|
@@ -46,6 +46,54 @@ module HexaPDF
|
|
|
46
46
|
# See: PDF1.7 s12.5
|
|
47
47
|
class Annotation < Dictionary
|
|
48
48
|
|
|
49
|
+
# The appearance dictionary references appearance streams for various use cases.
|
|
50
|
+
#
|
|
51
|
+
# Each appearance can either be an XObject or a dictionary mapping names to XObjects. The
|
|
52
|
+
# latter is used when the appearance depends on the state of the annotation, e.g. a check box
|
|
53
|
+
# widget that can be checked or unchecked.
|
|
54
|
+
#
|
|
55
|
+
# See: PDF1.7 s12.5.5
|
|
56
|
+
class AppearanceDictionary < Dictionary
|
|
57
|
+
|
|
58
|
+
define_type :XXAppearanceDictionary
|
|
59
|
+
|
|
60
|
+
define_field :N, type: [Dictionary, Stream], required: true
|
|
61
|
+
define_field :R, type: [Dictionary, Stream]
|
|
62
|
+
define_field :D, type: [Dictionary, Stream]
|
|
63
|
+
|
|
64
|
+
# The annotation's normal appearance.
|
|
65
|
+
def normal_appearance
|
|
66
|
+
self[:N]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# The rollover appearance which should be used when the cursor is moved into the active area
|
|
70
|
+
# of the annotation without pressing a button.
|
|
71
|
+
def rollover_appearance
|
|
72
|
+
self[:R] || self[:N]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# The down appearance which should be used when the mouse button is pressed or held down
|
|
76
|
+
# inside the active area of the annotation.
|
|
77
|
+
def down_appearance
|
|
78
|
+
self[:D] || self[:N]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Border style dictionary used by various annotation types.
|
|
84
|
+
#
|
|
85
|
+
# See: PDF1.7 s12.5.4
|
|
86
|
+
class Border < Dictionary
|
|
87
|
+
|
|
88
|
+
define_type :Border
|
|
89
|
+
|
|
90
|
+
define_field :Type, type: Symbol, default: type
|
|
91
|
+
define_field :W, type: [Integer, Float], default: 1
|
|
92
|
+
define_field :S, type: Symbol, default: :S, allowed_values: [:S, :D, :B, :I, :U]
|
|
93
|
+
define_field :D, type: PDFArray, default: [3]
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
49
97
|
extend Utils::BitField
|
|
50
98
|
|
|
51
99
|
define_type :Annot
|
|
@@ -58,7 +106,7 @@ module HexaPDF
|
|
|
58
106
|
define_field :NM, type: String, version: '1.4'
|
|
59
107
|
define_field :M, type: PDFDate, version: '1.1'
|
|
60
108
|
define_field :F, type: Integer, default: 0, version: '1.1'
|
|
61
|
-
define_field :AP, type:
|
|
109
|
+
define_field :AP, type: :XXAppearanceDictionary, version: '1.2'
|
|
62
110
|
define_field :AS, type: Symbol, version: '1.2'
|
|
63
111
|
define_field :Border, type: PDFArray, default: [0, 0, 1]
|
|
64
112
|
define_field :C, type: PDFArray, version: '1.1'
|
|
@@ -68,7 +116,29 @@ module HexaPDF
|
|
|
68
116
|
bit_field(:raw_flags, {invisible: 0, hidden: 1, print: 2, no_zoom: 3, no_rotate: 4,
|
|
69
117
|
no_view: 5, read_only: 6, locked: 7, toggle_no_view: 8,
|
|
70
118
|
locked_contents: 9},
|
|
71
|
-
lister: "flags", getter: "flagged?", setter: "flag")
|
|
119
|
+
lister: "flags", getter: "flagged?", setter: "flag", unsetter: "unflag")
|
|
120
|
+
|
|
121
|
+
# Returns +true+ because annotation objects must always be indirect objects.
|
|
122
|
+
def must_be_indirect?
|
|
123
|
+
true
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Returns the AppearanceDictionary instance associated with the annotation or +nil+ if none is
|
|
127
|
+
# set.
|
|
128
|
+
def appearance
|
|
129
|
+
self[:AP]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Returns +true+ if the widget's normal appearance exists.
|
|
133
|
+
#
|
|
134
|
+
# Note that this checks only if the appearance exists but not if the structure of the
|
|
135
|
+
# appearance dictionary conforms to the expectations of the annotation.
|
|
136
|
+
def appearance?
|
|
137
|
+
return false unless (normal_appearance = appearance&.normal_appearance)
|
|
138
|
+
normal_appearance.kind_of?(HexaPDF::Stream) ||
|
|
139
|
+
(!normal_appearance.empty? &&
|
|
140
|
+
normal_appearance.each.all? {|_k, v| v.kind_of?(HexaPDF::Stream) })
|
|
141
|
+
end
|
|
72
142
|
|
|
73
143
|
private
|
|
74
144
|
|