hexapdf 0.10.0 → 0.11.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 +33 -0
- data/CONTRIBUTERS +1 -1
- data/Rakefile +35 -50
- data/VERSION +1 -1
- data/lib/hexapdf/cli.rb +4 -0
- data/lib/hexapdf/cli/command.rb +6 -2
- data/lib/hexapdf/cli/image2pdf.rb +141 -0
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +32 -2
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +130 -0
- data/lib/hexapdf/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +7 -1
- data/lib/hexapdf/content/canvas.rb +2 -2
- data/lib/hexapdf/content/graphic_object/arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/dictionary.rb +11 -3
- data/lib/hexapdf/dictionary_fields.rb +32 -3
- data/lib/hexapdf/document.rb +7 -3
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +21 -1
- data/lib/hexapdf/document/pages.rb +2 -2
- data/lib/hexapdf/encryption/standard_security_handler.rb +2 -2
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +2 -2
- data/lib/hexapdf/font/true_type/table/os2.rb +4 -4
- data/lib/hexapdf/font/true_type_wrapper.rb +16 -16
- data/lib/hexapdf/font/type1_wrapper.rb +16 -16
- data/lib/hexapdf/font_loader.rb +2 -0
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -0
- data/lib/hexapdf/font_loader/standard14.rb +5 -0
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/layout/box.rb +2 -2
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/style.rb +50 -24
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +2 -2
- data/lib/hexapdf/layout/text_layouter.rb +14 -10
- data/lib/hexapdf/name_tree_node.rb +3 -3
- data/lib/hexapdf/number_tree_node.rb +3 -3
- data/lib/hexapdf/pdf_array.rb +207 -0
- data/lib/hexapdf/rectangle.rb +12 -12
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +6 -4
- data/lib/hexapdf/task/optimize.rb +3 -3
- data/lib/hexapdf/type.rb +2 -0
- data/lib/hexapdf/type/acro_form.rb +51 -0
- data/lib/hexapdf/type/acro_form/field.rb +129 -0
- data/lib/hexapdf/type/acro_form/form.rb +124 -0
- 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/annotation.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -0
- data/lib/hexapdf/type/annotations/link.rb +4 -15
- data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -1
- data/lib/hexapdf/type/annotations/text.rb +3 -6
- data/lib/hexapdf/type/annotations/widget.rb +90 -0
- data/lib/hexapdf/type/catalog.rb +12 -9
- data/lib/hexapdf/type/cid_font.rb +3 -3
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +5 -2
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +2 -2
- data/lib/hexapdf/type/graphics_state_parameter.rb +11 -6
- data/lib/hexapdf/type/icon_fit.rb +58 -0
- data/lib/hexapdf/type/image.rb +14 -8
- data/lib/hexapdf/type/info.rb +2 -1
- data/lib/hexapdf/type/page.rb +4 -4
- data/lib/hexapdf/type/page_tree_node.rb +3 -7
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +4 -4
- data/lib/hexapdf/type/viewer_preferences.rb +7 -4
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/man/man1/hexapdf.1 +77 -8
- data/test/hexapdf/content/test_canvas.rb +2 -2
- data/test/hexapdf/content/test_processor.rb +3 -3
- data/test/hexapdf/document/test_files.rb +4 -4
- data/test/hexapdf/document/test_fonts.rb +13 -1
- data/test/hexapdf/document/test_images.rb +6 -6
- data/test/hexapdf/document/test_pages.rb +8 -8
- data/test/hexapdf/encryption/test_security_handler.rb +7 -7
- data/test/hexapdf/encryption/test_standard_security_handler.rb +5 -5
- data/test/hexapdf/font/test_true_type_wrapper.rb +2 -2
- data/test/hexapdf/font_loader/test_from_configuration.rb +4 -0
- data/test/hexapdf/font_loader/test_standard14.rb +10 -0
- data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
- data/test/hexapdf/image_loader/test_png.rb +3 -3
- data/test/hexapdf/layout/test_box.rb +2 -2
- data/test/hexapdf/layout/test_frame.rb +1 -1
- data/test/hexapdf/layout/test_image_box.rb +1 -1
- data/test/hexapdf/layout/test_style.rb +18 -13
- data/test/hexapdf/layout/test_text_box.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +11 -6
- data/test/hexapdf/task/test_dereference.rb +2 -2
- data/test/hexapdf/task/test_optimize.rb +11 -11
- data/test/hexapdf/test_composer.rb +1 -1
- data/test/hexapdf/test_dictionary.rb +10 -2
- data/test/hexapdf/test_dictionary_fields.rb +27 -3
- data/test/hexapdf/test_document.rb +16 -15
- data/test/hexapdf/test_importer.rb +4 -4
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_pdf_array.rb +162 -0
- data/test/hexapdf/test_rectangle.rb +3 -5
- data/test/hexapdf/test_serializer.rb +1 -1
- data/test/hexapdf/test_stream.rb +1 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_field.rb +85 -0
- data/test/hexapdf/type/acro_form/test_form.rb +69 -0
- data/test/hexapdf/type/annotations/test_text.rb +2 -6
- data/test/hexapdf/type/annotations/test_widget.rb +24 -0
- data/test/hexapdf/type/test_annotation.rb +1 -1
- data/test/hexapdf/type/test_catalog.rb +1 -1
- data/test/hexapdf/type/test_cid_font.rb +3 -3
- data/test/hexapdf/type/test_font.rb +2 -2
- data/test/hexapdf/type/test_font_descriptor.rb +2 -1
- data/test/hexapdf/type/test_font_simple.rb +3 -3
- data/test/hexapdf/type/test_font_true_type.rb +6 -6
- data/test/hexapdf/type/test_font_type0.rb +5 -5
- data/test/hexapdf/type/test_font_type1.rb +8 -8
- data/test/hexapdf/type/test_font_type3.rb +4 -4
- data/test/hexapdf/type/test_image.rb +16 -12
- data/test/hexapdf/type/test_page.rb +11 -11
- data/test/hexapdf/type/test_page_tree_node.rb +20 -20
- data/test/hexapdf/type/test_resources.rb +6 -6
- data/test/hexapdf/type/test_trailer.rb +5 -2
- data/test/hexapdf/type/test_xref_stream.rb +1 -0
- data/test/hexapdf/utils/test_sorted_tree_node.rb +35 -35
- metadata +23 -7
- data/test/hexapdf/type/annotations/test_link.rb +0 -19
@@ -117,10 +117,15 @@ describe HexaPDF::Layout::TextLayouter::SimpleTextSegmentation do
|
|
117
117
|
assert_equal(20, result.size)
|
118
118
|
[1, 3, 5, 7, 9, 11, 13, 17, 19].each do |index|
|
119
119
|
assert_penalty(result[index],
|
120
|
-
HexaPDF::Layout::TextLayouter::Penalty::
|
120
|
+
HexaPDF::Layout::TextLayouter::Penalty::PARAGRAPH_BREAK)
|
121
|
+
assert_equal([], result[index].item.items)
|
122
|
+
assert(result[index].item.items.frozen?)
|
123
|
+
assert_same(frag.style, result[index].item.style)
|
121
124
|
end
|
122
|
-
assert_penalty(result[15],
|
123
|
-
|
125
|
+
assert_penalty(result[15], HexaPDF::Layout::TextLayouter::Penalty::LINE_BREAK)
|
126
|
+
assert_equal([], result[15].item.items)
|
127
|
+
assert(result[15].item.items.frozen?)
|
128
|
+
assert_same(frag.style, result[15].item.style)
|
124
129
|
end
|
125
130
|
|
126
131
|
it "insert a standard penalty after a hyphen" do
|
@@ -389,9 +394,9 @@ describe HexaPDF::Layout::TextLayouter do
|
|
389
394
|
|
390
395
|
it "handles text indentation" do
|
391
396
|
items = boxes([20, 20], [20, 20], [20, 20]) +
|
392
|
-
[HexaPDF::Layout::TextLayouter::Penalty::
|
397
|
+
[penalty(HexaPDF::Layout::TextLayouter::Penalty::PARAGRAPH_BREAK)] +
|
393
398
|
boxes([40, 20]) + [glue(20)] +
|
394
|
-
boxes(*([[20, 20]] * 4)) + [HexaPDF::Layout::TextLayouter::Penalty::
|
399
|
+
boxes(*([[20, 20]] * 4)) + [penalty(HexaPDF::Layout::TextLayouter::Penalty::LINE_BREAK)] +
|
395
400
|
boxes(*([[20, 20]] * 4))
|
396
401
|
@style.text_indent = 20
|
397
402
|
|
@@ -429,7 +434,7 @@ describe HexaPDF::Layout::TextLayouter do
|
|
429
434
|
assert_equal(140, result.height)
|
430
435
|
end
|
431
436
|
|
432
|
-
it "handles empty lines" do
|
437
|
+
it "handles empty lines if the break penalties don't have an item" do
|
433
438
|
items = boxes([20, 20]) + [penalty(-5000)] + boxes([30, 20]) + [penalty(-5000)] * 2 +
|
434
439
|
boxes([20, 20]) + [penalty(-5000)] * 2
|
435
440
|
result = @layouter.fit(items, 30, 100)
|
@@ -14,8 +14,8 @@ describe HexaPDF::Task::Dereference do
|
|
14
14
|
len = @doc.add(5)
|
15
15
|
str = @doc.add(@doc.wrap({Length: len}, stream: ''))
|
16
16
|
@doc.trailer[:Test] = str
|
17
|
-
pages = @doc.wrap(Type: :Pages)
|
18
|
-
pages.add_page(@doc.wrap(Type: :Page))
|
17
|
+
pages = @doc.wrap({Type: :Pages})
|
18
|
+
pages.add_page(@doc.wrap({Type: :Page}))
|
19
19
|
@doc.trailer[:Test2] = pages
|
20
20
|
@doc.trailer[:InvalidRef] = HexaPDF::Reference.new(5000, 2)
|
21
21
|
|
@@ -16,9 +16,9 @@ describe HexaPDF::Task::Optimize do
|
|
16
16
|
@obj1 = @doc.add(@doc.wrap({Optional: :Optional}, type: TestType))
|
17
17
|
@doc.trailer[:Test] = @doc.wrap(@obj1)
|
18
18
|
@doc.revisions.add
|
19
|
-
@obj2 = @doc.add(Type: :UsedEntry)
|
20
|
-
@obj3 = @doc.add(Unused: @obj2)
|
21
|
-
@obj4 = @doc.add(Test: :Test)
|
19
|
+
@obj2 = @doc.add({Type: :UsedEntry})
|
20
|
+
@obj3 = @doc.add({Unused: @obj2})
|
21
|
+
@obj4 = @doc.add({Test: :Test})
|
22
22
|
@obj1[:Test] = @doc.wrap(@obj4, type: TestType)
|
23
23
|
end
|
24
24
|
|
@@ -62,7 +62,7 @@ describe HexaPDF::Task::Optimize do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
it "compacts and deletes object streams" do
|
65
|
-
@doc.add(Type: :ObjStm)
|
65
|
+
@doc.add({Type: :ObjStm})
|
66
66
|
@doc.task(:optimize, compact: true, object_streams: :delete)
|
67
67
|
assert_no_objstms
|
68
68
|
assert_default_deleted
|
@@ -85,8 +85,8 @@ describe HexaPDF::Task::Optimize do
|
|
85
85
|
|
86
86
|
describe "object_streams" do
|
87
87
|
it "generates object streams" do
|
88
|
-
objstm = @doc.add(Type: :ObjStm)
|
89
|
-
xref = @doc.add(Type: :XRef)
|
88
|
+
objstm = @doc.add({Type: :ObjStm})
|
89
|
+
xref = @doc.add({Type: :XRef})
|
90
90
|
210.times { @doc.add(5) }
|
91
91
|
@doc.task(:optimize, object_streams: :generate)
|
92
92
|
assert_objstms_generated
|
@@ -97,8 +97,8 @@ describe HexaPDF::Task::Optimize do
|
|
97
97
|
end
|
98
98
|
|
99
99
|
it "deletes object and xref streams" do
|
100
|
-
@doc.add(Type: :ObjStm)
|
101
|
-
@doc.add(Type: :XRef)
|
100
|
+
@doc.add({Type: :ObjStm})
|
101
|
+
@doc.add({Type: :XRef})
|
102
102
|
@doc.task(:optimize, object_streams: :delete, xref_streams: :delete)
|
103
103
|
assert_no_objstms
|
104
104
|
assert_no_xrefstms
|
@@ -106,7 +106,7 @@ describe HexaPDF::Task::Optimize do
|
|
106
106
|
end
|
107
107
|
|
108
108
|
it "deletes object and generates xref streams" do
|
109
|
-
@doc.add(Type: :ObjStm)
|
109
|
+
@doc.add({Type: :ObjStm})
|
110
110
|
@doc.task(:optimize, object_streams: :delete, xref_streams: :generate)
|
111
111
|
assert_no_objstms
|
112
112
|
assert_xrefstms_generated
|
@@ -122,13 +122,13 @@ describe HexaPDF::Task::Optimize do
|
|
122
122
|
end
|
123
123
|
|
124
124
|
it "reuses an xref stream in generatation mode" do
|
125
|
-
@doc.add(Type: :XRef)
|
125
|
+
@doc.add({Type: :XRef})
|
126
126
|
@doc.task(:optimize, xref_streams: :generate)
|
127
127
|
assert_xrefstms_generated
|
128
128
|
end
|
129
129
|
|
130
130
|
it "deletes xref streams" do
|
131
|
-
@doc.add(Type: :XRef)
|
131
|
+
@doc.add({Type: :XRef})
|
132
132
|
@doc.task(:optimize, xref_streams: :delete)
|
133
133
|
assert_no_xrefstms
|
134
134
|
assert_default_deleted
|
@@ -194,6 +194,7 @@ describe HexaPDF::Dictionary do
|
|
194
194
|
describe "validate_fields" do
|
195
195
|
before do
|
196
196
|
@test_class.define_field(:Inherited, type: [Array, Symbol], required: true, indirect: false)
|
197
|
+
@test_class.define_field(:AllowedValues, type: Integer, allowed_values: [1, 5])
|
197
198
|
@obj = @test_class.new({Array: [], Inherited: :symbol}, document: self)
|
198
199
|
end
|
199
200
|
|
@@ -241,6 +242,13 @@ describe HexaPDF::Dictionary do
|
|
241
242
|
assert(@obj.validate(auto_correct: true))
|
242
243
|
end
|
243
244
|
|
245
|
+
it "checks whether the value is an allowed one" do
|
246
|
+
@obj.value[:AllowedValues] = 7
|
247
|
+
refute(@obj.validate(auto_correct: false))
|
248
|
+
@obj.value[:AllowedValues] = 1
|
249
|
+
assert(@obj.validate(auto_correct: false))
|
250
|
+
end
|
251
|
+
|
244
252
|
it "checks whether a field needs to be indirect w/wo auto_correct" do
|
245
253
|
@obj.value[:Inherited] = HexaPDF::Object.new(:test, oid: 1)
|
246
254
|
refute(@obj.validate(auto_correct: false))
|
@@ -252,7 +260,7 @@ describe HexaPDF::Dictionary do
|
|
252
260
|
assert(@obj.validate(auto_correct: true))
|
253
261
|
assert_equal(1, @obj.value[:TestClass].oid)
|
254
262
|
|
255
|
-
@obj.value[:TestClass] = HexaPDF::Object.new(Inherited: :symbol)
|
263
|
+
@obj.value[:TestClass] = HexaPDF::Object.new({Inherited: :symbol})
|
256
264
|
assert(@obj.validate(auto_correct: true))
|
257
265
|
assert_equal(1, @obj.value[:TestClass].oid)
|
258
266
|
end
|
@@ -319,7 +327,7 @@ describe HexaPDF::Dictionary do
|
|
319
327
|
describe "empty?" do
|
320
328
|
it "returns true if the dictionary contains no entries" do
|
321
329
|
assert(HexaPDF::Dictionary.new({}).empty?)
|
322
|
-
refute(HexaPDF::Dictionary.new(x: 5).empty?)
|
330
|
+
refute(HexaPDF::Dictionary.new({x: 5}).empty?)
|
323
331
|
end
|
324
332
|
end
|
325
333
|
end
|
@@ -11,7 +11,9 @@ describe HexaPDF::DictionaryFields do
|
|
11
11
|
|
12
12
|
describe "Field" do
|
13
13
|
before do
|
14
|
-
@field = self.class::Field.new([:Integer, self.class::PDFByteString], true,
|
14
|
+
@field = self.class::Field.new([:Integer, self.class::PDFByteString], required: true,
|
15
|
+
default: 500, indirect: false, allowed_values: [500, 1],
|
16
|
+
version: '1.2')
|
15
17
|
HexaPDF::GlobalConfiguration['object.type_map'][:Integer] = Integer
|
16
18
|
end
|
17
19
|
|
@@ -25,6 +27,7 @@ describe HexaPDF::DictionaryFields do
|
|
25
27
|
assert_equal(500, @field.default)
|
26
28
|
assert_equal(false, @field.indirect)
|
27
29
|
assert_equal('1.2', @field.version)
|
30
|
+
assert_equal([500, 1], @field.allowed_values)
|
28
31
|
end
|
29
32
|
|
30
33
|
it "maps string types to constants" do
|
@@ -71,7 +74,7 @@ describe HexaPDF::DictionaryFields do
|
|
71
74
|
|
72
75
|
it "allows conversion from a Dictionary" do
|
73
76
|
@doc.expect(:wrap, :data, [HexaPDF::Dictionary, Hash])
|
74
|
-
@field.convert(HexaPDF::Dictionary.new(Test: :value), @doc)
|
77
|
+
@field.convert(HexaPDF::Dictionary.new({Test: :value}), @doc)
|
75
78
|
@doc.verify
|
76
79
|
end
|
77
80
|
|
@@ -86,7 +89,28 @@ describe HexaPDF::DictionaryFields do
|
|
86
89
|
it "doesn't allow conversion to a Stream subclass from Hash or Dictionary" do
|
87
90
|
@field = self.class::Field.new(HexaPDF::Stream)
|
88
91
|
refute(@field.convert({}, @doc))
|
89
|
-
refute(@field.convert(HexaPDF::Dictionary.new(Test: :value), @doc))
|
92
|
+
refute(@field.convert(HexaPDF::Dictionary.new({Test: :value}), @doc))
|
93
|
+
end
|
94
|
+
|
95
|
+
it "doesn't allow conversion from nil" do
|
96
|
+
refute(@field.convert(nil, @doc))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "ArrayConverter" do
|
101
|
+
before do
|
102
|
+
@field = self.class::Field.new(HexaPDF::PDFArray)
|
103
|
+
@doc = Minitest::Mock.new
|
104
|
+
end
|
105
|
+
|
106
|
+
it "additionally adds Array as allowed type" do
|
107
|
+
assert(@field.type.include?(Array))
|
108
|
+
end
|
109
|
+
|
110
|
+
it "allows conversion from an array" do
|
111
|
+
@doc.expect(:wrap, :data, [[1, 2], {type: HexaPDF::PDFArray}])
|
112
|
+
@field.convert([1, 2], @doc)
|
113
|
+
@doc.verify
|
90
114
|
end
|
91
115
|
|
92
116
|
it "doesn't allow conversion from nil" do
|
@@ -282,7 +282,8 @@ describe HexaPDF::Document do
|
|
282
282
|
it "uses a suitable default type if no special type is specified" do
|
283
283
|
assert_instance_of(HexaPDF::Object, @doc.wrap(5))
|
284
284
|
assert_instance_of(HexaPDF::Stream, @doc.wrap({a: 5}, stream: ''))
|
285
|
-
assert_instance_of(HexaPDF::Dictionary, @doc.wrap(a: 5))
|
285
|
+
assert_instance_of(HexaPDF::Dictionary, @doc.wrap({a: 5}))
|
286
|
+
assert_instance_of(HexaPDF::PDFArray, @doc.wrap([1, 2]))
|
286
287
|
end
|
287
288
|
|
288
289
|
it "returns an object of type HexaPDF::Object" do
|
@@ -327,12 +328,12 @@ describe HexaPDF::Document do
|
|
327
328
|
end
|
328
329
|
|
329
330
|
it "uses the type/subtype information in the hash that should be wrapped" do
|
330
|
-
assert_kind_of(@myclass, @doc.wrap(Type: :MyClass))
|
331
|
-
refute_kind_of(@myclass2, @doc.wrap(Subtype: :TheSecond))
|
332
|
-
refute_kind_of(@myclass2, @doc.wrap(Subtype: :Global))
|
333
|
-
assert_kind_of(@myclass2, @doc.wrap(Subtype: :Global, Test: "true"))
|
334
|
-
assert_kind_of(@myclass2, @doc.wrap(Type: :MyClass, S: :TheSecond))
|
335
|
-
assert_kind_of(@myclass, @doc.wrap(Type: :MyClass, Subtype: :TheThird))
|
331
|
+
assert_kind_of(@myclass, @doc.wrap({Type: :MyClass}))
|
332
|
+
refute_kind_of(@myclass2, @doc.wrap({Subtype: :TheSecond}))
|
333
|
+
refute_kind_of(@myclass2, @doc.wrap({Subtype: :Global}))
|
334
|
+
assert_kind_of(@myclass2, @doc.wrap({Subtype: :Global, Test: "true"}))
|
335
|
+
assert_kind_of(@myclass2, @doc.wrap({Type: :MyClass, S: :TheSecond}))
|
336
|
+
assert_kind_of(@myclass, @doc.wrap({Type: :MyClass, Subtype: :TheThird}))
|
336
337
|
end
|
337
338
|
|
338
339
|
it "respects the given type/subtype arguments" do
|
@@ -367,14 +368,14 @@ describe HexaPDF::Document do
|
|
367
368
|
|
368
369
|
it "recursively unwraps hashes" do
|
369
370
|
assert_equal({a: 5, b: 10, c: [200], d: [200]},
|
370
|
-
@io_doc.unwrap(a: 5, b: HexaPDF::Reference.new(1, 0),
|
371
|
-
|
372
|
-
|
371
|
+
@io_doc.unwrap({a: 5, b: HexaPDF::Reference.new(1, 0),
|
372
|
+
c: [HexaPDF::Reference.new(2, 0)],
|
373
|
+
d: [HexaPDF::Reference.new(2, 0)]}))
|
373
374
|
end
|
374
375
|
|
375
376
|
it "recursively unwraps PDF objects" do
|
376
|
-
assert_equal({a: 10}, @io_doc.unwrap(@io_doc.wrap(a: HexaPDF::Reference.new(1, 0))))
|
377
|
-
value = {a: HexaPDF::Object.new(b: HexaPDF::Object.new(10))}
|
377
|
+
assert_equal({a: 10}, @io_doc.unwrap(@io_doc.wrap({a: HexaPDF::Reference.new(1, 0)})))
|
378
|
+
value = {a: HexaPDF::Object.new({b: HexaPDF::Object.new(10)})}
|
378
379
|
assert_equal({a: {b: 10}}, @doc.unwrap(value))
|
379
380
|
end
|
380
381
|
|
@@ -383,7 +384,7 @@ describe HexaPDF::Document do
|
|
383
384
|
obj2 = @doc.add({})
|
384
385
|
obj1.value[2] = obj2
|
385
386
|
obj2.value[1] = obj1
|
386
|
-
assert_raises(HexaPDF::Error) { @doc.unwrap(a: obj1) }
|
387
|
+
assert_raises(HexaPDF::Error) { @doc.unwrap({a: obj1}) }
|
387
388
|
end
|
388
389
|
end
|
389
390
|
|
@@ -444,7 +445,7 @@ describe HexaPDF::Document do
|
|
444
445
|
end
|
445
446
|
|
446
447
|
it "validates indirect objects" do
|
447
|
-
obj = @doc.add(Type: :Catalog)
|
448
|
+
obj = @doc.add({Type: :Catalog})
|
448
449
|
refute(@doc.validate(auto_correct: false))
|
449
450
|
|
450
451
|
called = false
|
@@ -462,7 +463,7 @@ describe HexaPDF::Document do
|
|
462
463
|
doc = HexaPDF::Document.new
|
463
464
|
doc.pages.add.delete(:Resources)
|
464
465
|
page = doc.pages.add
|
465
|
-
page[:Annots] = [doc.add(Type: :Annot, Subtype: :Link, Rect: [0, 0, 1, 1], H: :Z)]
|
466
|
+
page[:Annots] = [doc.add({Type: :Annot, Subtype: :Link, Rect: [0, 0, 1, 1], H: :Z})]
|
466
467
|
doc.write(io, validate: false)
|
467
468
|
doc = HexaPDF::Document.new(io: io)
|
468
469
|
doc.pages[0] # force loading of the first page
|
@@ -22,10 +22,10 @@ describe HexaPDF::Importer do
|
|
22
22
|
before do
|
23
23
|
@source = HexaPDF::Document.new
|
24
24
|
obj = @source.add("test")
|
25
|
-
@hash = @source.wrap(key: "value")
|
26
|
-
@obj = @source.add(hash: @hash, array: ["one", "two"],
|
27
|
-
|
28
|
-
|
25
|
+
@hash = @source.wrap({key: "value"})
|
26
|
+
@obj = @source.add({hash: @hash, array: ["one", "two"],
|
27
|
+
ref: HexaPDF::Reference.new(obj.oid, obj.gen),
|
28
|
+
others: [:symbol, 5, 5.5, nil, true, false]})
|
29
29
|
@source.pages.add
|
30
30
|
@source.pages.root[:Rotate] = 90
|
31
31
|
@dest = HexaPDF::Document.new
|
data/test/hexapdf/test_object.rb
CHANGED
@@ -167,7 +167,7 @@ describe HexaPDF::Object do
|
|
167
167
|
|
168
168
|
describe "deep_copy" do
|
169
169
|
it "creates an independent object" do
|
170
|
-
obj = HexaPDF::Object.new(a: "mystring", b: HexaPDF::Reference.new(1, 0), c: 5)
|
170
|
+
obj = HexaPDF::Object.new({a: "mystring", b: HexaPDF::Reference.new(1, 0), c: 5})
|
171
171
|
copy = obj.deep_copy
|
172
172
|
refute_equal(copy, obj)
|
173
173
|
assert_equal(copy.value, obj.value)
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'hexapdf/pdf_array'
|
5
|
+
require 'hexapdf/reference'
|
6
|
+
require 'hexapdf/dictionary'
|
7
|
+
|
8
|
+
describe HexaPDF::PDFArray do
|
9
|
+
def deref(obj)
|
10
|
+
if obj.kind_of?(HexaPDF::Reference)
|
11
|
+
HexaPDF::Object.new('deref', oid: obj.oid, gen: obj.gen)
|
12
|
+
else
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(obj)
|
18
|
+
HexaPDF::Object.new(obj, oid: 1)
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete(_obj)
|
22
|
+
end
|
23
|
+
|
24
|
+
def wrap(obj, type:)
|
25
|
+
type.new(obj, document: self)
|
26
|
+
end
|
27
|
+
|
28
|
+
before do
|
29
|
+
@array = HexaPDF::PDFArray.new([1, HexaPDF::Object.new(:data), HexaPDF::Reference.new(1, 0),
|
30
|
+
HexaPDF::Dictionary.new({a: 'b'})], document: self)
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "after_data_change" do
|
34
|
+
it "uses an empty array if nil is provided" do
|
35
|
+
array = HexaPDF::PDFArray.new(nil)
|
36
|
+
assert_equal([], array.value)
|
37
|
+
end
|
38
|
+
it "fails if the value is not an array" do
|
39
|
+
assert_raises(ArgumentError) { HexaPDF::PDFArray.new(:Name) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "[]" do
|
44
|
+
it "allows retrieving values by index" do
|
45
|
+
assert_equal(1, @array[0])
|
46
|
+
end
|
47
|
+
|
48
|
+
it "allows retrieving values by start/length" do
|
49
|
+
assert_equal([1, :data], @array[0, 2])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "allows retrieving values by range" do
|
53
|
+
assert_equal([1, :data], @array[0..1])
|
54
|
+
end
|
55
|
+
|
56
|
+
it "fetches the value out of a HexaPDF::Object" do
|
57
|
+
assert_equal(:data, @array[1])
|
58
|
+
end
|
59
|
+
|
60
|
+
it "resolves references and stores the resolved object in place of the reference" do
|
61
|
+
assert_equal('deref', @array[2])
|
62
|
+
assert_kind_of(HexaPDF::Object, @array.value[2])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "[]=" do
|
67
|
+
it "directly stores the value if the stored value is no HexaPDF::Object" do
|
68
|
+
@array[0] = 2
|
69
|
+
assert_equal(2, @array.value[0])
|
70
|
+
end
|
71
|
+
|
72
|
+
it "stores the value in an existing HexaPDF::Object but only if it is not such an object" do
|
73
|
+
@array[1] = [4, 5]
|
74
|
+
assert_equal([4, 5], @array.value[1].value)
|
75
|
+
|
76
|
+
@array[1] = temp = HexaPDF::Object.new(:other)
|
77
|
+
assert_equal(temp, @array.value[1])
|
78
|
+
end
|
79
|
+
|
80
|
+
it "doesn't store the value inside the existing object for subclasses of HexaPDF::Object" do
|
81
|
+
@array[3] = [4, 5]
|
82
|
+
assert_equal([4, 5], @array.value[3])
|
83
|
+
end
|
84
|
+
|
85
|
+
it "doesn't store the value inside for HexaPDF::Reference objects" do
|
86
|
+
@array[1] = HexaPDF::Reference.new(5, 0)
|
87
|
+
assert_kind_of(HexaPDF::Reference, @array.value[1])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "allows getting multiple values at once" do
|
92
|
+
assert_equal([1, :data, @array[3]], @array.values_at(0, 1, 3))
|
93
|
+
end
|
94
|
+
|
95
|
+
it "allows adding values to the end" do
|
96
|
+
@array << 5
|
97
|
+
assert_equal(5, @array[4])
|
98
|
+
end
|
99
|
+
|
100
|
+
it "allows inserting values like Array#insert" do
|
101
|
+
@array.insert(1, :a, :b)
|
102
|
+
assert_equal([1, :a, :b, :data], @array[0, 4])
|
103
|
+
end
|
104
|
+
|
105
|
+
it "allows deleting values at a certain index" do
|
106
|
+
@array.delete_at(2)
|
107
|
+
assert_equal([1, :data, @array[2]], @array[0, 5])
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "slice!" do
|
111
|
+
it "allows deleting a single element" do
|
112
|
+
@array.slice!(2)
|
113
|
+
assert_equal([1, :data, @array[2]], @array[0, 5])
|
114
|
+
end
|
115
|
+
|
116
|
+
it "allows deleting elements given by start/length" do
|
117
|
+
@array.slice!(1, 2)
|
118
|
+
assert_equal([1, @array[1]], @array[0, 5])
|
119
|
+
end
|
120
|
+
|
121
|
+
it "allows deleting elements given a range" do
|
122
|
+
@array.slice!(1..2)
|
123
|
+
assert_equal([1, @array[1]], @array[0, 5])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it "allows deleting elements that are selected using a block" do
|
128
|
+
@array.reject! {|item| item == :data }
|
129
|
+
assert_equal([1, "deref", @array[2]], @array[0, 5])
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "index" do
|
133
|
+
it "allows getting the index of an element" do
|
134
|
+
assert_equal(2, @array.index("deref"))
|
135
|
+
end
|
136
|
+
|
137
|
+
it "allows getting the index of the first element for which a block returns true" do
|
138
|
+
assert_equal(2, @array.index {|item| item == "deref" })
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
it "returns the length of the array" do
|
143
|
+
assert_equal(4, @array.length)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "allows checking for emptiness" do
|
147
|
+
refute(@array.empty?)
|
148
|
+
@array.slice!(0, 5)
|
149
|
+
assert(@array.empty?)
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "each" do
|
153
|
+
it "iterates over all elements in the dictionary" do
|
154
|
+
data = [1, :data, "deref", @array[3]]
|
155
|
+
@array.each {|value| assert_equal(data.shift, value) }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
it "can be converted to a simple array" do
|
160
|
+
assert_equal(@array.value, @array.to_ary)
|
161
|
+
end
|
162
|
+
end
|