hexapdf 0.11.9 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|