hexapdf 0.32.2 → 0.34.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 +104 -1
- data/README.md +9 -0
- data/examples/002-graphics.rb +15 -17
- data/examples/003-arcs.rb +9 -9
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +2 -2
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +7 -7
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +8 -7
- data/examples/016-frame_automatic_box_placement.rb +2 -2
- data/examples/017-frame_text_flow.rb +2 -1
- data/examples/018-composer.rb +1 -1
- data/examples/020-column_box.rb +2 -1
- data/examples/025-table_box.rb +46 -0
- data/examples/026-optional_content.rb +55 -0
- data/examples/027-composer_optional_content.rb +83 -0
- data/lib/hexapdf/cli/command.rb +12 -3
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +5 -7
- data/lib/hexapdf/composer.rb +106 -53
- data/lib/hexapdf/configuration.rb +65 -40
- data/lib/hexapdf/content/canvas.rb +445 -267
- data/lib/hexapdf/content/color_space.rb +72 -25
- data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
- data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
- data/lib/hexapdf/content/graphic_object.rb +6 -7
- data/lib/hexapdf/content/graphics_state.rb +54 -45
- data/lib/hexapdf/content/operator.rb +54 -54
- data/lib/hexapdf/content/parser.rb +2 -2
- data/lib/hexapdf/content/processor.rb +15 -15
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +5 -0
- data/lib/hexapdf/dictionary.rb +7 -5
- data/lib/hexapdf/dictionary_fields.rb +43 -16
- data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
- data/lib/hexapdf/digital_signature/signature.rb +6 -6
- data/lib/hexapdf/digital_signature/signatures.rb +13 -12
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
- data/lib/hexapdf/digital_signature/signing.rb +4 -0
- data/lib/hexapdf/digital_signature/verification_result.rb +3 -4
- data/lib/hexapdf/digital_signature.rb +7 -2
- data/lib/hexapdf/document/destinations.rb +12 -11
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/layout.rb +170 -39
- data/lib/hexapdf/document/pages.rb +4 -3
- data/lib/hexapdf/document.rb +96 -55
- data/lib/hexapdf/encryption/aes.rb +5 -5
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +2 -2
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +11 -21
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +31 -24
- data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
- data/lib/hexapdf/encryption.rb +7 -2
- data/lib/hexapdf/error.rb +18 -0
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.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/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +55 -6
- data/lib/hexapdf/font/cmap/parser.rb +2 -2
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
- 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 +3 -3
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +3 -0
- data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
- data/lib/hexapdf/font/type1_wrapper.rb +19 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
- data/lib/hexapdf/font_loader/from_file.rb +5 -5
- data/lib/hexapdf/font_loader/standard14.rb +3 -3
- data/lib/hexapdf/font_loader.rb +3 -0
- data/lib/hexapdf/image_loader/jpeg.rb +2 -2
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +2 -2
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +13 -0
- data/lib/hexapdf/layout/box.rb +32 -5
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +20 -5
- data/lib/hexapdf/layout/frame.rb +53 -18
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +21 -9
- data/lib/hexapdf/layout/list_box.rb +50 -20
- data/lib/hexapdf/layout/page_style.rb +6 -5
- data/lib/hexapdf/layout/style.rb +64 -9
- data/lib/hexapdf/layout/table_box.rb +684 -0
- data/lib/hexapdf/layout/text_box.rb +12 -3
- data/lib/hexapdf/layout/text_fragment.rb +29 -3
- data/lib/hexapdf/layout/text_layouter.rb +32 -8
- data/lib/hexapdf/layout.rb +1 -0
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +18 -7
- data/lib/hexapdf/parser.rb +7 -7
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +1 -1
- data/lib/hexapdf/revisions.rb +3 -3
- data/lib/hexapdf/serializer.rb +15 -15
- data/lib/hexapdf/stream.rb +5 -4
- data/lib/hexapdf/tokenizer.rb +14 -14
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +2 -2
- data/lib/hexapdf/type/acro_form/form.rb +1 -1
- data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
- data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.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/set_ocg_state.rb +86 -0
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +2 -1
- data/lib/hexapdf/type/annotation.rb +3 -3
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +2 -3
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +11 -2
- data/lib/hexapdf/type/cid_font.rb +18 -4
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +3 -3
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +76 -6
- 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 +1 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/mark_information.rb +1 -1
- data/lib/hexapdf/type/names.rb +2 -2
- data/lib/hexapdf/type/object_stream.rb +2 -1
- data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
- data/lib/hexapdf/type/optional_content_group.rb +370 -0
- data/lib/hexapdf/type/optional_content_membership.rb +63 -0
- data/lib/hexapdf/type/optional_content_properties.rb +158 -0
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +46 -21
- data/lib/hexapdf/type/page_label.rb +5 -9
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +2 -2
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/type.rb +4 -0
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -2
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +4 -4
- data/lib/hexapdf/xref_section.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
- data/test/hexapdf/content/test_canvas.rb +49 -1
- data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
- data/test/hexapdf/document/test_files.rb +2 -2
- data/test/hexapdf/document/test_layout.rb +105 -2
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/encryption/test_security_handler.rb +12 -11
- data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
- data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
- data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
- data/test/hexapdf/layout/test_box.rb +14 -5
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +27 -15
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +17 -3
- data/test/hexapdf/layout/test_list_box.rb +84 -33
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +60 -0
- data/test/hexapdf/layout/test_table_box.rb +728 -0
- data/test/hexapdf/layout/test_text_box.rb +26 -0
- data/test/hexapdf/layout/test_text_fragment.rb +33 -0
- data/test/hexapdf/layout/test_text_layouter.rb +36 -5
- data/test/hexapdf/test_composer.rb +10 -0
- data/test/hexapdf/test_dictionary.rb +10 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +5 -0
- data/test/hexapdf/test_filter.rb +8 -0
- data/test/hexapdf/test_importer.rb +9 -0
- data/test/hexapdf/test_object.rb +16 -5
- data/test/hexapdf/test_stream.rb +7 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
- data/test/hexapdf/type/acro_form/test_form.rb +4 -3
- data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
- data/test/hexapdf/type/test_catalog.rb +11 -0
- data/test/hexapdf/type/test_form.rb +119 -0
- data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
- data/test/hexapdf/type/test_optional_content_group.rb +158 -0
- data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
- data/test/hexapdf/type/test_page.rb +20 -6
- metadata +28 -8
|
@@ -196,15 +196,15 @@ describe HexaPDF::Document::Pages do
|
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
it "works for multiple page label entries" do
|
|
199
|
-
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 2, {S: :
|
|
199
|
+
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 2, {S: :D}, 7, {S: :A}]}
|
|
200
200
|
result = @doc.pages.each_labelling_range.to_a
|
|
201
|
-
assert_equal([[0, 2, {S: :r}], [2, 5, {S: :
|
|
201
|
+
assert_equal([[0, 2, {S: :r}], [2, 5, {S: :D}], [7, 3, {S: :A}]],
|
|
202
202
|
result.map {|s, c, l| [s, c, l.value] })
|
|
203
203
|
end
|
|
204
204
|
|
|
205
205
|
it "returns a zero or negative count for the last range if there aren't enough pages" do
|
|
206
206
|
assert_equal(10, @doc.pages.count)
|
|
207
|
-
@doc.catalog[:PageLabels] = {Nums: [0, {S: :
|
|
207
|
+
@doc.catalog[:PageLabels] = {Nums: [0, {S: :D}, 10, {S: :r}]}
|
|
208
208
|
assert_equal(0, @doc.pages.each_labelling_range.to_a[-1][1])
|
|
209
209
|
@doc.catalog[:PageLabels][:Nums][2] = 11
|
|
210
210
|
assert_equal(-1, @doc.pages.each_labelling_range.to_a[-1][1])
|
|
@@ -221,19 +221,19 @@ describe HexaPDF::Document::Pages do
|
|
|
221
221
|
|
|
222
222
|
it "adds an entry for the range starting at 0 if it doesn't exist" do
|
|
223
223
|
label = @doc.pages.add_labelling_range(5)
|
|
224
|
-
assert_equal([{S: :
|
|
224
|
+
assert_equal([{S: :D}, label],
|
|
225
225
|
@doc.catalog.page_labels[:Nums].value.values_at(1, 3))
|
|
226
226
|
end
|
|
227
227
|
end
|
|
228
228
|
|
|
229
229
|
describe "delete_labelling_range" do
|
|
230
230
|
before do
|
|
231
|
-
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 5, {S: :
|
|
231
|
+
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 5, {S: :D}]}
|
|
232
232
|
end
|
|
233
233
|
|
|
234
234
|
it "deletes the labelling range for a given start index" do
|
|
235
235
|
label = @doc.pages.delete_labelling_range(5)
|
|
236
|
-
assert_equal({S: :
|
|
236
|
+
assert_equal({S: :D}, label)
|
|
237
237
|
end
|
|
238
238
|
|
|
239
239
|
it "deletes the labelling range for 0 if it is the last, together with the number tree" do
|
|
@@ -17,13 +17,6 @@ describe HexaPDF::Encryption::EncryptionDictionary do
|
|
|
17
17
|
assert(@dict.must_be_indirect?)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
it "validates the /V value" do
|
|
21
|
-
@dict[:V] = 1
|
|
22
|
-
assert(@dict.validate)
|
|
23
|
-
@dict[:V] = 3
|
|
24
|
-
refute(@dict.validate)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
20
|
it "validates the /Length field when /V=2" do
|
|
28
21
|
@dict[:V] = 2
|
|
29
22
|
refute(@dict.validate)
|
|
@@ -240,6 +233,7 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
|
240
233
|
[:identity, 128, {V: 4, StrF: :Mine, CF: {Mine: {CFM: :None}}}],
|
|
241
234
|
[:identity, 128, {V: 4, CF: {Mine: {CFM: :AESV2}}}],
|
|
242
235
|
].each do |alg, length, dict|
|
|
236
|
+
dict[:Filter] = :Test
|
|
243
237
|
@enc.strf = alg
|
|
244
238
|
@enc.set_up_encryption(key_length: length, algorithm: (alg == :identity ? :aes : alg))
|
|
245
239
|
@obj[:X] = @enc.encrypt_string('data', @obj)
|
|
@@ -249,7 +243,7 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
|
249
243
|
end
|
|
250
244
|
|
|
251
245
|
it "selects the correct algorithm for string, stream and embedded file decryption" do
|
|
252
|
-
@handler.set_up_decryption({V: 4, StrF: :Mine, StmF: :Mine, EFF: :Mine,
|
|
246
|
+
@handler.set_up_decryption({Filter: :Test, V: 4, StrF: :Mine, StmF: :Mine, EFF: :Mine,
|
|
253
247
|
CF: {Mine: {CFM: :V2}}})
|
|
254
248
|
assert_equal(HexaPDF::Encryption::FastARC4, @handler.send(:embedded_file_algorithm))
|
|
255
249
|
assert_equal(HexaPDF::Encryption::FastARC4, @handler.send(:string_algorithm))
|
|
@@ -263,16 +257,23 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
|
263
257
|
@handler.encryption_details)
|
|
264
258
|
end
|
|
265
259
|
|
|
260
|
+
it "fails if the encryption dictionary is not valid" do
|
|
261
|
+
exp = assert_raises(HexaPDF::Error) do
|
|
262
|
+
@handler.set_up_decryption({V: 5})
|
|
263
|
+
end
|
|
264
|
+
assert_match(/Validation error for encryption dictionary.*Required field Filter/i, exp.message)
|
|
265
|
+
end
|
|
266
|
+
|
|
266
267
|
it "fails for unsupported /V values in the dict" do
|
|
267
268
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
|
268
|
-
@handler.set_up_decryption({V: 3})
|
|
269
|
+
@handler.set_up_decryption({Filter: :Text, V: 3})
|
|
269
270
|
end
|
|
270
271
|
assert_match(/Unsupported encryption version/i, exp.message)
|
|
271
272
|
end
|
|
272
273
|
|
|
273
274
|
it "fails for unsupported crypt filter encryption methods" do
|
|
274
275
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
|
275
|
-
@handler.set_up_decryption({V: 4, StrF: :Mine, CF: {Mine: {CFM: :Unknown}}})
|
|
276
|
+
@handler.set_up_decryption({Filter: :Test, V: 4, StrF: :Mine, CF: {Mine: {CFM: :Unknown}}})
|
|
276
277
|
end
|
|
277
278
|
assert_match(/Unsupported encryption method/i, exp.message)
|
|
278
279
|
end
|
|
@@ -280,7 +281,7 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
|
280
281
|
|
|
281
282
|
describe "decrypt" do
|
|
282
283
|
before do
|
|
283
|
-
@handler.set_up_decryption({V: 1})
|
|
284
|
+
@handler.set_up_decryption({Filter: :Test, V: 1})
|
|
284
285
|
@encrypted = @handler.encrypt_string('string', @obj)
|
|
285
286
|
@obj.value = {Key: @encrypted.dup, Array: [@encrypted.dup], Hash: {Another: @encrypted.dup}}
|
|
286
287
|
end
|
|
@@ -21,13 +21,6 @@ describe HexaPDF::Encryption::StandardEncryptionDictionary do
|
|
|
21
21
|
@dict[:Perms] = 'test' * 8
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
it "validates the /R value" do
|
|
25
|
-
@dict[:R] = 2
|
|
26
|
-
assert(@dict.validate)
|
|
27
|
-
@dict[:R] = 5
|
|
28
|
-
refute(@dict.validate)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
24
|
[:U, :O].each do |field|
|
|
32
25
|
it "validates the length of /#{field} field for R <= 4" do
|
|
33
26
|
@dict[field] = 'test'
|
|
@@ -35,19 +28,36 @@ describe HexaPDF::Encryption::StandardEncryptionDictionary do
|
|
|
35
28
|
end
|
|
36
29
|
end
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
describe "validation for R=6" do
|
|
32
|
+
before do
|
|
40
33
|
@dict[:R] = 6
|
|
41
|
-
@dict[
|
|
42
|
-
|
|
34
|
+
@dict[:U] = 't' * 48
|
|
35
|
+
@dict[:O] = 't' * 48
|
|
36
|
+
@dict[:UE] = 't' * 32
|
|
37
|
+
@dict[:OE] = 't' * 32
|
|
38
|
+
@dict[:Perms] = 't' * 16
|
|
43
39
|
end
|
|
44
|
-
end
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
[:U, :O, :UE, :OE, :Perms].each do |field|
|
|
42
|
+
it "validates the length of /#{field}" do
|
|
43
|
+
@dict[field] = 'test'
|
|
44
|
+
refute(@dict.validate)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
[:U, :O].each do |field|
|
|
49
|
+
it "auto-corrects /#{field} if it is larger and only padded with 0 bytes" do
|
|
50
|
+
@dict[field] = 't' * 48 + "\x00" * 20
|
|
51
|
+
assert(@dict.validate)
|
|
52
|
+
assert_equal('t' * 48, @dict[field])
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
[:UE, :OE, :Perms].each do |field|
|
|
57
|
+
it "validates the existence of the /#{field} field" do
|
|
58
|
+
@dict.delete(field)
|
|
59
|
+
refute(@dict.validate)
|
|
60
|
+
end
|
|
51
61
|
end
|
|
52
62
|
end
|
|
53
63
|
end
|
|
@@ -211,22 +221,24 @@ describe HexaPDF::Encryption::StandardSecurityHandler do
|
|
|
211
221
|
describe "prepare_decryption" do
|
|
212
222
|
it "fails if the /Filter value is incorrect" do
|
|
213
223
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
|
214
|
-
@handler.set_up_decryption({Filter: :NonStandard, V: 2
|
|
224
|
+
@handler.set_up_decryption({Filter: :NonStandard, V: 2, R: 4, O: 't' * 32, U: 't' * 32, P: 0,
|
|
225
|
+
Length: 128})
|
|
215
226
|
end
|
|
216
227
|
assert_match(/Invalid \/Filter value NonStandard/i, exp.message)
|
|
217
228
|
end
|
|
218
229
|
|
|
219
230
|
it "fails if the /R value is incorrect" do
|
|
220
231
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
|
221
|
-
@handler.set_up_decryption({Filter: :Standard, V: 2, R: 5
|
|
232
|
+
@handler.set_up_decryption({Filter: :Standard, V: 2, R: 5, O: 't' * 32, U: 't' * 32, P: 0,
|
|
233
|
+
Length: 128})
|
|
222
234
|
end
|
|
223
235
|
assert_match(/Invalid \/R value 5/i, exp.message)
|
|
224
236
|
end
|
|
225
237
|
|
|
226
238
|
it "fails if the supplied password is invalid" do
|
|
227
239
|
exp = assert_raises(HexaPDF::EncryptionError) do
|
|
228
|
-
@handler.set_up_decryption({Filter: :Standard, V:
|
|
229
|
-
UE: 'a' * 32, OE: 'a' * 32})
|
|
240
|
+
@handler.set_up_decryption({Filter: :Standard, V: 5, R: 6, U: 'a' * 48, O: 'a' * 48,
|
|
241
|
+
UE: 'a' * 32, OE: 'a' * 32, P: 0, Perms: 'a' * 16})
|
|
230
242
|
end
|
|
231
243
|
assert_match(/Invalid password/i, exp.message)
|
|
232
244
|
end
|
|
@@ -234,7 +246,7 @@ describe HexaPDF::Encryption::StandardSecurityHandler do
|
|
|
234
246
|
it "assigns empty strings to the trailer's ID field if it is missing" do
|
|
235
247
|
refute(@document.trailer.key?(:ID))
|
|
236
248
|
exp = assert_raises(HexaPDF::EncryptionError) do
|
|
237
|
-
@handler.set_up_decryption({Filter: :Standard, V: 1, R: 2, U: 'a' *
|
|
249
|
+
@handler.set_up_decryption({Filter: :Standard, V: 1, R: 2, U: 'a' * 32, O: 'a' * 32, P: 15})
|
|
238
250
|
end
|
|
239
251
|
assert_match(/Invalid password/i, exp.message)
|
|
240
252
|
assert_equal(['', ''], @document.trailer[:ID].value)
|
|
@@ -286,7 +298,7 @@ describe HexaPDF::Encryption::StandardSecurityHandler do
|
|
|
286
298
|
it "returns an array of permission symbols" do
|
|
287
299
|
perms = @handler.class::Permissions::MODIFY_CONTENT | @handler.class::Permissions::COPY_CONTENT
|
|
288
300
|
@handler.set_up_encryption(permissions: perms)
|
|
289
|
-
assert_equal([:copy_content, :modify_content], @handler.permissions.sort)
|
|
301
|
+
assert_equal([:copy_content, :extract_content, :modify_content], @handler.permissions.sort)
|
|
290
302
|
end
|
|
291
303
|
|
|
292
304
|
describe "handling of metadata streams" do
|
|
@@ -66,6 +66,20 @@ describe HexaPDF::Font::TrueTypeWrapper do
|
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
describe "custom_glyph" do
|
|
70
|
+
it "returns the specified glyph object" do
|
|
71
|
+
glyph = @font_wrapper.custom_glyph(0, "str")
|
|
72
|
+
assert_equal(0, glyph.id)
|
|
73
|
+
assert_equal("str", glyph.str)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "fails if an invalid glyph id is specified" do
|
|
77
|
+
exp = assert_raises(HexaPDF::Error) { @font_wrapper.custom_glyph(-5, 'c') }
|
|
78
|
+
assert_match(/Glyph ID -5 is invalid for font 'Ubuntu-Title'/, exp.message)
|
|
79
|
+
assert_raises(HexaPDF::Error) { @font_wrapper.custom_glyph(9999, 'c') }
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
69
83
|
describe "encode" do
|
|
70
84
|
it "returns the encoded glyph ID for fonts that are subset" do
|
|
71
85
|
code = @font_wrapper.encode(@font_wrapper.glyph(3))
|
|
@@ -83,7 +97,10 @@ describe HexaPDF::Font::TrueTypeWrapper do
|
|
|
83
97
|
end
|
|
84
98
|
|
|
85
99
|
it "raises an error if an InvalidGlyph is encoded" do
|
|
86
|
-
assert_raises(HexaPDF::
|
|
100
|
+
exp = assert_raises(HexaPDF::MissingGlyphError) do
|
|
101
|
+
@font_wrapper.encode(@font_wrapper.decode_utf8("ö").first)
|
|
102
|
+
end
|
|
103
|
+
assert_match(/No glyph for "ö" in font 'Ubuntu-Title'/, exp.message)
|
|
87
104
|
end
|
|
88
105
|
end
|
|
89
106
|
|
|
@@ -65,6 +65,19 @@ describe HexaPDF::Font::Type1Wrapper do
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
describe "custom_glyph" do
|
|
69
|
+
it "returns the specified glyph object" do
|
|
70
|
+
glyph = @times_wrapper.custom_glyph(:question, "str")
|
|
71
|
+
assert_equal(:question, glyph.name)
|
|
72
|
+
assert_equal("str", glyph.str)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "fails if the provided glyph name is not available for the font" do
|
|
76
|
+
exp = assert_raises(HexaPDF::Error) { @times_wrapper.custom_glyph(:handicap, 'c') }
|
|
77
|
+
assert_match(/Glyph named :handicap not found in font 'Times Roman'/, exp.message)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
68
81
|
describe "encode" do
|
|
69
82
|
describe "uses WinAnsiEncoding as initial encoding for non-symbolic fonts" do
|
|
70
83
|
it "returns the PDF font dictionary using WinAnsiEncoding and encoded glyph" do
|
|
@@ -75,7 +88,8 @@ describe HexaPDF::Font::Type1Wrapper do
|
|
|
75
88
|
end
|
|
76
89
|
|
|
77
90
|
it "fails if an InvalidGlyph is encoded" do
|
|
78
|
-
assert_raises(HexaPDF::
|
|
91
|
+
exp = assert_raises(HexaPDF::MissingGlyphError) { @times_wrapper.encode(@times_wrapper.glyph(:ffi)) }
|
|
92
|
+
assert_match(/No glyph for "ffi" in font 'Times Roman'/, exp.message)
|
|
79
93
|
end
|
|
80
94
|
|
|
81
95
|
it "fails if the encoding does not support the given glyph" do
|
|
@@ -56,8 +56,8 @@ describe HexaPDF::Layout::Box do
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
it "allows setting custom properties" do
|
|
59
|
-
|
|
60
|
-
assert_equal({'key' => :value},
|
|
59
|
+
assert_equal({}, create_box(properties: nil).properties)
|
|
60
|
+
assert_equal({'key' => :value}, create_box(properties: {'key' => :value}).properties)
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -150,6 +150,10 @@ describe HexaPDF::Layout::Box do
|
|
|
150
150
|
end
|
|
151
151
|
|
|
152
152
|
describe "draw" do
|
|
153
|
+
before do
|
|
154
|
+
@canvas = HexaPDF::Document.new.pages.add.canvas
|
|
155
|
+
end
|
|
156
|
+
|
|
153
157
|
it "draws the box onto the canvas" do
|
|
154
158
|
box = create_box(width: 150, height: 130) do |canvas, _|
|
|
155
159
|
canvas.line_width(15)
|
|
@@ -161,7 +165,6 @@ describe HexaPDF::Layout::Box do
|
|
|
161
165
|
box.style.underlays.add {|canvas, _| canvas.line_width(10) }
|
|
162
166
|
box.style.overlays.add {|canvas, _| canvas.line_width(20) }
|
|
163
167
|
|
|
164
|
-
@canvas = HexaPDF::Document.new.pages.add.canvas
|
|
165
168
|
box.draw(@canvas, 5, 5)
|
|
166
169
|
assert_operators(@canvas.contents, [[:save_graphics_state],
|
|
167
170
|
[:set_graphics_state_parameters, [:GS1]],
|
|
@@ -195,7 +198,6 @@ describe HexaPDF::Layout::Box do
|
|
|
195
198
|
end
|
|
196
199
|
|
|
197
200
|
it "draws nothing onto the canvas if the box is empty" do
|
|
198
|
-
@canvas = HexaPDF::Document.new.pages.add.canvas
|
|
199
201
|
box = create_box
|
|
200
202
|
box.draw(@canvas, 5, 5)
|
|
201
203
|
assert_operators(@canvas.contents, [])
|
|
@@ -204,10 +206,17 @@ describe HexaPDF::Layout::Box do
|
|
|
204
206
|
refute(box.style.border?)
|
|
205
207
|
refute(box.style.overlays?)
|
|
206
208
|
end
|
|
209
|
+
|
|
210
|
+
it "wraps the box in optional content markers if the optional_content property is set" do
|
|
211
|
+
box = create_box(properties: {'optional_content' => 'Text'})
|
|
212
|
+
box.draw(@canvas, 0, 0)
|
|
213
|
+
assert_operators(@canvas.contents, [[:begin_marked_content_with_property_list, [:OC, :P1]],
|
|
214
|
+
[:end_marked_content]])
|
|
215
|
+
end
|
|
207
216
|
end
|
|
208
217
|
|
|
209
218
|
describe "empty?" do
|
|
210
|
-
it "is
|
|
219
|
+
it "is empty when no drawing operation is specified" do
|
|
211
220
|
assert(create_box.empty?)
|
|
212
221
|
refute(create_box {}.empty?)
|
|
213
222
|
refute(create_box(style: {background_color: [5]}).empty?)
|
|
@@ -22,7 +22,7 @@ describe HexaPDF::Layout::ColumnBox do
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def check_box(box, width, height, fit_pos = nil)
|
|
25
|
-
assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box fit
|
|
25
|
+
assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box didn't fit")
|
|
26
26
|
assert_equal(width, box.width, "box width")
|
|
27
27
|
assert_equal(height, box.height, "box height")
|
|
28
28
|
if fit_pos
|
|
@@ -46,6 +46,24 @@ describe HexaPDF::Layout::ColumnBox do
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
describe "empty?" do
|
|
50
|
+
it "is empty if nothing is fit yet" do
|
|
51
|
+
assert(create_box.empty?)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "is empty if no box fits" do
|
|
55
|
+
box = create_box(children: [@fixed_size_boxes[0]], columns: [10])
|
|
56
|
+
box.fit(@frame.available_width, @frame.available_height, @frame)
|
|
57
|
+
assert(box.empty?)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "is not empty if at least one box fits" do
|
|
61
|
+
box = create_box(children: [@fixed_size_boxes[0]], columns: [30])
|
|
62
|
+
check_box(box, 30, 10)
|
|
63
|
+
refute(box.empty?)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
49
67
|
describe "fit" do
|
|
50
68
|
[:default, :flow].each do |position|
|
|
51
69
|
it "respects the set initial width, position #{position}" do
|
|
@@ -132,27 +150,53 @@ describe HexaPDF::Layout::ColumnBox do
|
|
|
132
150
|
assert_equal(5, box_b.children.size)
|
|
133
151
|
end
|
|
134
152
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
describe "draw_content" do
|
|
154
|
+
before do
|
|
155
|
+
@canvas = HexaPDF::Document.new.pages.add.canvas
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "draws the result onto the canvas" do
|
|
159
|
+
box = create_box(children: @fixed_size_boxes)
|
|
160
|
+
box.fit(100, 100, @frame)
|
|
161
|
+
box.draw(@canvas, 0, 100 - box.height)
|
|
162
|
+
operators = 90.step(to: 20, by: -10).map do |y|
|
|
163
|
+
[[:save_graphics_state],
|
|
164
|
+
[:concatenate_matrix, [1, 0, 0, 1, 0, y]],
|
|
165
|
+
[:move_to, [0, 0]],
|
|
166
|
+
[:end_path],
|
|
167
|
+
[:restore_graphics_state]]
|
|
168
|
+
end
|
|
169
|
+
operators.concat(90.step(to: 30, by: -10).map do |y|
|
|
170
|
+
[[:save_graphics_state],
|
|
171
|
+
[:concatenate_matrix, [1, 0, 0, 1, 55, y]],
|
|
172
|
+
[:move_to, [0, 0]],
|
|
173
|
+
[:end_path],
|
|
174
|
+
[:restore_graphics_state]]
|
|
175
|
+
end)
|
|
176
|
+
operators.flatten!(1)
|
|
177
|
+
assert_operators(@canvas.contents, operators)
|
|
178
|
+
end
|
|
138
179
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
180
|
+
it "takes a different final location into account" do
|
|
181
|
+
box = create_box(children: @fixed_size_boxes[0, 2])
|
|
182
|
+
box.fit(100, 100, @frame)
|
|
183
|
+
box.draw(@canvas, 20, 10)
|
|
184
|
+
operators = [
|
|
185
|
+
[:save_graphics_state],
|
|
186
|
+
[:concatenate_matrix, [1, 0, 0, 1, 20, -80]],
|
|
187
|
+
[:save_graphics_state],
|
|
188
|
+
[:concatenate_matrix, [1, 0, 0, 1, 0, 90]],
|
|
189
|
+
[:move_to, [0, 0]],
|
|
190
|
+
[:end_path],
|
|
191
|
+
[:restore_graphics_state],
|
|
192
|
+
[:save_graphics_state],
|
|
193
|
+
[:concatenate_matrix, [1, 0, 0, 1, 55, 90]],
|
|
194
|
+
[:move_to, [0, 0]],
|
|
195
|
+
[:end_path],
|
|
196
|
+
[:restore_graphics_state],
|
|
197
|
+
[:restore_graphics_state],
|
|
198
|
+
]
|
|
199
|
+
assert_operators(@canvas.contents, operators)
|
|
147
200
|
end
|
|
148
|
-
operators.concat(90.step(to: 30, by: -10).map do |y|
|
|
149
|
-
[[:save_graphics_state],
|
|
150
|
-
[:concatenate_matrix, [1, 0, 0, 1, 55, y]],
|
|
151
|
-
[:move_to, [0, 0]],
|
|
152
|
-
[:end_path],
|
|
153
|
-
[:restore_graphics_state]]
|
|
154
|
-
end)
|
|
155
|
-
operators.flatten!(1)
|
|
156
|
-
assert_operators(@canvas.contents, operators)
|
|
157
201
|
end
|
|
158
202
|
end
|
|
@@ -5,31 +5,31 @@ require 'hexapdf/layout/frame'
|
|
|
5
5
|
require 'hexapdf/layout/box'
|
|
6
6
|
require 'hexapdf/document'
|
|
7
7
|
|
|
8
|
-
describe HexaPDF::Layout::Frame do
|
|
8
|
+
describe HexaPDF::Layout::Frame::FitResult do
|
|
9
9
|
it "shows the box's mask area on #draw when using debug output" do
|
|
10
10
|
doc = HexaPDF::Document.new(config: {'debug' => true})
|
|
11
11
|
canvas = doc.pages.add.canvas
|
|
12
12
|
box = HexaPDF::Layout::Box.create(width: 20, height: 20) {}
|
|
13
13
|
result = HexaPDF::Layout::Frame::FitResult.new(box)
|
|
14
|
-
result.mask = Geom2D::
|
|
14
|
+
result.mask = Geom2D::Rectangle(0, 0, 20, 20)
|
|
15
15
|
result.x = result.y = 0
|
|
16
16
|
result.draw(canvas)
|
|
17
17
|
assert_equal(<<~CONTENTS, canvas.contents)
|
|
18
|
+
/OC /P1 BDC
|
|
18
19
|
q
|
|
19
20
|
0.0 0.501961 0.0 rg
|
|
20
21
|
0.0 0.392157 0.0 RG
|
|
21
22
|
/GS1 gs
|
|
22
|
-
0 0
|
|
23
|
-
0 20 l
|
|
24
|
-
20 20 l
|
|
25
|
-
20 0 l
|
|
26
|
-
h
|
|
23
|
+
0 0 20 20 re
|
|
27
24
|
B
|
|
28
25
|
Q
|
|
26
|
+
EMC
|
|
29
27
|
q
|
|
30
28
|
1 0 0 1 0 0 cm
|
|
31
29
|
Q
|
|
32
30
|
CONTENTS
|
|
31
|
+
ocg = doc.optional_content.ocgs.first
|
|
32
|
+
assert_equal([['Debug', ocg]], doc.optional_content.default_configuration[:Order])
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -38,6 +38,14 @@ describe HexaPDF::Layout::Frame do
|
|
|
38
38
|
@frame = HexaPDF::Layout::Frame.new(5, 10, 100, 150)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
it "allows accessing the context's document" do
|
|
42
|
+
assert_nil(@frame.document)
|
|
43
|
+
context = Minitest::Mock.new
|
|
44
|
+
context.expect(:document, :document)
|
|
45
|
+
assert_equal(:document, HexaPDF::Layout::Frame.new(0, 0, 10, 10, context: context).document)
|
|
46
|
+
context.verify
|
|
47
|
+
end
|
|
48
|
+
|
|
41
49
|
it "allows access to the bounding box attributes" do
|
|
42
50
|
assert_equal(5, @frame.left)
|
|
43
51
|
assert_equal(10, @frame.bottom)
|
|
@@ -90,7 +98,11 @@ describe HexaPDF::Layout::Frame do
|
|
|
90
98
|
refute_nil(fit_result)
|
|
91
99
|
@frame.draw(@canvas, fit_result)
|
|
92
100
|
assert_equal(mask, fit_result.mask.bbox.to_a)
|
|
93
|
-
|
|
101
|
+
if @frame.shape.respond_to?(:polygons)
|
|
102
|
+
assert_equal(points, @frame.shape.polygons.map(&:to_a))
|
|
103
|
+
else
|
|
104
|
+
assert_equal(points, [@frame.shape.to_a])
|
|
105
|
+
end
|
|
94
106
|
@canvas.verify
|
|
95
107
|
end
|
|
96
108
|
|
|
@@ -99,9 +111,9 @@ describe HexaPDF::Layout::Frame do
|
|
|
99
111
|
areas.each do |area|
|
|
100
112
|
@frame.remove_area(
|
|
101
113
|
case area
|
|
102
|
-
when :left then Geom2D::
|
|
103
|
-
when :right then Geom2D::
|
|
104
|
-
when :top then Geom2D::
|
|
114
|
+
when :left then Geom2D::Rectangle(10, 10, 10, 100)
|
|
115
|
+
when :right then Geom2D::Rectangle(100, 10, 10, 100)
|
|
116
|
+
when :top then Geom2D::Rectangle(10, 100, 100, 10)
|
|
105
117
|
end
|
|
106
118
|
)
|
|
107
119
|
end
|
|
@@ -323,7 +335,7 @@ describe HexaPDF::Layout::Frame do
|
|
|
323
335
|
end
|
|
324
336
|
|
|
325
337
|
it "can't fit the box if there is no available space" do
|
|
326
|
-
@frame.remove_area(Geom2D::
|
|
338
|
+
@frame.remove_area(Geom2D::Rectangle(0, 0, 110, 110))
|
|
327
339
|
box = HexaPDF::Layout::Box.create
|
|
328
340
|
refute(@frame.fit(box).success?)
|
|
329
341
|
end
|
|
@@ -388,7 +400,7 @@ describe HexaPDF::Layout::Frame do
|
|
|
388
400
|
# +--------+
|
|
389
401
|
it "works for a region with a hole" do
|
|
390
402
|
frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
|
|
391
|
-
frame.remove_area(Geom2D::
|
|
403
|
+
frame.remove_area(Geom2D::Rectangle(20, 20, 60, 60))
|
|
392
404
|
check_regions(frame, [[0, 100, 100, 20], [0, 100, 20, 100],
|
|
393
405
|
[0, 80, 20, 80], [0, 20, 100, 20]])
|
|
394
406
|
end
|
|
@@ -400,7 +412,7 @@ describe HexaPDF::Layout::Frame do
|
|
|
400
412
|
# +--------+
|
|
401
413
|
it "works for a u-shaped frame" do
|
|
402
414
|
frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
|
|
403
|
-
frame.remove_area(Geom2D::
|
|
415
|
+
frame.remove_area(Geom2D::Rectangle(30, 60, 40, 40))
|
|
404
416
|
check_regions(frame, [[0, 100, 30, 100], [0, 60, 100, 60]])
|
|
405
417
|
end
|
|
406
418
|
|
|
@@ -415,7 +427,7 @@ describe HexaPDF::Layout::Frame do
|
|
|
415
427
|
it "works for a complicated frame" do
|
|
416
428
|
frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
|
|
417
429
|
top_cut = Geom2D::Polygon([20, 100], [20, 80], [40, 80], [40, 90], [60, 90], [60, 100])
|
|
418
|
-
left_cut = Geom2D::
|
|
430
|
+
left_cut = Geom2D::Rectangle(0, 20, 30, 20)
|
|
419
431
|
frame.remove_area(Geom2D::PolygonSet(top_cut, left_cut))
|
|
420
432
|
|
|
421
433
|
check_regions(frame, [[0, 100, 20, 60], [0, 90, 20, 50], [0, 80, 100, 40],
|
|
@@ -24,20 +24,28 @@ describe HexaPDF::Layout::InlineBox do
|
|
|
24
24
|
assert_equal(:top, ibox.valign)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
it "fails if the wrapped box has not width set" do
|
|
28
|
+
box = HexaPDF::Document.new.layout.text("test is not going good")
|
|
29
|
+
assert_raises(HexaPDF::Error) { inline_box(box) }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "fit_wrapped_box" do
|
|
27
34
|
it "automatically fits the provided box into a frame" do
|
|
28
35
|
ibox = inline_box(HexaPDF::Document.new.layout.text("test is going good", width: 20))
|
|
36
|
+
ibox.fit_wrapped_box(nil)
|
|
29
37
|
assert_equal(20, ibox.width)
|
|
30
38
|
assert_equal(45, ibox.height)
|
|
31
39
|
end
|
|
32
40
|
|
|
33
41
|
it "fails if the wrapped box could not be fit" do
|
|
34
42
|
box = HexaPDF::Document.new.layout.text("test is not going good", width: 1)
|
|
35
|
-
assert_raises(HexaPDF::Error) { inline_box(box) }
|
|
43
|
+
assert_raises(HexaPDF::Error) { inline_box(box).fit_wrapped_box(nil) }
|
|
36
44
|
end
|
|
37
45
|
|
|
38
46
|
it "fails if the height is not set explicitly and during fitting" do
|
|
39
47
|
assert_raises(HexaPDF::Error) do
|
|
40
|
-
inline_box(HexaPDF::Layout::Box.create(width: 10))
|
|
48
|
+
inline_box(HexaPDF::Layout::Box.create(width: 10)).fit_wrapped_box(nil)
|
|
41
49
|
end
|
|
42
50
|
end
|
|
43
51
|
end
|
|
@@ -45,7 +53,9 @@ describe HexaPDF::Layout::InlineBox do
|
|
|
45
53
|
it "draws the wrapped box at the correct position" do
|
|
46
54
|
doc = HexaPDF::Document.new
|
|
47
55
|
canvas = doc.pages.add.canvas
|
|
48
|
-
inline_box(doc.layout.text("", width: 20, margin: [15, 10]))
|
|
56
|
+
box = inline_box(doc.layout.text("", width: 20, margin: [15, 10]))
|
|
57
|
+
box.fit_wrapped_box(nil)
|
|
58
|
+
box.draw(canvas, 100, 200)
|
|
49
59
|
assert_equal("q\n1 0 0 1 110 -99785 cm\nQ\n", canvas.contents)
|
|
50
60
|
end
|
|
51
61
|
|
|
@@ -54,6 +64,10 @@ describe HexaPDF::Layout::InlineBox do
|
|
|
54
64
|
refute(HexaPDF::Layout::InlineBox.create(width: 10, height: 15) {}.empty?)
|
|
55
65
|
end
|
|
56
66
|
|
|
67
|
+
it "returns the style of the box" do
|
|
68
|
+
assert_same(@box.box.style, @box.style)
|
|
69
|
+
end
|
|
70
|
+
|
|
57
71
|
describe "valign" do
|
|
58
72
|
it "has a default value of :baseline" do
|
|
59
73
|
assert_equal(:baseline, @box.valign)
|