hexapdf 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +126 -0
- data/examples/019-acro_form.rb +41 -4
- data/lib/hexapdf/cli/command.rb +4 -2
- data/lib/hexapdf/cli/image2pdf.rb +2 -1
- data/lib/hexapdf/cli/info.rb +51 -2
- data/lib/hexapdf/cli/inspect.rb +30 -8
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/split.rb +74 -14
- data/lib/hexapdf/configuration.rb +15 -0
- data/lib/hexapdf/content/graphic_object/arc.rb +3 -3
- data/lib/hexapdf/content/parser.rb +1 -1
- data/lib/hexapdf/dictionary.rb +4 -4
- data/lib/hexapdf/dictionary_fields.rb +1 -9
- data/lib/hexapdf/document.rb +41 -16
- data/lib/hexapdf/document/files.rb +0 -1
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +1 -0
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -0
- data/lib/hexapdf/font/cmap.rb +1 -4
- data/lib/hexapdf/font/encoding/base.rb +8 -0
- data/lib/hexapdf/font/encoding/difference_encoding.rb +6 -0
- data/lib/hexapdf/font/true_type/table/head.rb +1 -0
- data/lib/hexapdf/font/true_type/table/os2.rb +2 -0
- data/lib/hexapdf/font/type1_wrapper.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +3 -2
- data/lib/hexapdf/layout/line.rb +1 -1
- data/lib/hexapdf/layout/style.rb +23 -23
- data/lib/hexapdf/layout/text_layouter.rb +2 -2
- data/lib/hexapdf/layout/text_shaper.rb +3 -2
- data/lib/hexapdf/object.rb +52 -25
- data/lib/hexapdf/parser.rb +87 -3
- data/lib/hexapdf/pdf_array.rb +11 -4
- data/lib/hexapdf/revisions.rb +29 -21
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +6 -4
- data/lib/hexapdf/tokenizer.rb +4 -3
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +132 -28
- data/lib/hexapdf/type/acro_form/button_field.rb +21 -13
- data/lib/hexapdf/type/acro_form/choice_field.rb +68 -14
- data/lib/hexapdf/type/acro_form/field.rb +35 -5
- data/lib/hexapdf/type/acro_form/form.rb +139 -14
- data/lib/hexapdf/type/acro_form/text_field.rb +70 -4
- data/lib/hexapdf/type/actions/uri.rb +3 -2
- data/lib/hexapdf/type/annotations/widget.rb +3 -4
- data/lib/hexapdf/type/catalog.rb +2 -2
- data/lib/hexapdf/type/cid_font.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +1 -1
- data/lib/hexapdf/type/font.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +4 -2
- data/lib/hexapdf/type/font_true_type.rb +6 -2
- data/lib/hexapdf/type/font_type0.rb +4 -4
- data/lib/hexapdf/type/form.rb +15 -2
- data/lib/hexapdf/type/image.rb +2 -2
- data/lib/hexapdf/type/page.rb +37 -13
- data/lib/hexapdf/type/page_tree_node.rb +29 -5
- data/lib/hexapdf/type/resources.rb +1 -0
- data/lib/hexapdf/type/trailer.rb +2 -3
- data/lib/hexapdf/utils/object_hash.rb +0 -1
- data/lib/hexapdf/utils/sorted_tree_node.rb +18 -15
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/common_tokenizer_tests.rb +6 -1
- data/test/hexapdf/content/graphic_object/test_arc.rb +4 -4
- data/test/hexapdf/content/test_canvas.rb +3 -3
- data/test/hexapdf/content/test_color_space.rb +1 -1
- data/test/hexapdf/encryption/test_aes.rb +4 -4
- data/test/hexapdf/encryption/test_standard_security_handler.rb +11 -11
- data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
- data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
- data/test/hexapdf/font/encoding/test_base.rb +10 -0
- data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
- data/test/hexapdf/font/test_type1_wrapper.rb +4 -3
- data/test/hexapdf/layout/test_style.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +12 -5
- data/test/hexapdf/test_configuration.rb +2 -2
- data/test/hexapdf/test_dictionary.rb +3 -1
- data/test/hexapdf/test_dictionary_fields.rb +2 -2
- data/test/hexapdf/test_document.rb +18 -10
- data/test/hexapdf/test_object.rb +71 -26
- data/test/hexapdf/test_parser.rb +159 -53
- data/test/hexapdf/test_pdf_array.rb +8 -1
- data/test/hexapdf/test_revisions.rb +35 -0
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +296 -38
- data/test/hexapdf/type/acro_form/test_button_field.rb +22 -2
- data/test/hexapdf/type/acro_form/test_choice_field.rb +92 -9
- data/test/hexapdf/type/acro_form/test_field.rb +39 -0
- data/test/hexapdf/type/acro_form/test_form.rb +87 -15
- data/test/hexapdf/type/acro_form/test_text_field.rb +77 -1
- data/test/hexapdf/type/test_font_simple.rb +2 -1
- data/test/hexapdf/type/test_font_true_type.rb +6 -0
- data/test/hexapdf/type/test_form.rb +26 -1
- data/test/hexapdf/type/test_page.rb +45 -7
- data/test/hexapdf/type/test_page_tree_node.rb +42 -0
- data/test/hexapdf/utils/test_bit_field.rb +2 -0
- data/test/hexapdf/utils/test_object_hash.rb +5 -0
- data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -9
- data/test/test_helper.rb +2 -0
- metadata +6 -11
|
@@ -140,7 +140,7 @@ describe HexaPDF::Type::AcroForm::ButtonField do
|
|
|
140
140
|
it "sets a correct field value" do
|
|
141
141
|
@field.create_widget(@doc.pages.add, value: :button1)
|
|
142
142
|
|
|
143
|
-
@field.field_value =
|
|
143
|
+
@field.field_value = "button1"
|
|
144
144
|
assert_equal(:button1, @field[:V])
|
|
145
145
|
@field.field_value = nil
|
|
146
146
|
assert_equal(:Off, @field[:V])
|
|
@@ -158,7 +158,7 @@ describe HexaPDF::Type::AcroForm::ButtonField do
|
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
it "returns an array of possible values" do
|
|
161
|
-
@field.create_widget(@doc.pages.add, value:
|
|
161
|
+
@field.create_widget(@doc.pages.add, value: "Test")
|
|
162
162
|
@field.create_widget(@doc.pages.add, value: :x)
|
|
163
163
|
@field.create_widget(@doc.pages.add, value: :y)
|
|
164
164
|
assert_equal([:Test, :x, :y], @field.radio_button_values)
|
|
@@ -172,6 +172,7 @@ describe HexaPDF::Type::AcroForm::ButtonField do
|
|
|
172
172
|
assert_equal(:solid, border_style.style)
|
|
173
173
|
assert_equal([1], widget.background_color.components)
|
|
174
174
|
assert_equal(:circle, widget.marker_style.style)
|
|
175
|
+
assert_equal({test: nil, Off: nil}, widget[:AP][:N].value)
|
|
175
176
|
end
|
|
176
177
|
|
|
177
178
|
it "always creates standalone widgets" do
|
|
@@ -181,6 +182,10 @@ describe HexaPDF::Type::AcroForm::ButtonField do
|
|
|
181
182
|
it "fails if the value argument is not provided for create_widget" do
|
|
182
183
|
assert_raises(ArgumentError) { @field.create_widget(@doc.pages.add) }
|
|
183
184
|
end
|
|
185
|
+
|
|
186
|
+
it "fails if the value argument for create_widget doesn't respond to to_sym" do
|
|
187
|
+
assert_raises(ArgumentError) { @field.create_widget(@doc.pages.add, value: 5) }
|
|
188
|
+
end
|
|
184
189
|
end
|
|
185
190
|
|
|
186
191
|
it "returns a default field value" do
|
|
@@ -228,6 +233,14 @@ describe HexaPDF::Type::AcroForm::ButtonField do
|
|
|
228
233
|
refute_same(off, widget.appearance.normal_appearance[:Off])
|
|
229
234
|
end
|
|
230
235
|
|
|
236
|
+
it "always generates appearances if force is true" do
|
|
237
|
+
widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
238
|
+
@field.create_appearances
|
|
239
|
+
yes = widget.appearance.normal_appearance[:Yes]
|
|
240
|
+
@field.create_appearances(force: true)
|
|
241
|
+
refute_same(yes, widget.appearance.normal_appearance[:Yes])
|
|
242
|
+
end
|
|
243
|
+
|
|
231
244
|
it "fails for unsupported button types" do
|
|
232
245
|
@field.flag(:push_button)
|
|
233
246
|
@field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
@@ -258,6 +271,13 @@ describe HexaPDF::Type::AcroForm::ButtonField do
|
|
|
258
271
|
@field.update_widgets
|
|
259
272
|
assert_equal(:Yes, widget[:AS])
|
|
260
273
|
end
|
|
274
|
+
|
|
275
|
+
it "creates the appearances if necessary" do
|
|
276
|
+
widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
277
|
+
assert_nil(widget[:AP][:N][:Yes])
|
|
278
|
+
@field.update_widgets
|
|
279
|
+
assert(widget[:AP][:N][:Yes])
|
|
280
|
+
end
|
|
261
281
|
end
|
|
262
282
|
|
|
263
283
|
describe "validation" do
|
|
@@ -36,23 +36,34 @@ describe HexaPDF::Type::AcroForm::ChoiceField do
|
|
|
36
36
|
|
|
37
37
|
describe "field_value=" do
|
|
38
38
|
before do
|
|
39
|
-
@field.option_items = ["test", "other"]
|
|
39
|
+
@field.option_items = ["test", "something", "other", "neu"]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "updates the widgets to reflect the changed value" do
|
|
43
|
+
@field.initialize_as_combo_box
|
|
44
|
+
widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
45
|
+
@field.set_default_appearance_string
|
|
46
|
+
@field.field_value = 'test'
|
|
47
|
+
assert(widget[:AP][:N])
|
|
40
48
|
end
|
|
41
49
|
|
|
42
50
|
describe "combo_box" do
|
|
43
51
|
before do
|
|
44
52
|
@field.initialize_as_combo_box
|
|
53
|
+
@field[:I] = 2
|
|
45
54
|
end
|
|
46
55
|
|
|
47
56
|
it "can set the value for an uneditable combo box" do
|
|
48
57
|
@field.field_value = 'test'
|
|
49
58
|
assert_equal("test", @field[:V])
|
|
59
|
+
assert_nil(@field[:I])
|
|
50
60
|
end
|
|
51
61
|
|
|
52
62
|
it "can set the value for an editable combo box" do
|
|
53
63
|
@field.flag(:edit)
|
|
54
64
|
@field.field_value = 'another'
|
|
55
65
|
assert_equal("another", @field[:V])
|
|
66
|
+
assert_nil(@field[:I])
|
|
56
67
|
end
|
|
57
68
|
|
|
58
69
|
it "fails if mulitple values are provided for a combo box" do
|
|
@@ -76,8 +87,18 @@ describe HexaPDF::Type::AcroForm::ChoiceField do
|
|
|
76
87
|
|
|
77
88
|
it "can set a multiple values if the list box is a multi-select" do
|
|
78
89
|
@field.flag(:multi_select)
|
|
79
|
-
@field.field_value = ['
|
|
80
|
-
assert_equal(['
|
|
90
|
+
@field.field_value = ['other', 'test']
|
|
91
|
+
assert_equal(['other', 'test'], @field[:V].value)
|
|
92
|
+
assert_equal([0, 2], @field[:I].value)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "can read and set the top index" do
|
|
96
|
+
assert_raises(ArgumentError) { @field.list_box_top_index = 4 }
|
|
97
|
+
@field.delete(:Opt)
|
|
98
|
+
assert_raises(ArgumentError) { @field.list_box_top_index = 0 }
|
|
99
|
+
@field.option_items = [1, 2, 3, 4]
|
|
100
|
+
@field.list_box_top_index = 2
|
|
101
|
+
assert_equal(2, @field.list_box_top_index)
|
|
81
102
|
end
|
|
82
103
|
|
|
83
104
|
it "fails if mulitple values are provided but the list box is not a multi-select" do
|
|
@@ -97,10 +118,29 @@ describe HexaPDF::Type::AcroForm::ChoiceField do
|
|
|
97
118
|
assert_raises(HexaPDF::Error) { @field.default_field_value = 'unknown' }
|
|
98
119
|
end
|
|
99
120
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
121
|
+
describe "option items" do
|
|
122
|
+
before do
|
|
123
|
+
@items = [["a", "Zx"], "\xFE\xFF".b << "Töne".encode('UTF-16BE').b, "H\xe4llo".b,]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "sets the option items" do
|
|
127
|
+
@field.option_items = @items
|
|
128
|
+
assert_equal(@items, @field[:Opt].value)
|
|
129
|
+
|
|
130
|
+
@field.flag(:sort)
|
|
131
|
+
@field.option_items = @items
|
|
132
|
+
assert_equal(@items.values_at(2, 1, 0), @field[:Opt].value)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "can retrieve the option items" do
|
|
136
|
+
@field[:Opt] = @items
|
|
137
|
+
assert_equal(["Zx", "Töne", "Hällo"], @field.option_items)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "can retrieve the export values" do
|
|
141
|
+
@field[:Opt] = @items
|
|
142
|
+
assert_equal(["a", "Töne", "Hällo"], @field.export_values)
|
|
143
|
+
end
|
|
104
144
|
end
|
|
105
145
|
|
|
106
146
|
it "returns the correct concrete field type" do
|
|
@@ -121,8 +161,51 @@ describe HexaPDF::Type::AcroForm::ChoiceField do
|
|
|
121
161
|
assert(@field[:AP][:N])
|
|
122
162
|
end
|
|
123
163
|
|
|
124
|
-
it "
|
|
125
|
-
|
|
164
|
+
it "works for list box fields" do
|
|
165
|
+
@field.initialize_as_list_box
|
|
166
|
+
@field.set_default_appearance_string
|
|
167
|
+
@field.create_appearances
|
|
168
|
+
assert(@field[:AP][:N])
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "only creates a new appearance if the involved dictionary values have changed per widget" do
|
|
172
|
+
@field.initialize_as_list_box
|
|
173
|
+
@field.set_default_appearance_string
|
|
174
|
+
@field.create_appearances
|
|
175
|
+
appearance_stream = @field[:AP][:N].raw_stream
|
|
176
|
+
|
|
177
|
+
@field.create_appearances
|
|
178
|
+
assert_same(appearance_stream, @field[:AP][:N].raw_stream)
|
|
179
|
+
|
|
180
|
+
do_check = lambda do
|
|
181
|
+
@field.create_appearances
|
|
182
|
+
refute_same(appearance_stream, @field[:AP][:N].raw_stream)
|
|
183
|
+
appearance_stream = @field[:AP][:N].raw_stream
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
@field.option_items = ['a', 'b', 'c']
|
|
187
|
+
do_check.call
|
|
188
|
+
|
|
189
|
+
@field.list_box_top_index = 2
|
|
190
|
+
do_check.call
|
|
191
|
+
|
|
192
|
+
@field.field_value = 'b'
|
|
193
|
+
do_check.call
|
|
194
|
+
|
|
195
|
+
widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
196
|
+
assert_nil(widget[:AP])
|
|
197
|
+
@field.create_appearances
|
|
198
|
+
refute_nil(widget[:AP][:N])
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "force the creation of appearance streams when force: true" do
|
|
202
|
+
@field.initialize_as_list_box
|
|
203
|
+
@field.set_default_appearance_string
|
|
204
|
+
@field.create_appearances
|
|
205
|
+
appearance_stream = @field[:AP][:N].raw_stream
|
|
206
|
+
|
|
207
|
+
@field.create_appearances(force: true)
|
|
208
|
+
refute_same(appearance_stream, @field[:AP][:N].raw_stream)
|
|
126
209
|
end
|
|
127
210
|
end
|
|
128
211
|
|
|
@@ -99,6 +99,12 @@ describe HexaPDF::Type::AcroForm::Field do
|
|
|
99
99
|
refute(@field.terminal_field?)
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
+
it "can check whether a widget is embedded in the field" do
|
|
103
|
+
refute(@field.embedded_widget?)
|
|
104
|
+
@field[:Subtype] = :Wdiget
|
|
105
|
+
assert(@field.embedded_widget?)
|
|
106
|
+
end
|
|
107
|
+
|
|
102
108
|
describe "each_widget" do
|
|
103
109
|
it "yields a wrapped instance of self if a single widget is embedded" do
|
|
104
110
|
@field[:Subtype] = :Widget
|
|
@@ -175,6 +181,39 @@ describe HexaPDF::Type::AcroForm::Field do
|
|
|
175
181
|
end
|
|
176
182
|
end
|
|
177
183
|
|
|
184
|
+
describe "delete_widget" do
|
|
185
|
+
before do
|
|
186
|
+
@page = @doc.pages.add
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "does nothing if the provided widget doesn't belong to the field" do
|
|
190
|
+
wrong_widget = @doc.add({Subtype: :Widget})
|
|
191
|
+
|
|
192
|
+
@field.create_widget(@page)
|
|
193
|
+
@field.delete_widget(wrong_widget)
|
|
194
|
+
assert_equal(:Widget, @field[:Subtype])
|
|
195
|
+
|
|
196
|
+
@field.create_widget(@page)
|
|
197
|
+
@field.delete_widget(wrong_widget)
|
|
198
|
+
assert_equal(2, @field[:Kids].size)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "deletes the widget if it is embedded" do
|
|
202
|
+
widget = @field.create_widget(@page)
|
|
203
|
+
@field.delete_widget(widget)
|
|
204
|
+
refute(@field.key?(:Subtype))
|
|
205
|
+
assert(@page[:Annots].empty?)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "deletes the widget if it is not embedded" do
|
|
209
|
+
@field.create_widget(@page)
|
|
210
|
+
widget2 = @field.create_widget(@page)
|
|
211
|
+
@field.delete_widget(widget2)
|
|
212
|
+
assert_equal(1, @field[:Kids].size)
|
|
213
|
+
assert_equal(@field[:Kids].value, @page[:Annots].value)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
178
217
|
describe "perform_validation" do
|
|
179
218
|
before do
|
|
180
219
|
@field[:FT] = :Tx
|
|
@@ -7,7 +7,7 @@ require 'hexapdf/type/acro_form/form'
|
|
|
7
7
|
describe HexaPDF::Type::AcroForm::Form do
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
|
-
@acro_form = @doc.add({}, type: :XXAcroForm)
|
|
10
|
+
@acro_form = @doc.add({Fields: []}, type: :XXAcroForm)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
describe "signature flags" do
|
|
@@ -49,7 +49,7 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
|
49
49
|
root_fields = @acro_form.find_root_fields
|
|
50
50
|
assert_equal(result, root_fields.map(&:value))
|
|
51
51
|
assert_kind_of(HexaPDF::Type::AcroForm::TextField, root_fields[0])
|
|
52
|
-
|
|
52
|
+
assert_equal([], @acro_form[:Fields].value)
|
|
53
53
|
|
|
54
54
|
@acro_form.find_root_fields!
|
|
55
55
|
assert_equal(result, @acro_form[:Fields].value.map(&:value))
|
|
@@ -115,6 +115,10 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
describe "create fields" do
|
|
118
|
+
before do
|
|
119
|
+
@acro_form = @doc.acro_form(create: true)
|
|
120
|
+
end
|
|
121
|
+
|
|
118
122
|
describe "handles the general case" do
|
|
119
123
|
it "works for names with a dot" do
|
|
120
124
|
@acro_form[:Fields] = [{T: "root"}]
|
|
@@ -134,9 +138,57 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
|
134
138
|
end
|
|
135
139
|
end
|
|
136
140
|
|
|
141
|
+
def applies_variable_text_properties(method, **args)
|
|
142
|
+
field = @acro_form.send(method, "field", **args, font: 'Times')
|
|
143
|
+
font_name, font_size = field.parse_default_appearance_string
|
|
144
|
+
assert_equal(:'Times-Roman', @acro_form.default_resources.font(font_name)[:BaseFont])
|
|
145
|
+
assert_equal(0, font_size)
|
|
146
|
+
|
|
147
|
+
field = @acro_form.send(method, "field", **args, font_size: 10)
|
|
148
|
+
font_name, font_size = field.parse_default_appearance_string
|
|
149
|
+
assert_equal(:Helvetica, @acro_form.default_resources.font(font_name)[:BaseFont])
|
|
150
|
+
assert_equal(10, font_size)
|
|
151
|
+
|
|
152
|
+
field = @acro_form.send(method, "field", **args, font: 'Courier', font_size: 10, align: :center)
|
|
153
|
+
font_name, font_size = field.parse_default_appearance_string
|
|
154
|
+
assert_equal(:Courier, @acro_form.default_resources.font(font_name)[:BaseFont])
|
|
155
|
+
assert_equal(10, font_size)
|
|
156
|
+
assert_equal(:center, field.text_alignment)
|
|
157
|
+
end
|
|
158
|
+
|
|
137
159
|
it "creates a text field" do
|
|
138
160
|
field = @acro_form.create_text_field("field")
|
|
139
161
|
assert_equal(:Tx, field.field_type)
|
|
162
|
+
applies_variable_text_properties(:create_text_field)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "creates a multiline text field" do
|
|
166
|
+
field = @acro_form.create_multiline_text_field("field")
|
|
167
|
+
assert_equal(:Tx, field.field_type)
|
|
168
|
+
assert(field.multiline_text_field?)
|
|
169
|
+
applies_variable_text_properties(:create_multiline_text_field)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "creates a comb text field" do
|
|
173
|
+
field = @acro_form.create_comb_text_field("field", max_chars: 9)
|
|
174
|
+
assert_equal(:Tx, field.field_type)
|
|
175
|
+
assert_equal(9, field[:MaxLen])
|
|
176
|
+
assert(field.comb_text_field?)
|
|
177
|
+
applies_variable_text_properties(:create_comb_text_field, max_chars: 9)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "creates a password field" do
|
|
181
|
+
field = @acro_form.create_password_field("field")
|
|
182
|
+
assert_equal(:Tx, field.field_type)
|
|
183
|
+
assert(field.password_field?)
|
|
184
|
+
applies_variable_text_properties(:create_password_field)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "creates a file select field" do
|
|
188
|
+
field = @acro_form.create_file_select_field("field")
|
|
189
|
+
assert_equal(:Tx, field.field_type)
|
|
190
|
+
assert(field.file_select_field?)
|
|
191
|
+
applies_variable_text_properties(:create_file_select_field)
|
|
140
192
|
end
|
|
141
193
|
|
|
142
194
|
it "creates a check box" do
|
|
@@ -150,13 +202,19 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
|
150
202
|
end
|
|
151
203
|
|
|
152
204
|
it "creates a combo box" do
|
|
153
|
-
field = @acro_form.create_combo_box("field")
|
|
205
|
+
field = @acro_form.create_combo_box("field", option_items: ['a', 'b', 'c'], editable: true)
|
|
154
206
|
assert(field.combo_box?)
|
|
207
|
+
assert_equal(['a', 'b', 'c'], field.option_items)
|
|
208
|
+
assert(field.flagged?(:edit))
|
|
209
|
+
applies_variable_text_properties(:create_combo_box)
|
|
155
210
|
end
|
|
156
211
|
|
|
157
212
|
it "creates a list box" do
|
|
158
|
-
field = @acro_form.create_list_box("field")
|
|
213
|
+
field = @acro_form.create_list_box("field", option_items: ['a', 'b', 'c'], multi_select: true)
|
|
159
214
|
assert(field.list_box?)
|
|
215
|
+
assert_equal(['a', 'b', 'c'], field.option_items)
|
|
216
|
+
assert(field.flagged?(:multi_select))
|
|
217
|
+
applies_variable_text_properties(:create_list_box)
|
|
160
218
|
end
|
|
161
219
|
end
|
|
162
220
|
|
|
@@ -185,15 +243,29 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
|
185
243
|
assert(@acro_form[:NeedAppearances])
|
|
186
244
|
end
|
|
187
245
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
246
|
+
describe "create_appearances" do
|
|
247
|
+
before do
|
|
248
|
+
@tf = @acro_form.create_text_field('test')
|
|
249
|
+
@tf.set_default_appearance_string
|
|
250
|
+
@tf.create_widget(@doc.pages.add)
|
|
251
|
+
@cb = @acro_form.create_check_box('test2')
|
|
252
|
+
@cb.create_widget(@doc.pages.add)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it "creates the appearances of all field widgets if necessary" do
|
|
256
|
+
@acro_form.create_appearances
|
|
257
|
+
assert(@tf.each_widget.all? {|w| w.appearance.normal_appearance.kind_of?(HexaPDF::Stream) })
|
|
258
|
+
assert(@cb.each_widget.all? {|w| w.appearance.normal_appearance[:Yes].kind_of?(HexaPDF::Stream) })
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "force the creation of appearances if force is true" do
|
|
262
|
+
@acro_form.create_appearances
|
|
263
|
+
text_stream = @tf[:AP][:N].raw_stream
|
|
264
|
+
@acro_form.create_appearances
|
|
265
|
+
assert_same(text_stream, @tf[:AP][:N].raw_stream)
|
|
266
|
+
@acro_form.create_appearances(force: true)
|
|
267
|
+
refute_same(text_stream, @tf[:AP][:N].raw_stream)
|
|
268
|
+
end
|
|
197
269
|
end
|
|
198
270
|
|
|
199
271
|
describe "perform_validation" do
|
|
@@ -204,9 +276,9 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
|
204
276
|
|
|
205
277
|
it "checks whether the font used in /DA is available in /DR" do
|
|
206
278
|
@acro_form[:DA] = '/F2 0 Tf /F1 0 Tf'
|
|
207
|
-
refute(@acro_form.validate {|msg
|
|
279
|
+
refute(@acro_form.validate {|msg| assert_match(/DR must also be present/, msg) })
|
|
208
280
|
@acro_form.default_resources[:Font] = {}
|
|
209
|
-
refute(@acro_form.validate {|msg
|
|
281
|
+
refute(@acro_form.validate {|msg| assert_match(/font.*is not.*resource/, msg) })
|
|
210
282
|
@acro_form.default_resources[:Font][:F1] = :yes
|
|
211
283
|
assert(@acro_form.validate)
|
|
212
284
|
end
|
|
@@ -21,6 +21,56 @@ describe HexaPDF::Type::AcroForm::TextField do
|
|
|
21
21
|
assert_equal(6, @field[:MaxLen])
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
it "can be initialized as a multiline text field" do
|
|
25
|
+
@field.flag(:comb)
|
|
26
|
+
@field.initialize_as_multiline_text_field
|
|
27
|
+
assert(@field.multiline_text_field?)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "can be initialized as comb text field" do
|
|
31
|
+
@field.flag(:multiline)
|
|
32
|
+
@field.initialize_as_comb_text_field
|
|
33
|
+
assert(@field.comb_text_field?)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "can be initialized as password field" do
|
|
37
|
+
@field.flag(:multiline)
|
|
38
|
+
@field[:V] = 'test'
|
|
39
|
+
@field.initialize_as_password_field
|
|
40
|
+
assert_nil(@field[:V])
|
|
41
|
+
assert(@field.password_field?)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "can be initialized as a file select field" do
|
|
45
|
+
@field.flag(:multiline)
|
|
46
|
+
@field.initialize_as_file_select_field
|
|
47
|
+
assert(@field.file_select_field?)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "can check whether the field is a multiline text field" do
|
|
51
|
+
refute(@field.multiline_text_field?)
|
|
52
|
+
@field.flag(:multiline)
|
|
53
|
+
assert(@field.multiline_text_field?)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "can check whether the field is a comb text field" do
|
|
57
|
+
refute(@field.comb_text_field?)
|
|
58
|
+
@field.flag(:comb)
|
|
59
|
+
assert(@field.comb_text_field?)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "can check whether the field is a password field" do
|
|
63
|
+
refute(@field.password_field?)
|
|
64
|
+
@field.flag(:password)
|
|
65
|
+
assert(@field.password_field?)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "can check whether the field is a file select field" do
|
|
69
|
+
refute(@field.file_select_field?)
|
|
70
|
+
@field.flag(:file_select)
|
|
71
|
+
assert(@field.file_select_field?)
|
|
72
|
+
end
|
|
73
|
+
|
|
24
74
|
describe "field_value" do
|
|
25
75
|
it "handles unset values" do
|
|
26
76
|
assert_nil(@field.field_value)
|
|
@@ -81,14 +131,38 @@ describe HexaPDF::Type::AcroForm::TextField do
|
|
|
81
131
|
end
|
|
82
132
|
|
|
83
133
|
describe "create_appearances" do
|
|
84
|
-
|
|
134
|
+
before do
|
|
85
135
|
@doc.acro_form(create: true)
|
|
86
136
|
@field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
87
137
|
@field.set_default_appearance_string
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "creates the needed streams" do
|
|
88
141
|
@field.create_appearances
|
|
89
142
|
assert(@field[:AP][:N])
|
|
90
143
|
end
|
|
91
144
|
|
|
145
|
+
it "doesn't create a new appearance stream if the field value hasn't changed, checked per widget" do
|
|
146
|
+
@field.create_appearances
|
|
147
|
+
stream = @field[:AP][:N].raw_stream
|
|
148
|
+
@field.create_appearances
|
|
149
|
+
assert_same(stream, @field[:AP][:N].raw_stream)
|
|
150
|
+
@field.field_value = 'test'
|
|
151
|
+
refute_same(stream, @field[:AP][:N].raw_stream)
|
|
152
|
+
|
|
153
|
+
widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
|
154
|
+
assert_nil(widget[:AP])
|
|
155
|
+
@field.create_appearances
|
|
156
|
+
refute_nil(widget[:AP][:N])
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "always creates a new appearance stream if force is true" do
|
|
160
|
+
@field.create_appearances
|
|
161
|
+
stream = @field[:AP][:N].raw_stream
|
|
162
|
+
@field.create_appearances(force: true)
|
|
163
|
+
refute_same(stream, @field[:AP][:N].raw_stream)
|
|
164
|
+
end
|
|
165
|
+
|
|
92
166
|
it "uses the configuration option acro_form.appearance_generator" do
|
|
93
167
|
@doc.config['acro_form.appearance_generator'] = 'NonExistent'
|
|
94
168
|
assert_raises(Exception) { @field.create_appearances }
|
|
@@ -114,6 +188,8 @@ describe HexaPDF::Type::AcroForm::TextField do
|
|
|
114
188
|
assert(@field.validate)
|
|
115
189
|
@field[:MaxLen] = 2
|
|
116
190
|
refute(@field.validate)
|
|
191
|
+
@field[:V] = nil
|
|
192
|
+
assert(@field.validate)
|
|
117
193
|
end
|
|
118
194
|
end
|
|
119
195
|
end
|