hexapdf 0.11.9 → 0.13.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 +157 -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 +22 -11
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/form.rb +240 -0
- data/lib/hexapdf/cli/image2pdf.rb +3 -2
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +52 -3
- data/lib/hexapdf/cli/inspect.rb +31 -9
- data/lib/hexapdf/cli/merge.rb +2 -2
- 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 +81 -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 +4 -4
- 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 +5 -5
- data/lib/hexapdf/dictionary_fields.rb +2 -10
- data/lib/hexapdf/document.rb +45 -17
- data/lib/hexapdf/document/files.rb +1 -2
- 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 +2 -2
- 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 +2 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +2 -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 +2 -5
- 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 +2 -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 +3 -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 +4 -3
- 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 +2 -2
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +24 -24
- 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 +4 -3
- 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 +32 -27
- data/lib/hexapdf/parser.rb +69 -6
- data/lib/hexapdf/pdf_array.rb +10 -3
- 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 +30 -22
- 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 +7 -5
- data/lib/hexapdf/tokenizer.rb +5 -4
- data/lib/hexapdf/type.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +7 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +405 -0
- data/lib/hexapdf/type/acro_form/button_field.rb +305 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
- data/lib/hexapdf/type/acro_form/field.rb +250 -17
- data/lib/hexapdf/type/acro_form/form.rb +159 -7
- data/lib/hexapdf/type/acro_form/text_field.rb +187 -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 +4 -3
- 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 +238 -2
- data/lib/hexapdf/type/catalog.rb +23 -3
- 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 +2 -2
- data/lib/hexapdf/type/font.rb +18 -1
- data/lib/hexapdf/type/font_descriptor.rb +2 -2
- data/lib/hexapdf/type/font_simple.rb +4 -2
- data/lib/hexapdf/type/font_true_type.rb +7 -3
- data/lib/hexapdf/type/font_type0.rb +2 -2
- data/lib/hexapdf/type/font_type1.rb +16 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +12 -2
- 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 +5 -3
- 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 +36 -12
- data/lib/hexapdf/type/page_tree_node.rb +37 -16
- data/lib/hexapdf/type/resources.rb +17 -3
- data/lib/hexapdf/type/trailer.rb +4 -6
- 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 +19 -16
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/test/hexapdf/common_tokenizer_tests.rb +6 -1
- data/test/hexapdf/content/common.rb +2 -2
- 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 +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_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_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/layout/test_text_layouter.rb +3 -4
- 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 +16 -4
- data/test/hexapdf/test_object.rb +44 -26
- data/test/hexapdf/test_parser.rb +125 -55
- data/test/hexapdf/test_pdf_array.rb +7 -0
- data/test/hexapdf/test_rectangle.rb +14 -0
- data/test/hexapdf/test_revision.rb +3 -0
- 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 +521 -0
- data/test/hexapdf/type/acro_form/test_button_field.rb +281 -0
- data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
- data/test/hexapdf/type/acro_form/test_field.rb +163 -6
- data/test/hexapdf/type/acro_form/test_form.rb +189 -22
- data/test/hexapdf/type/acro_form/test_text_field.rb +121 -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_simple.rb +2 -1
- data/test/hexapdf/type/test_font_true_type.rb +6 -0
- data/test/hexapdf/type/test_font_type1.rb +8 -0
- data/test/hexapdf/type/test_form.rb +19 -1
- data/test/hexapdf/type/test_image.rb +7 -0
- data/test/hexapdf/type/test_page.rb +45 -7
- data/test/hexapdf/type/test_page_tree_node.rb +62 -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 +15 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -9
- data/test/test_helper.rb +1 -1
- metadata +34 -21
- data/lib/hexapdf/filter/dct_decode.rb +0 -60
|
@@ -8,7 +8,7 @@ describe HexaPDF::Type::Annotations::Text do
|
|
|
8
8
|
before do
|
|
9
9
|
@doc = HexaPDF::Document.new
|
|
10
10
|
@doc.version = '1.5'
|
|
11
|
-
@annot = HexaPDF::Type::Annotations::Text.new({Rect: [0, 0, 1, 1]}, document: @doc)
|
|
11
|
+
@annot = HexaPDF::Type::Annotations::Text.new({Rect: [0, 0, 1, 1]}, document: @doc, oid: 1)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
describe "validation" do
|
|
@@ -22,3 +22,202 @@ describe HexaPDF::Type::Annotations::Widget::AppearanceCharacteristics do
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
|
+
|
|
26
|
+
describe HexaPDF::Type::Annotations::Widget do
|
|
27
|
+
before do
|
|
28
|
+
@doc = HexaPDF::Document.new
|
|
29
|
+
@widget = @doc.wrap({Type: :Annot, Subtype: :Widget})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "form_field" do
|
|
33
|
+
it "works for the field and widget being the same object" do
|
|
34
|
+
@widget[:FT] = :Tx
|
|
35
|
+
@widget[:T] = 'field'
|
|
36
|
+
result = @widget.form_field
|
|
37
|
+
assert_kind_of(HexaPDF::Type::AcroForm::TextField, result)
|
|
38
|
+
assert_same(@widget.data, result.data)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "works for a field with a parent field and the widget being the same object" do
|
|
42
|
+
@widget[:Parent] = {FT: :Tx, T: 'parent', Kids: [@widget]}
|
|
43
|
+
@widget[:T] = 'field'
|
|
44
|
+
result = @widget.form_field
|
|
45
|
+
assert_kind_of(HexaPDF::Type::AcroForm::TextField, result)
|
|
46
|
+
assert_same(@widget.data, result.data)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "works for the widget being in the /Kids array of the field" do
|
|
50
|
+
@widget[:Parent] = {FT: :Tx, T: 'parent', Kids: [@widget]}
|
|
51
|
+
result = @widget.form_field
|
|
52
|
+
assert_kind_of(HexaPDF::Type::AcroForm::TextField, result)
|
|
53
|
+
refute_same(@widget.data, result.data)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "background_color" do
|
|
58
|
+
it "returns the current background color" do
|
|
59
|
+
assert_nil(@widget.background_color)
|
|
60
|
+
@widget[:MK] = {BG: [1]}
|
|
61
|
+
assert_equal([1], @widget.background_color.components)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "sets the color and returns self" do
|
|
65
|
+
assert_same(@widget, @widget.background_color(51))
|
|
66
|
+
assert_equal([0.2], @widget.background_color.components)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "border_style" do
|
|
71
|
+
before do
|
|
72
|
+
@widget[:MK] = {BC: [1, 0, 1]}
|
|
73
|
+
@color = HexaPDF::Content::ColorSpace.prenormalized_device_color([1, 0, 1])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "getter" do
|
|
77
|
+
it "no /Border, /BS or /MK set" do
|
|
78
|
+
@widget.delete(:MK)
|
|
79
|
+
assert_equal([1, nil, :solid, 0, 0], @widget.border_style.to_a)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "no /Border, /BS but with /MK empty" do
|
|
83
|
+
@widget[:MK].delete(:BC)
|
|
84
|
+
assert_equal([1, nil, :solid, 0, 0], @widget.border_style.to_a)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "uses the color from /MK" do
|
|
88
|
+
assert_equal([1, @color, :solid, 0, 0], @widget.border_style.to_a)
|
|
89
|
+
@widget[:MK][:BC] = []
|
|
90
|
+
assert_equal([1, nil, :solid, 0, 0], @widget.border_style.to_a)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "uses the data from /Border" do
|
|
94
|
+
@widget[:Border] = [1, 2, 3, [1, 2]]
|
|
95
|
+
assert_equal([3, @color, [1, 2], 1, 2], @widget.border_style.to_a)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "uses the data from /BS, overriding /Border values" do
|
|
99
|
+
@widget[:Border] = [1, 2, 3, [1, 2]]
|
|
100
|
+
@widget[:BS] = {W: 5, S: :D, D: [5, 6]}
|
|
101
|
+
assert_equal([5, @color, [5, 6], 0, 0], @widget.border_style.to_a)
|
|
102
|
+
|
|
103
|
+
[[:S, :solid], [:D, [5, 6]], [:B, :beveled], [:I, :inset],
|
|
104
|
+
[:U, :underlined], [:Unknown, :solid]].each do |val, result|
|
|
105
|
+
@widget[:BS] = {S: val, D: [5, 6]}
|
|
106
|
+
assert_equal([1, @color, result, 0, 0], @widget.border_style.to_a)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe "setter" do
|
|
112
|
+
it "returns self" do
|
|
113
|
+
assert_equal(@widget, @widget.border_style(width: 1))
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "sets the color" do
|
|
117
|
+
@widget.border_style(color: [1.0, 51, 1.0])
|
|
118
|
+
assert_equal([1, 0.2, 1], @widget[:MK][:BC].value)
|
|
119
|
+
|
|
120
|
+
@widget.border_style(color: :transparent)
|
|
121
|
+
assert_equal([], @widget[:MK][:BC].value)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "sets the width" do
|
|
125
|
+
@widget.border_style(width: 2)
|
|
126
|
+
assert_equal(2, @widget[:BS][:W])
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "sets the style" do
|
|
130
|
+
[[:solid, :S], [[5, 6], :D], [:beveled, :B], [:inset, :I], [:underlined, :U]].each do |val, r|
|
|
131
|
+
@widget.border_style(style: val)
|
|
132
|
+
assert_equal(r, @widget[:BS][:S])
|
|
133
|
+
assert_equal(val, @widget[:BS][:D].value) if r == :D
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "overrides all priorly set values" do
|
|
138
|
+
@widget.border_style(width: 3, style: :inset, color: [1])
|
|
139
|
+
@widget.border_style(width: 5)
|
|
140
|
+
border_style = @widget.border_style
|
|
141
|
+
assert_equal(:solid, border_style.style)
|
|
142
|
+
assert_equal([0], border_style.color.components)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "raises an error for an unknown style" do
|
|
146
|
+
assert_raises(ArgumentError) { @widget.border_style(style: :unknown) }
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe "marker_style" do
|
|
152
|
+
before do
|
|
153
|
+
@chars = %w[4 l 8 u n H S]
|
|
154
|
+
@values = [:check, :circle, :cross, :diamond, :square, :star, 'S']
|
|
155
|
+
@widget[:Parent] = {FT: :Btn}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
describe "style" do
|
|
159
|
+
it "returns the style" do
|
|
160
|
+
@chars.zip(@values) do |char, result|
|
|
161
|
+
@widget[:MK] = {CA: char}
|
|
162
|
+
assert_equal(result, @widget.marker_style.style)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "returns the correct default button style depending on the field" do
|
|
167
|
+
@widget.form_field.initialize_as_check_box
|
|
168
|
+
assert_equal(:check, @widget.marker_style.style)
|
|
169
|
+
@widget.form_field.initialize_as_radio_button
|
|
170
|
+
assert_equal(:circle, @widget.marker_style.style)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "sets the button style" do
|
|
174
|
+
@values.zip(@chars) do |argument, char|
|
|
175
|
+
@widget.marker_style(style: argument)
|
|
176
|
+
assert_equal(char, @widget[:MK][:CA])
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "fails if an invalid argument is provided" do
|
|
181
|
+
assert_raises(ArgumentError) { @widget.marker_style(style: 5) }
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe "size" do
|
|
186
|
+
it "returns the size" do
|
|
187
|
+
@widget.form_field[:DA] = "/F 15 Tf"
|
|
188
|
+
assert_equal(15, @widget.marker_style.size)
|
|
189
|
+
@widget[:DA] = "/F 10 Tf"
|
|
190
|
+
assert_equal(10, @widget.marker_style.size)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "returns the default size if none is set" do
|
|
194
|
+
assert_equal(0, @widget.marker_style.size)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "sets the given size" do
|
|
198
|
+
@widget.marker_style(size: 10)
|
|
199
|
+
assert_equal('/ZaDb 10 Tf 0.0 g', @widget[:DA])
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
describe "color" do
|
|
204
|
+
it "returns the color" do
|
|
205
|
+
@widget.form_field[:DA] = "0 1 0 rg"
|
|
206
|
+
assert_equal([0, 1, 0], @widget.marker_style.color.components)
|
|
207
|
+
@widget[:DA] = "0 0 1 rg"
|
|
208
|
+
assert_equal([0, 0, 1], @widget.marker_style.color.components)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "returns the default color if none is set" do
|
|
212
|
+
assert_equal([0], @widget.marker_style.color.components)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "sets the given color" do
|
|
216
|
+
@widget.marker_style(color: [1.0, 51, 1.0])
|
|
217
|
+
assert_equal([1, 0.2, 1], @widget.marker_style.color.components)
|
|
218
|
+
@widget.marker_style(color: [1.0, 20, 1.0, 1.0])
|
|
219
|
+
assert_equal([1, 0.2, 1, 1], @widget.marker_style.color.components)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
@@ -4,12 +4,57 @@ require 'test_helper'
|
|
|
4
4
|
require 'hexapdf/document'
|
|
5
5
|
require 'hexapdf/type/annotation'
|
|
6
6
|
|
|
7
|
+
describe HexaPDF::Type::Annotation::AppearanceDictionary do
|
|
8
|
+
before do
|
|
9
|
+
@doc = HexaPDF::Document.new
|
|
10
|
+
@ap = @doc.add({N: :n, D: :d, R: :r}, type: :XXAppearanceDictionary)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "resolves the normal appearance" do
|
|
14
|
+
assert_equal(:n, @ap.normal_appearance)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "resolves the rollover appearance" do
|
|
18
|
+
assert_equal(:r, @ap.rollover_appearance)
|
|
19
|
+
@ap.delete(:R)
|
|
20
|
+
assert_equal(:n, @ap.rollover_appearance)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "resolves the down appearance" do
|
|
24
|
+
assert_equal(:d, @ap.down_appearance)
|
|
25
|
+
@ap.delete(:D)
|
|
26
|
+
assert_equal(:n, @ap.down_appearance)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
7
30
|
describe HexaPDF::Type::Annotation do
|
|
8
31
|
before do
|
|
9
32
|
@doc = HexaPDF::Document.new
|
|
10
33
|
@annot = @doc.add({Type: :Annot, F: 0b100011})
|
|
11
34
|
end
|
|
12
35
|
|
|
36
|
+
it "must always be indirect" do
|
|
37
|
+
@annot.must_be_indirect = false
|
|
38
|
+
assert(@annot.must_be_indirect?)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "returns the appearance dictionary" do
|
|
42
|
+
@annot[:AP] = :yes
|
|
43
|
+
assert_equal(:yes, @annot.appearance)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "checks whether an appearance exists" do
|
|
47
|
+
refute(@annot.appearance?)
|
|
48
|
+
@annot[:AP] = {N: {}}
|
|
49
|
+
refute(@annot.appearance?)
|
|
50
|
+
@annot[:AP][:N] = @doc.wrap({}, stream: '')
|
|
51
|
+
assert(@annot.appearance?)
|
|
52
|
+
@annot[:AP][:N] = {okay: @doc.wrap({}, stream: '')}
|
|
53
|
+
assert(@annot.appearance?)
|
|
54
|
+
@annot[:AP][:N][:Off] = :other
|
|
55
|
+
refute(@annot.appearance?)
|
|
56
|
+
end
|
|
57
|
+
|
|
13
58
|
describe "flags" do
|
|
14
59
|
it "returns all flags" do
|
|
15
60
|
assert_equal([:invisible, :hidden, :no_view], @annot.flags)
|
|
@@ -21,6 +21,24 @@ describe HexaPDF::Type::Catalog do
|
|
|
21
21
|
assert_equal(:Pages, pages.type)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
describe "acro_form" do
|
|
25
|
+
it "returns an existing form object" do
|
|
26
|
+
@catalog[:AcroForm] = :test
|
|
27
|
+
assert_equal(:test, @catalog.acro_form)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "returns an existing form object even if create: true" do
|
|
31
|
+
@catalog[:AcroForm] = :test
|
|
32
|
+
assert_equal(:test, @catalog.acro_form(create: true))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "creates a new AcroForm object with defaults if create: true" do
|
|
36
|
+
form = @catalog.acro_form(create: true)
|
|
37
|
+
assert_kind_of(HexaPDF::Type::AcroForm::Form, form)
|
|
38
|
+
assert(form[:DA])
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
24
42
|
describe "validation" do
|
|
25
43
|
it "creates the page tree if necessary" do
|
|
26
44
|
refute(@catalog.validate(auto_correct: false))
|
|
@@ -17,6 +17,11 @@ describe HexaPDF::Type::Font do
|
|
|
17
17
|
@font = @doc.add({Type: :Font, BaseFont: :TestFont, FontDescriptor: fd, ToUnicode: cmap})
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
it "allows setting and returning a font wrapper object" do
|
|
21
|
+
@font.font_wrapper = :fake_wrapper
|
|
22
|
+
assert_equal(:fake_wrapper, @font.font_wrapper)
|
|
23
|
+
end
|
|
24
|
+
|
|
20
25
|
it "must always be an indirect" do
|
|
21
26
|
assert(@font.must_be_indirect?)
|
|
22
27
|
end
|
|
@@ -161,8 +161,9 @@ describe HexaPDF::Type::FontSimple do
|
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
describe "validation" do
|
|
164
|
+
before { assert(@font.validate) }
|
|
165
|
+
|
|
164
166
|
it "validates the existence of required keys" do
|
|
165
|
-
assert(@font.validate)
|
|
166
167
|
@font.delete(:FirstChar)
|
|
167
168
|
refute(@font.validate)
|
|
168
169
|
end
|
|
@@ -16,6 +16,12 @@ describe HexaPDF::Type::FontTrueType do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe "validation" do
|
|
19
|
+
it "ignores some missing fields if the font name is one of the standard PDF fonts" do
|
|
20
|
+
@font[:BaseFont] = :'Arial,Bold'
|
|
21
|
+
[:FirstChar, :LastChar, :Widths, :FontDescriptor].each {|field| @font.delete(field) }
|
|
22
|
+
assert(@font.validate)
|
|
23
|
+
end
|
|
24
|
+
|
|
19
25
|
it "requires that the FontDescriptor key is set" do
|
|
20
26
|
assert(@font.validate)
|
|
21
27
|
@font.delete(:FontDescriptor)
|
|
@@ -57,6 +57,14 @@ describe HexaPDF::Type::FontType1 do
|
|
|
57
57
|
FirstChar: 32, LastChar: 34, Widths: [600, 0, 700]})
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
it "can create a usable font wrapper for the standard fonts" do
|
|
61
|
+
wrapper = @font.font_wrapper
|
|
62
|
+
assert(wrapper)
|
|
63
|
+
assert_same(@font, wrapper.pdf_object)
|
|
64
|
+
assert_equal(@font[:BaseFont], wrapper.wrapped_font.font_name.intern)
|
|
65
|
+
assert_same(wrapper, @font.font_wrapper)
|
|
66
|
+
end
|
|
67
|
+
|
|
60
68
|
describe "encoding" do
|
|
61
69
|
it "returns the the standard font's encoding" do
|
|
62
70
|
@font.delete(:Encoding)
|
|
@@ -49,7 +49,7 @@ describe HexaPDF::Type::Form do
|
|
|
49
49
|
it "creates the resource dictionary if it is not found" do
|
|
50
50
|
resources = @form.resources
|
|
51
51
|
assert_equal(:XXResources, resources.type)
|
|
52
|
-
assert_equal({}, resources.value)
|
|
52
|
+
assert_equal({ProcSet: [:PDF, :Text, :ImageB, :ImageC, :ImageI]}, resources.value)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
it "returns the already used resource dictionary" do
|
|
@@ -82,9 +82,27 @@ describe HexaPDF::Type::Form do
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
describe "canvas" do
|
|
85
|
+
# Asserts that the form's contents contains the operators.
|
|
86
|
+
def assert_operators(form, operators)
|
|
87
|
+
processor = TestHelper::OperatorRecorder.new
|
|
88
|
+
form.process_contents(processor)
|
|
89
|
+
assert_equal(operators, processor.recorded_ops)
|
|
90
|
+
end
|
|
91
|
+
|
|
85
92
|
it "always returns the same Canvas instance" do
|
|
93
|
+
@form[:BBox] = [0, 0, 100, 100]
|
|
86
94
|
canvas = @form.canvas
|
|
87
95
|
assert_same(canvas, @form.canvas)
|
|
96
|
+
assert_operators(@form, [])
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "always moves the origin to the bottom left corner of the bounding box" do
|
|
100
|
+
@form[:BBox] = [-10, -5, 100, 300]
|
|
101
|
+
@form.canvas.line_width = 5
|
|
102
|
+
assert_operators(@form, [[:save_graphics_state],
|
|
103
|
+
[:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
|
|
104
|
+
[:set_line_width, [5]],
|
|
105
|
+
[:restore_graphics_state]])
|
|
88
106
|
end
|
|
89
107
|
|
|
90
108
|
it "fails if the form XObject already has data" do
|
|
@@ -120,6 +120,12 @@ describe HexaPDF::Type::Image do
|
|
|
120
120
|
assert_equal(:other, info.color_space)
|
|
121
121
|
assert_equal(-1, info.components)
|
|
122
122
|
end
|
|
123
|
+
|
|
124
|
+
it "processes the SMask entry" do
|
|
125
|
+
@image[:SMask] = :something
|
|
126
|
+
info = @image.info
|
|
127
|
+
refute(info.writable)
|
|
128
|
+
end
|
|
123
129
|
end
|
|
124
130
|
|
|
125
131
|
describe "write" do
|
|
@@ -182,6 +188,7 @@ describe HexaPDF::Type::Image do
|
|
|
182
188
|
end
|
|
183
189
|
|
|
184
190
|
Dir.glob(File.join(TEST_DATA_DIR, 'images', '*.png')).each do |png_file|
|
|
191
|
+
next if png_file =~ /alpha/
|
|
185
192
|
it "writes #{File.basename(png_file)} correctly as PNG file" do
|
|
186
193
|
image = @doc.images.add(png_file)
|
|
187
194
|
if png_file =~ /greyscale-1bit.png/ # force use of arrays for one image
|
|
@@ -277,7 +277,7 @@ describe HexaPDF::Type::Page do
|
|
|
277
277
|
page = @doc.add({Type: :Page, Parent: @doc.pages.root})
|
|
278
278
|
resources = page.resources
|
|
279
279
|
assert_equal(:XXResources, resources.type)
|
|
280
|
-
assert_equal({}, resources.value)
|
|
280
|
+
assert_equal({ProcSet: [:PDF, :Text, :ImageB, :ImageC, :ImageI]}, resources.value)
|
|
281
281
|
end
|
|
282
282
|
|
|
283
283
|
it "returns the already used resource dictionary" do
|
|
@@ -319,6 +319,13 @@ describe HexaPDF::Type::Page do
|
|
|
319
319
|
end
|
|
320
320
|
end
|
|
321
321
|
|
|
322
|
+
it "returns all ancestor page tree nodes of a page" do
|
|
323
|
+
root = @doc.add({Type: :Pages})
|
|
324
|
+
kid = @doc.add({Type: :Pages, Parent: root})
|
|
325
|
+
page = @doc.add({Type: :Page, Parent: kid})
|
|
326
|
+
assert_equal([kid, root], page.ancestor_nodes)
|
|
327
|
+
end
|
|
328
|
+
|
|
322
329
|
describe "canvas" do
|
|
323
330
|
before do
|
|
324
331
|
@page = @doc.pages.add
|
|
@@ -331,31 +338,36 @@ describe HexaPDF::Type::Page do
|
|
|
331
338
|
@page.canvas(type: :overlay).line_width = 5
|
|
332
339
|
assert_operators(@page, [[:save_graphics_state], [:restore_graphics_state],
|
|
333
340
|
[:save_graphics_state], [:set_line_width, [10]],
|
|
334
|
-
[:restore_graphics_state], [:
|
|
341
|
+
[:restore_graphics_state], [:save_graphics_state],
|
|
342
|
+
[:set_line_width, [5]], [:restore_graphics_state]])
|
|
335
343
|
|
|
336
344
|
@page.canvas(type: :underlay).line_width = 2
|
|
337
345
|
assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
|
|
338
346
|
[:restore_graphics_state], [:save_graphics_state],
|
|
339
347
|
[:set_line_width, [10]],
|
|
340
|
-
[:restore_graphics_state], [:
|
|
348
|
+
[:restore_graphics_state], [:save_graphics_state],
|
|
349
|
+
[:set_line_width, [5]], [:restore_graphics_state]])
|
|
341
350
|
end
|
|
342
351
|
|
|
343
352
|
it "works correctly if invoked on an empty page, using type :underlay in first invocation" do
|
|
344
353
|
@page.canvas(type: :underlay).line_width = 2
|
|
345
354
|
assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
|
|
355
|
+
[:restore_graphics_state], [:save_graphics_state],
|
|
346
356
|
[:restore_graphics_state], [:save_graphics_state],
|
|
347
357
|
[:restore_graphics_state]])
|
|
348
358
|
|
|
349
359
|
@page.canvas.line_width = 10
|
|
350
360
|
assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
|
|
351
361
|
[:restore_graphics_state], [:save_graphics_state],
|
|
352
|
-
[:set_line_width, [10]], [:restore_graphics_state]
|
|
362
|
+
[:set_line_width, [10]], [:restore_graphics_state],
|
|
363
|
+
[:save_graphics_state], [:restore_graphics_state]])
|
|
353
364
|
|
|
354
365
|
@page.canvas(type: :overlay).line_width = 5
|
|
355
366
|
assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
|
|
356
367
|
[:restore_graphics_state], [:save_graphics_state],
|
|
357
368
|
[:set_line_width, [10]],
|
|
358
|
-
[:restore_graphics_state], [:
|
|
369
|
+
[:restore_graphics_state], [:save_graphics_state],
|
|
370
|
+
[:set_line_width, [5]], [:restore_graphics_state]])
|
|
359
371
|
end
|
|
360
372
|
|
|
361
373
|
it "works correctly if invoked on a page with existing contents" do
|
|
@@ -364,13 +376,39 @@ describe HexaPDF::Type::Page do
|
|
|
364
376
|
@page.canvas(type: :overlay).line_width = 5
|
|
365
377
|
assert_operators(@page, [[:save_graphics_state], [:restore_graphics_state],
|
|
366
378
|
[:save_graphics_state], [:set_line_width, [10]],
|
|
367
|
-
[:restore_graphics_state],
|
|
379
|
+
[:restore_graphics_state],
|
|
380
|
+
[:save_graphics_state], [:set_line_width, [5]],
|
|
381
|
+
[:restore_graphics_state]])
|
|
368
382
|
|
|
369
383
|
@page.canvas(type: :underlay).line_width = 2
|
|
370
384
|
assert_operators(@page, [[:save_graphics_state], [:set_line_width, [2]],
|
|
371
385
|
[:restore_graphics_state], [:save_graphics_state],
|
|
372
386
|
[:set_line_width, [10]],
|
|
373
|
-
[:restore_graphics_state],
|
|
387
|
+
[:restore_graphics_state],
|
|
388
|
+
[:save_graphics_state], [:set_line_width, [5]],
|
|
389
|
+
[:restore_graphics_state]])
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
it "works correctly if the page has its origin not at (0,0)" do
|
|
393
|
+
@page.box(:media, [-10, -5, 100, 300])
|
|
394
|
+
@page.canvas(type: :underlay).line_width = 2
|
|
395
|
+
@page.canvas(type: :page).line_width = 2
|
|
396
|
+
@page.canvas(type: :overlay).line_width = 2
|
|
397
|
+
|
|
398
|
+
assert_operators(@page, [[:save_graphics_state],
|
|
399
|
+
[:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
|
|
400
|
+
[:set_line_width, [2]],
|
|
401
|
+
[:restore_graphics_state],
|
|
402
|
+
|
|
403
|
+
[:save_graphics_state],
|
|
404
|
+
[:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
|
|
405
|
+
[:set_line_width, [2]],
|
|
406
|
+
[:restore_graphics_state],
|
|
407
|
+
|
|
408
|
+
[:save_graphics_state],
|
|
409
|
+
[:concatenate_matrix, [1, 0, 0, 1, -10, -5]],
|
|
410
|
+
[:set_line_width, [2]],
|
|
411
|
+
[:restore_graphics_state]])
|
|
374
412
|
end
|
|
375
413
|
|
|
376
414
|
it "fails if the page canvas is requested for a page with existing contents" do
|