hexapdf 0.10.0 → 0.11.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 +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
|