hexapdf 0.32.1 → 0.33.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 +76 -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/lib/hexapdf/cli/command.rb +5 -2
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +3 -3
- data/lib/hexapdf/cli.rb +4 -0
- data/lib/hexapdf/composer.rb +104 -52
- data/lib/hexapdf/configuration.rb +44 -39
- data/lib/hexapdf/content/canvas.rb +393 -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 +52 -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 +6 -5
- data/lib/hexapdf/dictionary_fields.rb +42 -14
- 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 +2 -2
- 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 +167 -39
- data/lib/hexapdf/document/pages.rb +3 -2
- data/lib/hexapdf/document.rb +89 -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 +1 -1
- 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 +9 -2
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +18 -4
- data/lib/hexapdf/layout/frame.rb +30 -12
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +1 -0
- data/lib/hexapdf/layout/list_box.rb +17 -1
- data/lib/hexapdf/layout/page_style.rb +4 -4
- data/lib/hexapdf/layout/style.rb +18 -3
- data/lib/hexapdf/layout/table_box.rb +682 -0
- data/lib/hexapdf/layout/text_box.rb +5 -3
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +12 -4
- 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 +8 -8
- 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 +4 -2
- 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/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -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 +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +1 -1
- data/lib/hexapdf/type/cid_font.rb +3 -3
- 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 +1 -1
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +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 +7 -3
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +19 -10
- data/lib/hexapdf/type/page_label.rb +1 -1
- 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/utils/pdf_doc_encoding.rb +1 -1
- 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 +0 -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 +98 -0
- 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 +1 -1
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +14 -14
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +5 -0
- data/test/hexapdf/layout/test_list_box.rb +40 -6
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +50 -0
- data/test/hexapdf/layout/test_table_box.rb +722 -0
- data/test/hexapdf/layout/test_text_box.rb +18 -0
- data/test/hexapdf/layout/test_text_layouter.rb +4 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +1 -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_parser.rb +1 -1
- 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/test_object_stream.rb +9 -3
- data/test/hexapdf/type/test_page.rb +18 -4
- metadata +17 -8
@@ -107,6 +107,14 @@ describe HexaPDF::Layout::TextBox do
|
|
107
107
|
assert_equal([nil, box], box.split(100, 100, @frame))
|
108
108
|
end
|
109
109
|
|
110
|
+
it "works if the box fits exactly (+/- float divergence)" do
|
111
|
+
box = create_box([@inline_box] * 5)
|
112
|
+
box.fit(50, 10, @frame)
|
113
|
+
box.instance_variable_set(:@width, 50.00000000006)
|
114
|
+
box.instance_variable_set(:@height, 10.00000000003)
|
115
|
+
assert_equal([box], box.split(50, 10, @frame))
|
116
|
+
end
|
117
|
+
|
110
118
|
it "splits the box if necessary when using non-flowing text" do
|
111
119
|
box = create_box([@inline_box] * 10)
|
112
120
|
boxes = box.split(50, 10, @frame)
|
@@ -125,6 +133,16 @@ describe HexaPDF::Layout::TextBox do
|
|
125
133
|
assert_equal(box, boxes[0])
|
126
134
|
assert_equal(5, boxes[1].instance_variable_get(:@items).length)
|
127
135
|
end
|
136
|
+
|
137
|
+
it "correctly handles text indentation for split boxes" do
|
138
|
+
[{}, {position: :flow}].each do |styles|
|
139
|
+
box = create_box([@inline_box] * 202, style: {text_indent: 50, **styles})
|
140
|
+
boxes = box.split(100, 100, @frame)
|
141
|
+
assert_equal(107, boxes[1].instance_variable_get(:@items).length)
|
142
|
+
boxes = boxes[1].split(100, 100, @frame)
|
143
|
+
assert_equal(7, boxes[1].instance_variable_get(:@items).length)
|
144
|
+
end
|
145
|
+
end
|
128
146
|
end
|
129
147
|
|
130
148
|
describe "draw" do
|
@@ -419,6 +419,10 @@ describe HexaPDF::Layout::TextLayouter do
|
|
419
419
|
assert(result.remaining_items.empty?)
|
420
420
|
assert_equal(:success, result.status)
|
421
421
|
end
|
422
|
+
|
423
|
+
result = @layouter.fit(boxes([20, 20], [20, 20], [20, 20], [20, 20]), 60, 200,
|
424
|
+
apply_first_text_indent: false)
|
425
|
+
assert_equal([60, 20], result.lines.map(&:width))
|
422
426
|
end
|
423
427
|
|
424
428
|
it "fits using a limited height" do
|
@@ -188,8 +188,11 @@ describe HexaPDF::DictionaryFields do
|
|
188
188
|
["D:19981223-08'00'", [1998, 12, 23, 00, 00, 00, "-08:00"]],
|
189
189
|
["D:199812-08'00'", [1998, 12, 01, 00, 00, 00, "-08:00"]],
|
190
190
|
["D:1998-08'00'", [1998, 01, 01, 00, 00, 00, "-08:00"]],
|
191
|
+
["D:19981223195210Z", [1998, 12, 23, 19, 52, 10, "+00:00"]],
|
192
|
+
["D:19981223195210Z00", [1998, 12, 23, 19, 52, 10, "+00:00"]],
|
193
|
+
["D:19981223195210Z00'00", [1998, 12, 23, 19, 52, 10, "+00:00"]],
|
191
194
|
["D:19981223195210-08", [1998, 12, 23, 19, 52, 10, "-08:00"]], # missing '
|
192
|
-
["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], #
|
195
|
+
["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], # no trailing ', as per PDF 2.0
|
193
196
|
["D:19981223195210-54'00", [1998, 12, 23, 19, 52, 10, "-23:59:59"]], # TZ hour too large
|
194
197
|
["D:19981223195210+10'65", [1998, 12, 23, 19, 52, 10, "+11:05"]], # TZ min too large
|
195
198
|
["D:19982423195210-08'00'", [1998, 12, 23, 19, 52, 10, "-08:00"]], # months too large
|
@@ -240,6 +240,7 @@ describe HexaPDF::Document do
|
|
240
240
|
assert_kind_of(@myclass2, @doc.wrap({Subtype: :Global, Test: "true"}))
|
241
241
|
assert_kind_of(@myclass2, @doc.wrap({Type: :MyClass, S: :TheSecond}))
|
242
242
|
assert_kind_of(@myclass, @doc.wrap({Type: :MyClass, Subtype: :TheThird}))
|
243
|
+
assert_kind_of(HexaPDF::Type::FontTrueType, @doc.wrap({Subtype: :TrueType, BaseFont: :Help}))
|
243
244
|
end
|
244
245
|
|
245
246
|
it "respects the given type/subtype arguments" do
|
data/test/hexapdf/test_filter.rb
CHANGED
@@ -12,6 +12,14 @@ describe HexaPDF::Filter do
|
|
12
12
|
40.times { @str << [rand(2**32)].pack('N') }
|
13
13
|
end
|
14
14
|
|
15
|
+
describe "source_from_proc" do
|
16
|
+
it "returns the whole string, once" do
|
17
|
+
fib = @obj.source_from_proc { @str }
|
18
|
+
assert_equal(@str, collector(fib))
|
19
|
+
assert_equal('', collector(fib))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
15
23
|
describe "source_from_string" do
|
16
24
|
it "doesn't modify the given string" do
|
17
25
|
str = @str.dup
|
@@ -40,6 +40,15 @@ describe HexaPDF::Importer do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
describe "::copy" do
|
44
|
+
it "copies a complete object including references" do
|
45
|
+
obj1 = HexaPDF::Importer.copy(@dest, @obj)
|
46
|
+
obj2 = HexaPDF::Importer.copy(@dest, @obj)
|
47
|
+
refute_same(obj1, obj2)
|
48
|
+
refute_same(obj1[:ref], obj2[:ref])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
43
52
|
describe "import" do
|
44
53
|
it "updates the associated document" do
|
45
54
|
obj = @importer.import(@obj)
|
data/test/hexapdf/test_object.rb
CHANGED
@@ -50,26 +50,37 @@ describe HexaPDF::Object do
|
|
50
50
|
@doc = HexaPDF::Document.new
|
51
51
|
end
|
52
52
|
|
53
|
-
it "
|
53
|
+
it "makes values of wrapped direct objects also direct" do
|
54
54
|
obj = HexaPDF::Object.new(5)
|
55
|
-
assert_same(obj, HexaPDF::Object.make_direct(obj))
|
55
|
+
assert_same(obj, HexaPDF::Object.make_direct(obj, @doc))
|
56
|
+
obj = HexaPDF::Dictionary.new({a: 5, b: HexaPDF::Object.new(:a, oid: 3, document: @doc)})
|
57
|
+
assert_same(obj, HexaPDF::Object.make_direct(obj, @doc))
|
58
|
+
assert_equal(:a, obj[:b])
|
56
59
|
end
|
57
60
|
|
58
61
|
it "works for simple values" do
|
59
62
|
obj = HexaPDF::Object.new(5, oid: 1, document: @doc)
|
60
|
-
assert_same(5, HexaPDF::Object.make_direct(obj))
|
63
|
+
assert_same(5, HexaPDF::Object.make_direct(obj, @doc))
|
61
64
|
end
|
62
65
|
|
63
66
|
it "works for hashes" do
|
64
67
|
obj = HexaPDF::Dictionary.new({a: 5, b: HexaPDF::Object.new(:a, oid: 3, document: @doc)},
|
65
68
|
oid: 1, document: @doc)
|
66
|
-
assert_equal({a: 5, b: :a}, HexaPDF::Object.make_direct(obj))
|
69
|
+
assert_equal({a: 5, b: :a}, HexaPDF::Object.make_direct(obj, @doc))
|
67
70
|
end
|
68
71
|
|
69
72
|
it "works for arrays" do
|
70
73
|
obj = HexaPDF::PDFArray.new([:b, HexaPDF::Object.new(:a, oid: 3, document: @doc)],
|
71
74
|
oid: 1, document: @doc)
|
72
|
-
assert_equal([:b, :a], HexaPDF::Object.make_direct(obj))
|
75
|
+
assert_equal([:b, :a], HexaPDF::Object.make_direct(obj, @doc))
|
76
|
+
end
|
77
|
+
|
78
|
+
it "resolves references" do
|
79
|
+
@doc.add(:Test, oid: 1)
|
80
|
+
obj = HexaPDF::PDFArray.new([HexaPDF::Reference.new(1, 0)],
|
81
|
+
oid: 2, document: @doc)
|
82
|
+
assert_equal([:Test], HexaPDF::Object.make_direct(obj, @doc))
|
83
|
+
assert(@doc.object(1).null?)
|
73
84
|
end
|
74
85
|
end
|
75
86
|
|
data/test/hexapdf/test_parser.rb
CHANGED
@@ -609,7 +609,7 @@ describe HexaPDF::Parser do
|
|
609
609
|
end
|
610
610
|
|
611
611
|
it "serially parses the contents" do
|
612
|
-
create_parser("1 0 obj\n5\
|
612
|
+
create_parser("1 0 obj\n5 endobj\n1 0 obj\n6\nendobj\ntrailer\n<</Size 1>>")
|
613
613
|
assert_equal(6, @parser.load_object(@xref).value)
|
614
614
|
end
|
615
615
|
|
data/test/hexapdf/test_stream.rb
CHANGED
@@ -31,6 +31,13 @@ describe HexaPDF::StreamData do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
describe "fiber" do
|
34
|
+
it "returns a duplicate for a FiberDoubleForString source" do
|
35
|
+
source = HexaPDF::Filter.source_from_string("str")
|
36
|
+
fiber = HexaPDF::StreamData.new(source).fiber
|
37
|
+
assert_equal("str", fiber.resume)
|
38
|
+
refute_same(source, fiber)
|
39
|
+
end
|
40
|
+
|
34
41
|
it "returns a fiber for a Proc source" do
|
35
42
|
s = HexaPDF::StreamData.new(proc { :source })
|
36
43
|
assert_equal(:source, s.fiber.resume)
|
data/test/hexapdf/test_writer.rb
CHANGED
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
|
|
40
40
|
219
|
41
41
|
%%EOF
|
42
42
|
3 0 obj
|
43
|
-
<</Producer(HexaPDF version 0.
|
43
|
+
<</Producer(HexaPDF version 0.33.0)>>
|
44
44
|
endobj
|
45
45
|
xref
|
46
46
|
3 1
|
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
|
|
72
72
|
141
|
73
73
|
%%EOF
|
74
74
|
6 0 obj
|
75
|
-
<</Producer(HexaPDF version 0.
|
75
|
+
<</Producer(HexaPDF version 0.33.0)>>
|
76
76
|
endobj
|
77
77
|
2 0 obj
|
78
78
|
<</Length 10>>stream
|
@@ -214,7 +214,7 @@ describe HexaPDF::Writer do
|
|
214
214
|
<</Type/Page/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<<>>>>
|
215
215
|
endobj
|
216
216
|
5 0 obj
|
217
|
-
<</Producer(HexaPDF version 0.
|
217
|
+
<</Producer(HexaPDF version 0.33.0)>>
|
218
218
|
endobj
|
219
219
|
4 0 obj
|
220
220
|
<</Root 1 0 R/Info 5 0 R/Size 6/Type/XRef/W[1 1 2]/Index[0 6]/Filter/FlateDecode/DecodeParms<</Columns 4/Predictor 12>>/Length 33>>stream
|
@@ -467,12 +467,20 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
|
|
467
467
|
it "calculates the font size based on the rectangle height and border width" do
|
468
468
|
@generator.create_appearances
|
469
469
|
assert_operators(@widget[:AP][:N].stream,
|
470
|
-
[:set_font_and_size, [:F1,
|
470
|
+
[:set_font_and_size, [:F1, 13.235294]],
|
471
471
|
range: 5)
|
472
472
|
@widget.border_style(width: 2, color: :transparent)
|
473
473
|
@generator.create_appearances
|
474
474
|
assert_operators(@widget[:AP][:N].stream,
|
475
|
-
[:set_font_and_size, [:F1, 11.
|
475
|
+
[:set_font_and_size, [:F1, 11.764706]],
|
476
|
+
range: 5)
|
477
|
+
end
|
478
|
+
|
479
|
+
it "shrinks the font size if necessary to fit the rectangle width" do
|
480
|
+
@field.field_value = "This is some arbitrary, long text"
|
481
|
+
@generator.create_appearances
|
482
|
+
assert_operators(@widget[:AP][:N].stream,
|
483
|
+
[:set_font_and_size, [:F1, 6.909955]],
|
476
484
|
range: 5)
|
477
485
|
end
|
478
486
|
|
@@ -573,7 +581,7 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
|
|
573
581
|
assert_format("2, 3, #{style}, 0, \"E\", true",
|
574
582
|
[[:set_device_rgb_non_stroking_color, [style % 2, 0.0, 0.0]],
|
575
583
|
[:begin_text],
|
576
|
-
[:set_text_matrix, [1, 0, 0, 1, 2, 3.
|
584
|
+
[:set_text_matrix, [1, 0, 0, 1, 2, 3.183272]],
|
577
585
|
[:show_text, [result]]], 6..9)
|
578
586
|
end
|
579
587
|
end
|
@@ -598,10 +606,10 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
|
|
598
606
|
[:append_rectangle, [1, 1, 98, 9.25]],
|
599
607
|
[:clip_path_non_zero],
|
600
608
|
[:end_path],
|
601
|
-
[:set_font_and_size, [:F1, 6.
|
609
|
+
[:set_font_and_size, [:F1, 6.801471]],
|
602
610
|
[:set_device_rgb_non_stroking_color, [1.0, 0.0, 0.0]],
|
603
611
|
[:begin_text],
|
604
|
-
[:set_text_matrix, [1, 0, 0, 1, 2, 3.
|
612
|
+
[:set_text_matrix, [1, 0, 0, 1, 2, 3.183272]],
|
605
613
|
[:show_text, ["Text"]],
|
606
614
|
[:end_text],
|
607
615
|
[:restore_graphics_state],
|
@@ -42,11 +42,12 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it "finds the root fields" do
|
45
|
-
@doc.pages.add[:Annots] = [{
|
46
|
-
|
45
|
+
@doc.pages.add[:Annots] = [{Subtype: :Widget, Rect: [0, 0, 0, 0], FT: :Tx},
|
46
|
+
{Subtype: :Widget, Rect: [0, 0, 0, 0], FT: :Tx, Parent: {FT: :Tx}}]
|
47
|
+
@doc.pages.add[:Annots] = [{Subtype: :Widget, Rect: [0, 0, 0, 0]}]
|
47
48
|
@doc.pages.add
|
48
49
|
|
49
|
-
result = [{FT: :Tx}, {FT: :
|
50
|
+
result = [{Subtype: :Widget, Rect: [0, 0, 0, 0], FT: :Tx}, {FT: :Tx}]
|
50
51
|
root_fields = @acro_form.find_root_fields
|
51
52
|
assert_equal(result, root_fields.map(&:value))
|
52
53
|
assert_kind_of(HexaPDF::Type::AcroForm::TextField, root_fields[0])
|
@@ -23,9 +23,14 @@ describe HexaPDF::Type::ObjectStream do
|
|
23
23
|
before do
|
24
24
|
@doc = Object.new
|
25
25
|
@doc.instance_variable_set(:@version, '1.5')
|
26
|
-
|
27
|
-
|
26
|
+
@doc.define_singleton_method(:revisions) do
|
27
|
+
rev1 = Object.new
|
28
|
+
def rev1.trailer; {Encrypt: HexaPDF::Object.new({}, oid: 10)}; end
|
29
|
+
rev2 = Object.new
|
30
|
+
def rev2.trailer; {Encrypt: HexaPDF::Object.new({}, oid: 9)}; end
|
31
|
+
@revisions ||= [rev1, rev2]
|
28
32
|
end
|
33
|
+
@doc.define_singleton_method(:trailer) { revisions.last.trailer }
|
29
34
|
@obj = HexaPDF::Type::ObjectStream.new({N: 2, First: 8}, oid: 1, document: @doc,
|
30
35
|
stream: "1 0 5 2 5 [1 2]")
|
31
36
|
end
|
@@ -96,8 +101,9 @@ describe HexaPDF::Type::ObjectStream do
|
|
96
101
|
assert_equal("", @obj.stream)
|
97
102
|
end
|
98
103
|
|
99
|
-
it "doesn't allow
|
104
|
+
it "doesn't allow an encryption dictionary to be compressed" do
|
100
105
|
@obj.add_object(@doc.trailer[:Encrypt])
|
106
|
+
@obj.add_object(@doc.revisions[0].trailer[:Encrypt])
|
101
107
|
@obj.write_objects(@revision)
|
102
108
|
assert_equal(0, @obj.value[:N])
|
103
109
|
assert_equal(0, @obj.value[:First])
|
@@ -557,7 +557,7 @@ describe HexaPDF::Type::Page do
|
|
557
557
|
@page = @doc.pages.add
|
558
558
|
@appearance = @doc.add({Type: :XObject, Subtype: :Form, BBox: [-10, -5, 50, 20]}, stream: "")
|
559
559
|
@annot1 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [100, 100, 160, 125], AP: {N: @appearance}})
|
560
|
-
@annot2 = @doc.add({Rect: [10, 10, 70, 35], AP: {N: @appearance}})
|
560
|
+
@annot2 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [10, 10, 70, 35], AP: {N: @appearance}})
|
561
561
|
@page[:Annots] = [@annot1, @annot2]
|
562
562
|
@canvas = @page.canvas(type: :overlay)
|
563
563
|
end
|
@@ -591,6 +591,18 @@ describe HexaPDF::Type::Page do
|
|
591
591
|
assert(@annot2.null?)
|
592
592
|
end
|
593
593
|
|
594
|
+
it "gracefully handles invalid /Annot key values" do
|
595
|
+
@page[:Annots] << nil << @doc.add({}, stream: '')
|
596
|
+
result = @page.flatten_annotations
|
597
|
+
assert(result.empty?)
|
598
|
+
assert(@annot1.null?)
|
599
|
+
assert(@annot2.null?)
|
600
|
+
|
601
|
+
@page[:Annots] = @doc.add({}, stream: '')
|
602
|
+
result = @page.flatten_annotations
|
603
|
+
assert(result.empty?)
|
604
|
+
end
|
605
|
+
|
594
606
|
it "only deletes the widget annotation of a form field even if it is embedded in the field object" do
|
595
607
|
form = @doc.acro_form(create: true)
|
596
608
|
field = form.create_text_field('test')
|
@@ -631,7 +643,7 @@ describe HexaPDF::Type::Page do
|
|
631
643
|
[:restore_graphics_state]])
|
632
644
|
end
|
633
645
|
|
634
|
-
it "ignores annotations without
|
646
|
+
it "ignores annotations without appearance stream" do
|
635
647
|
@annot1.delete(:AP)
|
636
648
|
result = @page.flatten_annotations
|
637
649
|
assert_equal([@annot1], result)
|
@@ -708,10 +720,12 @@ describe HexaPDF::Type::Page do
|
|
708
720
|
it "yields each annotation" do
|
709
721
|
page = @doc.pages.add
|
710
722
|
annot1 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [100, 100, 160, 125]})
|
711
|
-
annot2 = @doc.add({Rect: [10, 10, 70, 35]})
|
712
|
-
|
723
|
+
annot2 = @doc.add({Subtype: :Unknown, Rect: [10, 10, 70, 35]})
|
724
|
+
not_an_annot = @doc.add({}, stream: '')
|
725
|
+
page[:Annots] = [not_an_annot, annot1, nil, annot2]
|
713
726
|
|
714
727
|
annotations = page.each_annotation.to_a
|
728
|
+
assert_equal(2, annotations.size)
|
715
729
|
assert_equal([100, 100, 160, 125], annotations[0][:Rect])
|
716
730
|
assert_equal(:Annot, annotations[0].type)
|
717
731
|
assert_equal(:Annot, annotations[1].type)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hexapdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.33.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Leitner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdparse
|
@@ -36,14 +36,20 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '0.
|
39
|
+
version: '0.4'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.4.1
|
40
43
|
type: :runtime
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
47
|
- - "~>"
|
45
48
|
- !ruby/object:Gem::Version
|
46
|
-
version: '0.
|
49
|
+
version: '0.4'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.4.1
|
47
53
|
- !ruby/object:Gem::Dependency
|
48
54
|
name: openssl
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -292,6 +298,7 @@ files:
|
|
292
298
|
- examples/022-outline.rb
|
293
299
|
- examples/023-images.rb
|
294
300
|
- examples/024-digital-signatures.rb
|
301
|
+
- examples/025-table_box.rb
|
295
302
|
- examples/emoji-smile.png
|
296
303
|
- examples/emoji-wink.png
|
297
304
|
- examples/machupicchu.jpg
|
@@ -430,6 +437,7 @@ files:
|
|
430
437
|
- lib/hexapdf/layout/numeric_refinements.rb
|
431
438
|
- lib/hexapdf/layout/page_style.rb
|
432
439
|
- lib/hexapdf/layout/style.rb
|
440
|
+
- lib/hexapdf/layout/table_box.rb
|
433
441
|
- lib/hexapdf/layout/text_box.rb
|
434
442
|
- lib/hexapdf/layout/text_fragment.rb
|
435
443
|
- lib/hexapdf/layout/text_layouter.rb
|
@@ -682,6 +690,7 @@ files:
|
|
682
690
|
- test/hexapdf/layout/test_list_box.rb
|
683
691
|
- test/hexapdf/layout/test_page_style.rb
|
684
692
|
- test/hexapdf/layout/test_style.rb
|
693
|
+
- test/hexapdf/layout/test_table_box.rb
|
685
694
|
- test/hexapdf/layout/test_text_box.rb
|
686
695
|
- test/hexapdf/layout/test_text_fragment.rb
|
687
696
|
- test/hexapdf/layout/test_text_layouter.rb
|
@@ -760,7 +769,7 @@ licenses:
|
|
760
769
|
- AGPL-3.0
|
761
770
|
- Nonstandard
|
762
771
|
metadata: {}
|
763
|
-
post_install_message:
|
772
|
+
post_install_message:
|
764
773
|
rdoc_options: []
|
765
774
|
require_paths:
|
766
775
|
- lib
|
@@ -775,8 +784,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
775
784
|
- !ruby/object:Gem::Version
|
776
785
|
version: '0'
|
777
786
|
requirements: []
|
778
|
-
rubygems_version: 3.
|
779
|
-
signing_key:
|
787
|
+
rubygems_version: 3.5.0.dev
|
788
|
+
signing_key:
|
780
789
|
specification_version: 4
|
781
790
|
summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
782
791
|
test_files: []
|