hexapdf 0.44.0 → 0.46.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 +106 -47
- data/examples/019-acro_form.rb +5 -0
- data/examples/027-composer_optional_content.rb +6 -4
- data/examples/030-pdfa.rb +12 -11
- data/lib/hexapdf/cli/inspect.rb +5 -0
- data/lib/hexapdf/composer.rb +23 -1
- data/lib/hexapdf/configuration.rb +8 -0
- data/lib/hexapdf/content/canvas.rb +3 -3
- data/lib/hexapdf/content/canvas_composer.rb +1 -0
- data/lib/hexapdf/digital_signature/cms_handler.rb +31 -3
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +9 -1
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +5 -1
- data/lib/hexapdf/document/layout.rb +63 -30
- data/lib/hexapdf/document.rb +24 -2
- data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
- data/lib/hexapdf/importer.rb +15 -5
- data/lib/hexapdf/layout/box.rb +48 -36
- data/lib/hexapdf/layout/column_box.rb +3 -11
- data/lib/hexapdf/layout/container_box.rb +4 -4
- data/lib/hexapdf/layout/frame.rb +7 -6
- data/lib/hexapdf/layout/inline_box.rb +17 -23
- data/lib/hexapdf/layout/list_box.rb +27 -42
- data/lib/hexapdf/layout/page_style.rb +23 -16
- data/lib/hexapdf/layout/style.rb +5 -5
- data/lib/hexapdf/layout/table_box.rb +14 -10
- data/lib/hexapdf/layout/text_box.rb +60 -36
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +7 -8
- data/lib/hexapdf/parser.rb +5 -1
- data/lib/hexapdf/rectangle.rb +4 -4
- data/lib/hexapdf/revisions.rb +1 -1
- data/lib/hexapdf/stream.rb +3 -3
- data/lib/hexapdf/tokenizer.rb +3 -2
- data/lib/hexapdf/type/acro_form/button_field.rb +2 -0
- data/lib/hexapdf/type/acro_form/choice_field.rb +2 -0
- data/lib/hexapdf/type/acro_form/field.rb +8 -0
- data/lib/hexapdf/type/acro_form/form.rb +2 -1
- data/lib/hexapdf/type/acro_form/text_field.rb +2 -0
- data/lib/hexapdf/type/form.rb +2 -2
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/content/test_canvas_composer.rb +13 -8
- data/test/hexapdf/digital_signature/common.rb +66 -84
- data/test/hexapdf/digital_signature/signing/test_default_handler.rb +7 -0
- data/test/hexapdf/digital_signature/signing/test_signed_data_creator.rb +9 -0
- data/test/hexapdf/digital_signature/test_cms_handler.rb +41 -1
- data/test/hexapdf/digital_signature/test_handler.rb +2 -1
- data/test/hexapdf/document/test_layout.rb +44 -5
- data/test/hexapdf/layout/test_box.rb +23 -5
- data/test/hexapdf/layout/test_frame.rb +21 -2
- data/test/hexapdf/layout/test_inline_box.rb +17 -28
- data/test/hexapdf/layout/test_list_box.rb +8 -8
- data/test/hexapdf/layout/test_page_style.rb +7 -2
- data/test/hexapdf/layout/test_table_box.rb +8 -1
- data/test/hexapdf/layout/test_text_box.rb +51 -29
- data/test/hexapdf/layout/test_text_layouter.rb +0 -3
- data/test/hexapdf/test_composer.rb +14 -5
- data/test/hexapdf/test_document.rb +27 -0
- data/test/hexapdf/test_importer.rb +17 -0
- data/test/hexapdf/test_revisions.rb +54 -41
- data/test/hexapdf/test_serializer.rb +1 -0
- data/test/hexapdf/type/acro_form/test_form.rb +9 -0
- metadata +2 -2
@@ -65,13 +65,13 @@ describe HexaPDF::Layout::ListBox do
|
|
65
65
|
describe "fit" do
|
66
66
|
[:default, :flow].each do |position|
|
67
67
|
it "respects the set initial width, position #{position}" do
|
68
|
-
box = create_box(children: @text_boxes[0, 2], width:
|
69
|
-
check_box(box,
|
68
|
+
box = create_box(children: @text_boxes[0, 2], width: 55, style: {position: position})
|
69
|
+
check_box(box, 55, 80)
|
70
70
|
end
|
71
71
|
|
72
72
|
it "respects the set initial height, position #{position}" do
|
73
|
-
box = create_box(children: @text_boxes[0, 2], height:
|
74
|
-
check_box(box, 100,
|
73
|
+
box = create_box(children: @text_boxes[0, 2], height: 55, style: {position: position})
|
74
|
+
check_box(box, 100, 55)
|
75
75
|
end
|
76
76
|
|
77
77
|
it "respects the set initial height even when it doesn't fit completely" do
|
@@ -123,7 +123,7 @@ describe HexaPDF::Layout::ListBox do
|
|
123
123
|
|
124
124
|
it "fails if not even a part of the first list item fits" do
|
125
125
|
box = create_box(children: @text_boxes[0, 2], height: 5)
|
126
|
-
check_box(box, 100,
|
126
|
+
check_box(box, 100, 5, status: :failure)
|
127
127
|
end
|
128
128
|
|
129
129
|
it "fails for unknown marker types" do
|
@@ -134,13 +134,13 @@ describe HexaPDF::Layout::ListBox do
|
|
134
134
|
|
135
135
|
describe "split" do
|
136
136
|
it "splits before a list item if no part of it will fit" do
|
137
|
-
box = create_box(children: @text_boxes[0,
|
138
|
-
assert(box.fit(100,
|
137
|
+
box = create_box(children: @text_boxes[0, 3])
|
138
|
+
assert(box.fit(100, 22, @frame).overflow?)
|
139
139
|
box_a, box_b = box.split
|
140
140
|
assert_same(box, box_a)
|
141
141
|
assert_equal(:show_first_marker, box_b.split_box?)
|
142
142
|
assert_equal(1, box_a.instance_variable_get(:@results)[0].box_fitter.fit_results.size)
|
143
|
-
assert_equal(
|
143
|
+
assert_equal(2, box_b.children.size)
|
144
144
|
assert_equal(2, box_b.start_number)
|
145
145
|
end
|
146
146
|
|
@@ -44,8 +44,13 @@ describe HexaPDF::Layout::PageStyle do
|
|
44
44
|
|
45
45
|
it "works when no template is set" do
|
46
46
|
style = HexaPDF::Layout::PageStyle.new
|
47
|
-
|
48
|
-
|
47
|
+
page1 = style.create_page(@doc)
|
48
|
+
frame1 = style.frame
|
49
|
+
assert_equal("", page1.contents)
|
50
|
+
assert_equal(523.275591, style.frame.width)
|
51
|
+
|
52
|
+
page2 = style.create_page(@doc)
|
53
|
+
refute_same(frame1, style.frame)
|
49
54
|
end
|
50
55
|
|
51
56
|
it "creates a default frame if none is set beforehand or during template execution" do
|
@@ -116,7 +116,14 @@ describe HexaPDF::Layout::TableBox::Cell do
|
|
116
116
|
assert_equal(12, cell.preferred_height)
|
117
117
|
end
|
118
118
|
|
119
|
-
it "doesn't fit
|
119
|
+
it "doesn't fit children that are too big" do
|
120
|
+
cell = create_cell(children: HexaPDF::Layout::Box.create(width: 300, height: 20))
|
121
|
+
assert(cell.fit(100, 100, @frame).failure?)
|
122
|
+
cell = create_cell(children: [HexaPDF::Layout::Box.create(width: 300, height: 20)])
|
123
|
+
assert(cell.fit(100, 100, @frame).failure?)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "doesn't fit anything if the available width or height are too small even if there are no children" do
|
120
127
|
cell = create_cell(children: nil)
|
121
128
|
assert(cell.fit(10, 100, @frame).failure?)
|
122
129
|
assert(cell.fit(100, 10, @frame).failure?)
|
@@ -42,31 +42,32 @@ describe HexaPDF::Layout::TextBox do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it "respects the set width and height" do
|
45
|
-
box = create_box([@inline_box], width:
|
45
|
+
box = create_box([@inline_box] * 5, width: 44, height: 50,
|
46
|
+
style: {padding: 10, text_align: :right, text_valign: :bottom})
|
46
47
|
assert(box.fit(100, 100, @frame).success?)
|
47
|
-
assert_equal(
|
48
|
+
assert_equal(44, box.width)
|
48
49
|
assert_equal(50, box.height)
|
49
|
-
assert_equal([10], box.instance_variable_get(:@result).lines.map(&:width))
|
50
|
+
assert_equal([20, 20, 10], box.instance_variable_get(:@result).lines.map(&:width))
|
50
51
|
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
53
|
+
describe "style option last_line_gap" do
|
54
|
+
it "is taken into account" do
|
55
|
+
box = create_box([@inline_box] * 5, style: {last_line_gap: true, line_spacing: :double})
|
56
|
+
assert(box.fit(100, 100, @frame).success?)
|
57
|
+
assert_equal(50, box.width)
|
58
|
+
assert_equal(20, box.height)
|
59
|
+
end
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
it "will have no effect for fixed-height boxes" do
|
62
|
+
box = create_box([@inline_box] * 5, height: 40, style: {last_line_gap: true, line_spacing: :double})
|
63
|
+
assert(box.fit(100, 100, @frame).success?)
|
64
|
+
assert_equal(50, box.width)
|
65
|
+
assert_equal(40, box.height)
|
66
|
+
end
|
66
67
|
end
|
67
68
|
|
68
|
-
it "uses the whole available width when aligning to the center or
|
69
|
-
[:center, :right].each do |align|
|
69
|
+
it "uses the whole available width when aligning to the center, right or justified" do
|
70
|
+
[:center, :right, :justify].each do |align|
|
70
71
|
box = create_box([@inline_box], style: {text_align: align})
|
71
72
|
assert(box.fit(100, 100, @frame).success?)
|
72
73
|
assert_equal(100, box.width)
|
@@ -103,6 +104,33 @@ describe HexaPDF::Layout::TextBox do
|
|
103
104
|
assert(box.fit(100, 100, @frame).success?)
|
104
105
|
end
|
105
106
|
|
107
|
+
describe "position :flow" do
|
108
|
+
it "fits into the frame's outline" do
|
109
|
+
@frame.remove_area(Geom2D::Rectangle(0, 80, 20, 20))
|
110
|
+
@frame.remove_area(Geom2D::Rectangle(80, 70, 20, 20))
|
111
|
+
box = create_box([@inline_box] * 20, style: {position: :flow})
|
112
|
+
assert(box.fit(100, 100, @frame).success?)
|
113
|
+
assert_equal(100, box.width)
|
114
|
+
assert_equal(30, box.height)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "respects a set initial height" do
|
118
|
+
box = create_box([@inline_box] * 20, height: 13, style: {position: :flow})
|
119
|
+
assert(box.fit(100, 100, @frame).overflow?)
|
120
|
+
assert_equal(100, box.width)
|
121
|
+
assert_equal(13, box.height)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "respects top/bottom padding/border" do
|
125
|
+
@frame.remove_area(Geom2D::Rectangle(0, 80, 20, 20))
|
126
|
+
box = create_box([@inline_box] * 20, style: {position: :flow, padding: 10, border: {width: 2}})
|
127
|
+
assert(box.fit(100, 100, @frame).success?)
|
128
|
+
assert_equal(124, box.width)
|
129
|
+
assert_equal(54, box.height)
|
130
|
+
assert_equal([80, 100, 20], box.instance_variable_get(:@result).lines.map(&:width))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
106
134
|
it "fails if no item of the text box fits due to the width" do
|
107
135
|
box = create_box([@inline_box])
|
108
136
|
assert(box.fit(5, 20, @frame).failure?)
|
@@ -150,15 +178,12 @@ describe HexaPDF::Layout::TextBox do
|
|
150
178
|
assert_operators(@canvas.contents, [[:save_graphics_state],
|
151
179
|
[:restore_graphics_state],
|
152
180
|
[:save_graphics_state],
|
153
|
-
[:
|
154
|
-
[:save_graphics_state],
|
155
|
-
[:append_rectangle, [0, 0, 10, 10]],
|
181
|
+
[:append_rectangle, [5, 10, 10, 10]],
|
156
182
|
[:clip_path_non_zero],
|
157
183
|
[:end_path],
|
158
|
-
[:append_rectangle, [
|
184
|
+
[:append_rectangle, [5.5, 10.5, 9.0, 9.0]],
|
159
185
|
[:stroke_path],
|
160
186
|
[:restore_graphics_state],
|
161
|
-
[:restore_graphics_state],
|
162
187
|
[:save_graphics_state],
|
163
188
|
[:restore_graphics_state]])
|
164
189
|
end
|
@@ -167,21 +192,18 @@ describe HexaPDF::Layout::TextBox do
|
|
167
192
|
@frame.remove_area(Geom2D::Rectangle(0, 0, 40, 100))
|
168
193
|
box = create_box([@inline_box], style: {position: :flow, border: {width: 1}})
|
169
194
|
box.fit(60, 100, @frame)
|
170
|
-
box.draw(@canvas,
|
195
|
+
box.draw(@canvas, 40, 88)
|
171
196
|
assert_operators(@canvas.contents, [[:save_graphics_state],
|
172
|
-
[:append_rectangle, [40,
|
197
|
+
[:append_rectangle, [40, 88, 12, 12]],
|
173
198
|
[:clip_path_non_zero],
|
174
199
|
[:end_path],
|
175
|
-
[:append_rectangle, [40.5,
|
200
|
+
[:append_rectangle, [40.5, 88.5, 11.0, 11.0]],
|
176
201
|
[:stroke_path],
|
177
202
|
[:restore_graphics_state],
|
178
203
|
[:save_graphics_state],
|
179
204
|
[:restore_graphics_state],
|
180
205
|
[:save_graphics_state],
|
181
206
|
[:concatenate_matrix, [1, 0, 0, 1, 41, 89]],
|
182
|
-
[:save_graphics_state],
|
183
|
-
[:concatenate_matrix, [1, 0, 0, 1, 0, 0]],
|
184
|
-
[:restore_graphics_state],
|
185
207
|
[:restore_graphics_state],
|
186
208
|
[:save_graphics_state],
|
187
209
|
[:restore_graphics_state]])
|
@@ -812,11 +812,8 @@ describe HexaPDF::Layout::TextLayouter do
|
|
812
812
|
[:restore_graphics_state],
|
813
813
|
[:save_graphics_state],
|
814
814
|
[:concatenate_matrix, [1, 0, 0, 1, 10, -40]],
|
815
|
-
[:save_graphics_state],
|
816
|
-
[:concatenate_matrix, [1, 0, 0, 1, 0, 0]],
|
817
815
|
[:set_line_width, [2]],
|
818
816
|
[:restore_graphics_state],
|
819
|
-
[:restore_graphics_state],
|
820
817
|
[:save_graphics_state],
|
821
818
|
[:restore_graphics_state]])
|
822
819
|
end
|
@@ -119,6 +119,13 @@ describe HexaPDF::Composer do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
describe "styles" do
|
123
|
+
it "delegates to layout.styles" do
|
124
|
+
@composer.styles(base: {font_size: 30}, other: {font_size: 40})
|
125
|
+
assert_equal([:base, :other], @composer.document.layout.styles.keys)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
122
129
|
describe "page_style" do
|
123
130
|
it "returns the page style if no argument or block is given" do
|
124
131
|
page_style = @composer.page_style(:default)
|
@@ -225,8 +232,9 @@ describe HexaPDF::Composer do
|
|
225
232
|
first_page_contents = @composer.canvas.contents
|
226
233
|
@composer.draw_box(create_box(height: 400))
|
227
234
|
|
228
|
-
box = create_box
|
229
|
-
box.define_singleton_method(:
|
235
|
+
box = create_box
|
236
|
+
box.define_singleton_method(:fit_content) {|*| fit_result.overflow! }
|
237
|
+
box.define_singleton_method(:split_content) do |*|
|
230
238
|
[box, HexaPDF::Layout::Box.new(height: 100) {}]
|
231
239
|
end
|
232
240
|
@composer.draw_box(box)
|
@@ -235,7 +243,7 @@ describe HexaPDF::Composer do
|
|
235
243
|
[:concatenate_matrix, [1, 0, 0, 1, 36, 405.889764]],
|
236
244
|
[:restore_graphics_state],
|
237
245
|
[:save_graphics_state],
|
238
|
-
[:concatenate_matrix, [1, 0, 0, 1, 36,
|
246
|
+
[:concatenate_matrix, [1, 0, 0, 1, 36, 36]],
|
239
247
|
[:restore_graphics_state]])
|
240
248
|
assert_operators(@composer.canvas.contents,
|
241
249
|
[[:save_graphics_state],
|
@@ -273,9 +281,10 @@ describe HexaPDF::Composer do
|
|
273
281
|
box = create_box(height: 400)
|
274
282
|
assert_same(box, @composer.draw_box(box))
|
275
283
|
|
276
|
-
box = create_box(height: 400)
|
277
284
|
split_box = create_box(height: 100)
|
278
|
-
box
|
285
|
+
box = create_box
|
286
|
+
box.define_singleton_method(:fit_content) {|*| fit_result.overflow! }
|
287
|
+
box.define_singleton_method(:split_content) {|*| [box, split_box] }
|
279
288
|
assert_same(split_box, @composer.draw_box(box))
|
280
289
|
end
|
281
290
|
|
@@ -568,4 +568,31 @@ describe HexaPDF::Document do
|
|
568
568
|
it "can be inspected and the output is not too large" do
|
569
569
|
assert_match(/HexaPDF::Document:\d+/, @doc.inspect)
|
570
570
|
end
|
571
|
+
|
572
|
+
describe "duplicate" do
|
573
|
+
it "creates an in-memory copy" do
|
574
|
+
doc = HexaPDF::Document.new
|
575
|
+
doc.pages.add.canvas.line_width(10)
|
576
|
+
doc.trailer.info[:Author] = 'HexaPDF'
|
577
|
+
doc.dispatch_message(:complete_objects)
|
578
|
+
|
579
|
+
dupped = doc.duplicate
|
580
|
+
assert_equal('HexaPDF', dupped.trailer.info[:Author])
|
581
|
+
doc.pages[0].canvas.line_cap_style(:round)
|
582
|
+
assert_equal("10 w\n", dupped.pages[0].contents)
|
583
|
+
end
|
584
|
+
|
585
|
+
it "doesn't copy the encryption state" do
|
586
|
+
doc = HexaPDF::Document.new
|
587
|
+
doc.pages.add.canvas.line_width(10)
|
588
|
+
doc.encrypt
|
589
|
+
io = StringIO.new
|
590
|
+
doc.write(io)
|
591
|
+
|
592
|
+
doc = HexaPDF::Document.new(io: io)
|
593
|
+
dupped = doc.duplicate
|
594
|
+
assert_equal("10 w\n", dupped.pages[0].contents)
|
595
|
+
refute(dupped.encrypted?)
|
596
|
+
end
|
597
|
+
end
|
571
598
|
end
|
@@ -47,6 +47,13 @@ describe HexaPDF::Importer do
|
|
47
47
|
refute_same(obj1, obj2)
|
48
48
|
refute_same(obj1[:ref], obj2[:ref])
|
49
49
|
end
|
50
|
+
|
51
|
+
it "duplicates the whole document" do
|
52
|
+
trailer = HexaPDF::Importer.copy(@dest, @source.trailer, allow_all: true)
|
53
|
+
refute_same(@source.catalog, trailer[:Root])
|
54
|
+
refute_same(@source.pages.root, trailer[:Root][:Pages])
|
55
|
+
assert_equal(90, trailer[:Root][:Pages][:Kids][0][:Rotate])
|
56
|
+
end
|
50
57
|
end
|
51
58
|
|
52
59
|
describe "import" do
|
@@ -121,6 +128,16 @@ describe HexaPDF::Importer do
|
|
121
128
|
refute_same(dst_obj.data.stream, src_obj.data.stream)
|
122
129
|
end
|
123
130
|
|
131
|
+
it "duplicates the stream if it is a FiberDoubleForString, e.g. when using Canvas" do
|
132
|
+
src_page = @source.pages[0]
|
133
|
+
src_page.canvas.line_width(10)
|
134
|
+
dst_page = @importer.import(src_page)
|
135
|
+
refute_same(dst_page, src_page)
|
136
|
+
refute_same(dst_page[:Contents].data.stream, src_page[:Contents].data.stream)
|
137
|
+
src_page.canvas.line_width(20)
|
138
|
+
assert_equal("10 w\n", dst_page.contents)
|
139
|
+
end
|
140
|
+
|
124
141
|
it "does not import objects of type Catalog or Pages" do
|
125
142
|
@obj[:catalog] = @source.catalog
|
126
143
|
@obj[:pages] = @source.catalog.pages
|
@@ -357,46 +357,59 @@ describe HexaPDF::Revisions do
|
|
357
357
|
end
|
358
358
|
end
|
359
359
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
360
|
+
describe "linearzied PDFs" do
|
361
|
+
before do
|
362
|
+
@io = StringIO.new(<<~EOF)
|
363
|
+
%PDF-1.2
|
364
|
+
5 0 obj
|
365
|
+
<</Linearized 1>>
|
366
|
+
endobj
|
367
|
+
xref
|
368
|
+
5 1
|
369
|
+
0000000009 00000 n
|
370
|
+
trailer
|
371
|
+
<</ID[(a)(b)]/Info 1 0 R/Root 2 0 R/Size 6/Prev 394>>
|
372
|
+
%
|
373
|
+
1 0 obj
|
374
|
+
<</ModDate(D:20221205233910+01'00')/Producer(HexaPDF version 0.27.0)>>
|
375
|
+
endobj
|
376
|
+
2 0 obj
|
377
|
+
<</Type/Catalog/Pages 3 0 R>>
|
378
|
+
endobj
|
379
|
+
3 0 obj
|
380
|
+
<</Type/Pages/Kids[4 0 R]/Count 1>>
|
381
|
+
endobj
|
382
|
+
4 0 obj
|
383
|
+
<</Type/Page/MediaBox[0 0 595 842]/Parent 3 0 R/Resources<<>>>>
|
384
|
+
endobj
|
385
|
+
xref
|
386
|
+
0 5
|
387
|
+
0000000000 65535 f
|
388
|
+
0000000133 00000 n
|
389
|
+
0000000219 00000 n
|
390
|
+
0000000264 00000 n
|
391
|
+
0000000315 00000 n
|
392
|
+
trailer
|
393
|
+
<</ID[(a)(b)]/Info 1 0 R/Root 2 0 R/Size 5>>
|
394
|
+
startxref
|
395
|
+
41
|
396
|
+
%%EOF
|
397
|
+
EOF
|
398
|
+
end
|
399
|
+
|
400
|
+
it "merges the two revisions of a linearized PDF into one" do
|
401
|
+
doc = HexaPDF::Document.new(io: @io, config: {'parser.try_xref_reconstruction' => false})
|
402
|
+
assert(doc.revisions.parser.linearized?)
|
403
|
+
assert_equal(1, doc.revisions.count)
|
404
|
+
assert_same(5, doc.revisions.current.xref_section.max_oid)
|
405
|
+
end
|
406
|
+
|
407
|
+
it "works for a fake linearized PDF where the first xref section isn't actually used" do
|
408
|
+
@io.string[-9..-1] = "394\n%%EOF\n"
|
409
|
+
doc = HexaPDF::Document.new(io: @io, config: {'parser.try_xref_reconstruction' => false})
|
410
|
+
assert(doc.revisions.parser.linearized?)
|
411
|
+
assert_equal(1, doc.revisions.count)
|
412
|
+
assert_same(4, doc.revisions.current.xref_section.max_oid)
|
413
|
+
end
|
401
414
|
end
|
402
415
|
end
|
@@ -89,6 +89,7 @@ describe HexaPDF::Serializer do
|
|
89
89
|
assert_serialized('/ ', :"")
|
90
90
|
assert_serialized('/H#c3#b6#c3#9fgang', :Hößgang)
|
91
91
|
assert_serialized('/H#e8lp', "H\xE8lp".force_encoding('BINARY').intern)
|
92
|
+
assert_serialized('/#00#09#0a#0c#0d#20', :"\x00\t\n\f\r ")
|
92
93
|
end
|
93
94
|
|
94
95
|
it "serializes arrays" do
|
@@ -274,6 +274,15 @@ describe HexaPDF::Type::AcroForm::Form do
|
|
274
274
|
assert(obj.null?)
|
275
275
|
end
|
276
276
|
|
277
|
+
it "deletes a field with an embedded widget annotation" do
|
278
|
+
widget = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
279
|
+
assert_equal(widget, @field)
|
280
|
+
refute(@doc.pages[0][:Annots].empty?)
|
281
|
+
@acro_form.delete_field(@field)
|
282
|
+
assert(@doc.pages[0][:Annots].empty?)
|
283
|
+
assert(@field.null?)
|
284
|
+
end
|
285
|
+
|
277
286
|
it "deletes all widget annotations from the document and the annotation array" do
|
278
287
|
widget1 = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
279
288
|
widget2 = @field.create_widget(@doc.pages.add, Rect: [0, 0, 0, 0])
|
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.46.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Leitner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdparse
|