hexapdf 0.33.0 → 0.34.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 +42 -1
- data/examples/026-optional_content.rb +55 -0
- data/examples/027-composer_optional_content.rb +83 -0
- data/lib/hexapdf/cli/command.rb +7 -1
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +2 -4
- data/lib/hexapdf/composer.rb +2 -1
- data/lib/hexapdf/configuration.rb +21 -1
- data/lib/hexapdf/content/canvas.rb +52 -0
- data/lib/hexapdf/content/operator.rb +2 -0
- data/lib/hexapdf/dictionary.rb +1 -0
- data/lib/hexapdf/dictionary_fields.rb +1 -2
- data/lib/hexapdf/digital_signature/verification_result.rb +1 -2
- data/lib/hexapdf/document/layout.rb +3 -0
- data/lib/hexapdf/document/pages.rb +1 -1
- data/lib/hexapdf/document.rb +7 -0
- data/lib/hexapdf/encryption/ruby_aes.rb +10 -20
- data/lib/hexapdf/layout/box.rb +23 -3
- data/lib/hexapdf/layout/column_box.rb +2 -1
- data/lib/hexapdf/layout/frame.rb +23 -6
- data/lib/hexapdf/layout/inline_box.rb +20 -9
- data/lib/hexapdf/layout/list_box.rb +34 -20
- data/lib/hexapdf/layout/page_style.rb +2 -1
- data/lib/hexapdf/layout/style.rb +46 -6
- data/lib/hexapdf/layout/table_box.rb +9 -7
- data/lib/hexapdf/layout/text_box.rb +9 -2
- data/lib/hexapdf/layout/text_fragment.rb +28 -2
- data/lib/hexapdf/layout/text_layouter.rb +21 -5
- data/lib/hexapdf/stream.rb +1 -2
- data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
- data/lib/hexapdf/type/actions.rb +1 -0
- data/lib/hexapdf/type/annotations/text.rb +1 -2
- data/lib/hexapdf/type/catalog.rb +10 -1
- data/lib/hexapdf/type/cid_font.rb +15 -1
- data/lib/hexapdf/type/form.rb +75 -5
- data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
- data/lib/hexapdf/type/optional_content_group.rb +370 -0
- data/lib/hexapdf/type/optional_content_membership.rb +63 -0
- data/lib/hexapdf/type/optional_content_properties.rb +158 -0
- data/lib/hexapdf/type/page.rb +27 -11
- data/lib/hexapdf/type/page_label.rb +4 -8
- data/lib/hexapdf/type.rb +4 -0
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +0 -1
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/content/test_canvas.rb +49 -0
- data/test/hexapdf/document/test_layout.rb +7 -2
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/layout/test_box.rb +13 -4
- data/test/hexapdf/layout/test_frame.rb +13 -1
- data/test/hexapdf/layout/test_inline_box.rb +17 -8
- data/test/hexapdf/layout/test_list_box.rb +48 -31
- data/test/hexapdf/layout/test_style.rb +10 -0
- data/test/hexapdf/layout/test_table_box.rb +32 -26
- data/test/hexapdf/layout/test_text_box.rb +8 -0
- data/test/hexapdf/layout/test_text_fragment.rb +33 -0
- data/test/hexapdf/layout/test_text_layouter.rb +32 -5
- data/test/hexapdf/test_composer.rb +10 -0
- data/test/hexapdf/test_dictionary.rb +10 -0
- data/test/hexapdf/test_document.rb +4 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
- data/test/hexapdf/type/test_catalog.rb +11 -0
- data/test/hexapdf/type/test_form.rb +119 -0
- data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
- data/test/hexapdf/type/test_optional_content_group.rb +158 -0
- data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
- data/test/hexapdf/type/test_page.rb +2 -2
- metadata +14 -3
@@ -103,8 +103,7 @@ module HexaPDF
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
-
# :nodoc:
|
107
|
-
NUMBERING_STYLE_MAPPING = {
|
106
|
+
NUMBERING_STYLE_MAPPING = { # :nodoc:
|
108
107
|
decimal: :D, D: :D,
|
109
108
|
uppercase_roman: :R, R: :R,
|
110
109
|
lowercase_roman: :r, r: :r,
|
@@ -113,8 +112,7 @@ module HexaPDF
|
|
113
112
|
none: nil
|
114
113
|
}
|
115
114
|
|
116
|
-
# :nodoc:
|
117
|
-
REVERSE_NUMBERING_STYLE_MAPPING = Hash[*NUMBERING_STYLE_MAPPING.flatten.reverse]
|
115
|
+
REVERSE_NUMBERING_STYLE_MAPPING = Hash[*NUMBERING_STYLE_MAPPING.flatten.reverse] # :nodoc:
|
118
116
|
|
119
117
|
# :call-seq:
|
120
118
|
# page_label.numbering_style -> numbering_style
|
@@ -174,8 +172,7 @@ module HexaPDF
|
|
174
172
|
|
175
173
|
private
|
176
174
|
|
177
|
-
# :nodoc:
|
178
|
-
ALPHABET = ('A'..'Z').to_a
|
175
|
+
ALPHABET = ('A'..'Z').to_a # :nodoc:
|
179
176
|
|
180
177
|
# Maps the given number to uppercase (or, if +lowercase+ is +true+, lowercase) letters (e.g. 1
|
181
178
|
# -> A, 27 -> AA, 28 -> AB, ...).
|
@@ -188,8 +185,7 @@ module HexaPDF
|
|
188
185
|
lowercase ? result.downcase : result
|
189
186
|
end
|
190
187
|
|
191
|
-
# :nodoc:
|
192
|
-
ROMAN_NUMERAL_MAPPING = {
|
188
|
+
ROMAN_NUMERAL_MAPPING = { # :nodoc:
|
193
189
|
1000 => "M",
|
194
190
|
900 => "CM",
|
195
191
|
500 => "D",
|
data/lib/hexapdf/type.rb
CHANGED
@@ -76,6 +76,10 @@ module HexaPDF
|
|
76
76
|
autoload(:OutlineItem, 'hexapdf/type/outline_item')
|
77
77
|
autoload(:PageLabel, 'hexapdf/type/page_label')
|
78
78
|
autoload(:MarkInformation, 'hexapdf/type/mark_information')
|
79
|
+
autoload(:OptionalContentGroup, 'hexapdf/type/optional_content_group')
|
80
|
+
autoload(:OptionalContentMembership, 'hexapdf/type/optional_content_membership')
|
81
|
+
autoload(:OptionalContentProperties, 'hexapdf/type/optional_content_properties')
|
82
|
+
autoload(:OptionalContentConfiguration, 'hexapdf/type/optional_content_configuration')
|
79
83
|
|
80
84
|
end
|
81
85
|
|
@@ -52,7 +52,6 @@ module HexaPDF
|
|
52
52
|
# See: PDF2.0 s7.9.2, D.1, D.3
|
53
53
|
module PDFDocEncoding
|
54
54
|
|
55
|
-
# :nodoc:
|
56
55
|
CHARACTER_MAP = %W[\uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD
|
57
56
|
\uFFFD \u0009 \u000A \uFFFD \uFFFD \u000D \uFFFD \uFFFD
|
58
57
|
\uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD
|
data/lib/hexapdf/version.rb
CHANGED
@@ -71,6 +71,13 @@ describe HexaPDF::Content::Canvas do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
describe "pos" do
|
75
|
+
it "returns the transformed position" do
|
76
|
+
@canvas.translate(9, 4)
|
77
|
+
assert_equal([10, 5], @canvas.pos(1, 1))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
74
81
|
describe "save_graphics_state" do
|
75
82
|
it "invokes the operator implementation" do
|
76
83
|
assert_operator_invoked(:q) { @canvas.save_graphics_state }
|
@@ -1280,6 +1287,48 @@ describe HexaPDF::Content::Canvas do
|
|
1280
1287
|
end
|
1281
1288
|
end
|
1282
1289
|
|
1290
|
+
describe "optional_content" do
|
1291
|
+
it "invokes the marked-sequence operator implementation" do
|
1292
|
+
assert_operator_invoked(:BDC, :OC, :P1) { @canvas.optional_content('Test') }
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
it "is serialized correctly when no block is used" do
|
1296
|
+
@canvas.optional_content('Test')
|
1297
|
+
assert_operators(@canvas.contents, [[:begin_marked_content_with_property_list, [:OC, :P1]]])
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
it "is serialized correctly when a block is used" do
|
1301
|
+
@canvas.optional_content('Test') {}
|
1302
|
+
assert_operators(@canvas.contents, [[:begin_marked_content_with_property_list, [:OC, :P1]],
|
1303
|
+
[:end_marked_content]])
|
1304
|
+
end
|
1305
|
+
|
1306
|
+
it "uses the provided OCG dictionary" do
|
1307
|
+
ocg = @doc.optional_content.add_ocg('Test')
|
1308
|
+
@canvas.optional_content(ocg)
|
1309
|
+
assert_equal(ocg, @page.resources.property_list(:P1))
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
it "uses an existing OCG specified by name" do
|
1313
|
+
ocg = @doc.optional_content.add_ocg('Test')
|
1314
|
+
@canvas.optional_content('Test')
|
1315
|
+
assert_equal(ocg, @page.resources.property_list(:P1))
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
it "creates an OCG if the named one doesn't yet exist" do
|
1319
|
+
@canvas.optional_content('Test')
|
1320
|
+
assert_equal(@doc.optional_content.ocg('Test'), @page.resources.property_list(:P1))
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
it "always creates a new OCG if use_existing_ocg is false" do
|
1324
|
+
ocg = @doc.optional_content.add_ocg('Test')
|
1325
|
+
@canvas.optional_content('Test', use_existing_ocg: false)
|
1326
|
+
pl_item = @page.resources.property_list(:P1)
|
1327
|
+
refute_equal(ocg, pl_item)
|
1328
|
+
assert_equal(@doc.optional_content.ocgs.last, pl_item)
|
1329
|
+
end
|
1330
|
+
end
|
1331
|
+
|
1283
1332
|
describe "color_from_specification "do
|
1284
1333
|
it "accepts a color string" do
|
1285
1334
|
assert_equal([1, 0, 0], @canvas.color_from_specification("red").components)
|
@@ -219,6 +219,10 @@ describe HexaPDF::Document::Layout do
|
|
219
219
|
box = @layout.text_box("Test", box_style: :named)
|
220
220
|
assert_equal(20, box.style.font_size)
|
221
221
|
end
|
222
|
+
|
223
|
+
it "raises an error if the to-be-used style doesn't exist" do
|
224
|
+
assert_raises(HexaPDF::Error) { @layout.text_box("Test", style: :unknown) }
|
225
|
+
end
|
222
226
|
end
|
223
227
|
|
224
228
|
describe "formatted_text" do
|
@@ -305,9 +309,10 @@ describe HexaPDF::Document::Layout do
|
|
305
309
|
|
306
310
|
it "allows creating an inline box through a hash with a :box key" do
|
307
311
|
block = lambda {|item| item.box(:base, width: 5, height: 15) }
|
308
|
-
box = @layout.formatted_text_box([{box: :
|
312
|
+
box = @layout.formatted_text_box([{box: :column, columns: 1, width: 100, block: block}])
|
309
313
|
ibox = box.instance_variable_get(:@items).first
|
310
|
-
|
314
|
+
ibox.fit_wrapped_box(nil)
|
315
|
+
assert_equal(100, ibox.width)
|
311
316
|
assert_equal(15, ibox.height)
|
312
317
|
end
|
313
318
|
|
@@ -196,15 +196,15 @@ describe HexaPDF::Document::Pages do
|
|
196
196
|
end
|
197
197
|
|
198
198
|
it "works for multiple page label entries" do
|
199
|
-
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 2, {S: :
|
199
|
+
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 2, {S: :D}, 7, {S: :A}]}
|
200
200
|
result = @doc.pages.each_labelling_range.to_a
|
201
|
-
assert_equal([[0, 2, {S: :r}], [2, 5, {S: :
|
201
|
+
assert_equal([[0, 2, {S: :r}], [2, 5, {S: :D}], [7, 3, {S: :A}]],
|
202
202
|
result.map {|s, c, l| [s, c, l.value] })
|
203
203
|
end
|
204
204
|
|
205
205
|
it "returns a zero or negative count for the last range if there aren't enough pages" do
|
206
206
|
assert_equal(10, @doc.pages.count)
|
207
|
-
@doc.catalog[:PageLabels] = {Nums: [0, {S: :
|
207
|
+
@doc.catalog[:PageLabels] = {Nums: [0, {S: :D}, 10, {S: :r}]}
|
208
208
|
assert_equal(0, @doc.pages.each_labelling_range.to_a[-1][1])
|
209
209
|
@doc.catalog[:PageLabels][:Nums][2] = 11
|
210
210
|
assert_equal(-1, @doc.pages.each_labelling_range.to_a[-1][1])
|
@@ -221,19 +221,19 @@ describe HexaPDF::Document::Pages do
|
|
221
221
|
|
222
222
|
it "adds an entry for the range starting at 0 if it doesn't exist" do
|
223
223
|
label = @doc.pages.add_labelling_range(5)
|
224
|
-
assert_equal([{S: :
|
224
|
+
assert_equal([{S: :D}, label],
|
225
225
|
@doc.catalog.page_labels[:Nums].value.values_at(1, 3))
|
226
226
|
end
|
227
227
|
end
|
228
228
|
|
229
229
|
describe "delete_labelling_range" do
|
230
230
|
before do
|
231
|
-
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 5, {S: :
|
231
|
+
@doc.catalog[:PageLabels] = {Nums: [0, {S: :r}, 5, {S: :D}]}
|
232
232
|
end
|
233
233
|
|
234
234
|
it "deletes the labelling range for a given start index" do
|
235
235
|
label = @doc.pages.delete_labelling_range(5)
|
236
|
-
assert_equal({S: :
|
236
|
+
assert_equal({S: :D}, label)
|
237
237
|
end
|
238
238
|
|
239
239
|
it "deletes the labelling range for 0 if it is the last, together with the number tree" do
|
@@ -56,8 +56,8 @@ describe HexaPDF::Layout::Box do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
it "allows setting custom properties" do
|
59
|
-
|
60
|
-
assert_equal({'key' => :value},
|
59
|
+
assert_equal({}, create_box(properties: nil).properties)
|
60
|
+
assert_equal({'key' => :value}, create_box(properties: {'key' => :value}).properties)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -150,6 +150,10 @@ describe HexaPDF::Layout::Box do
|
|
150
150
|
end
|
151
151
|
|
152
152
|
describe "draw" do
|
153
|
+
before do
|
154
|
+
@canvas = HexaPDF::Document.new.pages.add.canvas
|
155
|
+
end
|
156
|
+
|
153
157
|
it "draws the box onto the canvas" do
|
154
158
|
box = create_box(width: 150, height: 130) do |canvas, _|
|
155
159
|
canvas.line_width(15)
|
@@ -161,7 +165,6 @@ describe HexaPDF::Layout::Box do
|
|
161
165
|
box.style.underlays.add {|canvas, _| canvas.line_width(10) }
|
162
166
|
box.style.overlays.add {|canvas, _| canvas.line_width(20) }
|
163
167
|
|
164
|
-
@canvas = HexaPDF::Document.new.pages.add.canvas
|
165
168
|
box.draw(@canvas, 5, 5)
|
166
169
|
assert_operators(@canvas.contents, [[:save_graphics_state],
|
167
170
|
[:set_graphics_state_parameters, [:GS1]],
|
@@ -195,7 +198,6 @@ describe HexaPDF::Layout::Box do
|
|
195
198
|
end
|
196
199
|
|
197
200
|
it "draws nothing onto the canvas if the box is empty" do
|
198
|
-
@canvas = HexaPDF::Document.new.pages.add.canvas
|
199
201
|
box = create_box
|
200
202
|
box.draw(@canvas, 5, 5)
|
201
203
|
assert_operators(@canvas.contents, [])
|
@@ -204,6 +206,13 @@ describe HexaPDF::Layout::Box do
|
|
204
206
|
refute(box.style.border?)
|
205
207
|
refute(box.style.overlays?)
|
206
208
|
end
|
209
|
+
|
210
|
+
it "wraps the box in optional content markers if the optional_content property is set" do
|
211
|
+
box = create_box(properties: {'optional_content' => 'Text'})
|
212
|
+
box.draw(@canvas, 0, 0)
|
213
|
+
assert_operators(@canvas.contents, [[:begin_marked_content_with_property_list, [:OC, :P1]],
|
214
|
+
[:end_marked_content]])
|
215
|
+
end
|
207
216
|
end
|
208
217
|
|
209
218
|
describe "empty?" do
|
@@ -5,7 +5,7 @@ require 'hexapdf/layout/frame'
|
|
5
5
|
require 'hexapdf/layout/box'
|
6
6
|
require 'hexapdf/document'
|
7
7
|
|
8
|
-
describe HexaPDF::Layout::Frame do
|
8
|
+
describe HexaPDF::Layout::Frame::FitResult do
|
9
9
|
it "shows the box's mask area on #draw when using debug output" do
|
10
10
|
doc = HexaPDF::Document.new(config: {'debug' => true})
|
11
11
|
canvas = doc.pages.add.canvas
|
@@ -15,6 +15,7 @@ describe HexaPDF::Layout::Frame do
|
|
15
15
|
result.x = result.y = 0
|
16
16
|
result.draw(canvas)
|
17
17
|
assert_equal(<<~CONTENTS, canvas.contents)
|
18
|
+
/OC /P1 BDC
|
18
19
|
q
|
19
20
|
0.0 0.501961 0.0 rg
|
20
21
|
0.0 0.392157 0.0 RG
|
@@ -22,10 +23,13 @@ describe HexaPDF::Layout::Frame do
|
|
22
23
|
0 0 20 20 re
|
23
24
|
B
|
24
25
|
Q
|
26
|
+
EMC
|
25
27
|
q
|
26
28
|
1 0 0 1 0 0 cm
|
27
29
|
Q
|
28
30
|
CONTENTS
|
31
|
+
ocg = doc.optional_content.ocgs.first
|
32
|
+
assert_equal([['Debug', ocg]], doc.optional_content.default_configuration[:Order])
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
@@ -34,6 +38,14 @@ describe HexaPDF::Layout::Frame do
|
|
34
38
|
@frame = HexaPDF::Layout::Frame.new(5, 10, 100, 150)
|
35
39
|
end
|
36
40
|
|
41
|
+
it "allows accessing the context's document" do
|
42
|
+
assert_nil(@frame.document)
|
43
|
+
context = Minitest::Mock.new
|
44
|
+
context.expect(:document, :document)
|
45
|
+
assert_equal(:document, HexaPDF::Layout::Frame.new(0, 0, 10, 10, context: context).document)
|
46
|
+
context.verify
|
47
|
+
end
|
48
|
+
|
37
49
|
it "allows access to the bounding box attributes" do
|
38
50
|
assert_equal(5, @frame.left)
|
39
51
|
assert_equal(10, @frame.bottom)
|
@@ -24,25 +24,28 @@ describe HexaPDF::Layout::InlineBox do
|
|
24
24
|
assert_equal(:top, ibox.valign)
|
25
25
|
end
|
26
26
|
|
27
|
+
it "fails if the wrapped box has not width set" do
|
28
|
+
box = HexaPDF::Document.new.layout.text("test is not going good")
|
29
|
+
assert_raises(HexaPDF::Error) { inline_box(box) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "fit_wrapped_box" do
|
27
34
|
it "automatically fits the provided box into a frame" do
|
28
35
|
ibox = inline_box(HexaPDF::Document.new.layout.text("test is going good", width: 20))
|
36
|
+
ibox.fit_wrapped_box(nil)
|
29
37
|
assert_equal(20, ibox.width)
|
30
38
|
assert_equal(45, ibox.height)
|
31
39
|
end
|
32
40
|
|
33
|
-
it "fails if the wrapped box has not width set" do
|
34
|
-
box = HexaPDF::Document.new.layout.text("test is not going good")
|
35
|
-
assert_raises(HexaPDF::Error) { inline_box(box) }
|
36
|
-
end
|
37
|
-
|
38
41
|
it "fails if the wrapped box could not be fit" do
|
39
42
|
box = HexaPDF::Document.new.layout.text("test is not going good", width: 1)
|
40
|
-
assert_raises(HexaPDF::Error) { inline_box(box) }
|
43
|
+
assert_raises(HexaPDF::Error) { inline_box(box).fit_wrapped_box(nil) }
|
41
44
|
end
|
42
45
|
|
43
46
|
it "fails if the height is not set explicitly and during fitting" do
|
44
47
|
assert_raises(HexaPDF::Error) do
|
45
|
-
inline_box(HexaPDF::Layout::Box.create(width: 10))
|
48
|
+
inline_box(HexaPDF::Layout::Box.create(width: 10)).fit_wrapped_box(nil)
|
46
49
|
end
|
47
50
|
end
|
48
51
|
end
|
@@ -50,7 +53,9 @@ describe HexaPDF::Layout::InlineBox do
|
|
50
53
|
it "draws the wrapped box at the correct position" do
|
51
54
|
doc = HexaPDF::Document.new
|
52
55
|
canvas = doc.pages.add.canvas
|
53
|
-
inline_box(doc.layout.text("", width: 20, margin: [15, 10]))
|
56
|
+
box = inline_box(doc.layout.text("", width: 20, margin: [15, 10]))
|
57
|
+
box.fit_wrapped_box(nil)
|
58
|
+
box.draw(canvas, 100, 200)
|
54
59
|
assert_equal("q\n1 0 0 1 110 -99785 cm\nQ\n", canvas.contents)
|
55
60
|
end
|
56
61
|
|
@@ -59,6 +64,10 @@ describe HexaPDF::Layout::InlineBox do
|
|
59
64
|
refute(HexaPDF::Layout::InlineBox.create(width: 10, height: 15) {}.empty?)
|
60
65
|
end
|
61
66
|
|
67
|
+
it "returns the style of the box" do
|
68
|
+
assert_same(@box.box.style, @box.style)
|
69
|
+
end
|
70
|
+
|
62
71
|
describe "valign" do
|
63
72
|
it "has a default value of :baseline" do
|
64
73
|
assert_equal(:baseline, @box.valign)
|
@@ -6,7 +6,9 @@ require 'hexapdf/layout/list_box'
|
|
6
6
|
|
7
7
|
describe HexaPDF::Layout::ListBox do
|
8
8
|
before do
|
9
|
-
@
|
9
|
+
@doc = HexaPDF::Document.new
|
10
|
+
@page = @doc.pages.add
|
11
|
+
@frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100, context: @page)
|
10
12
|
inline_box = HexaPDF::Layout::InlineBox.create(width: 10, height: 10) {}
|
11
13
|
@text_boxes = 5.times.map do
|
12
14
|
HexaPDF::Layout::TextBox.new(items: [inline_box] * 15, style: {position: :default})
|
@@ -23,8 +25,8 @@ describe HexaPDF::Layout::ListBox do
|
|
23
25
|
assert_equal(height, box.height, "box height")
|
24
26
|
if fit_pos
|
25
27
|
results = box.instance_variable_get(:@results)
|
26
|
-
results.each_with_index do |
|
27
|
-
box_fitter.fit_results.each_with_index do |fit_result, result_index|
|
28
|
+
results.each_with_index do |item_result, item_index|
|
29
|
+
item_result.box_fitter.fit_results.each_with_index do |fit_result, result_index|
|
28
30
|
x, y = fit_pos.shift
|
29
31
|
assert_equal(x, fit_result.x, "item #{item_index}, result #{result_index}, x")
|
30
32
|
assert_equal(y, fit_result.y, "item #{item_index}, result #{result_index}, y")
|
@@ -55,7 +57,7 @@ describe HexaPDF::Layout::ListBox do
|
|
55
57
|
it "is empty if nothing could be fit" do
|
56
58
|
box = create_box(children: [@text_boxes[0]], width: 5)
|
57
59
|
box.fit(@frame.available_width, @frame.available_height, @frame)
|
58
|
-
assert(
|
60
|
+
assert(box.empty?)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
@@ -90,6 +92,12 @@ describe HexaPDF::Layout::ListBox do
|
|
90
92
|
check_box(box, 100, 90, [[10, 80], [10, 60], [10, 40], [50, 10]])
|
91
93
|
end
|
92
94
|
|
95
|
+
it "calculates the correct height if the marker is higher than the content" do
|
96
|
+
box = create_box(children: @text_boxes[0, 1], content_indentation: 20,
|
97
|
+
style: {font_size: 30})
|
98
|
+
check_box(box, 100, 27, [[20, 80]])
|
99
|
+
end
|
100
|
+
|
93
101
|
it "respects the content indentation" do
|
94
102
|
box = create_box(children: @text_boxes[0, 1], content_indentation: 30)
|
95
103
|
check_box(box, 100, 30, [[30, 70]])
|
@@ -99,6 +107,11 @@ describe HexaPDF::Layout::ListBox do
|
|
99
107
|
box = create_box(children: @text_boxes[0, 2], item_spacing: 30)
|
100
108
|
check_box(box, 100, 70, [[10, 80], [10, 30]])
|
101
109
|
end
|
110
|
+
|
111
|
+
it "fails for unknown item types" do
|
112
|
+
box = create_box(children: @text_boxes[0, 1], item_type: :unknown)
|
113
|
+
assert_raises(HexaPDF::Error) { box.fit(100, 100, @frame) }
|
114
|
+
end
|
102
115
|
end
|
103
116
|
|
104
117
|
describe "split" do
|
@@ -108,7 +121,7 @@ describe HexaPDF::Layout::ListBox do
|
|
108
121
|
box_a, box_b = box.split(100, 100, @frame)
|
109
122
|
assert_same(box, box_a)
|
110
123
|
assert_equal(:show_first_marker, box_b.split_box?)
|
111
|
-
assert_equal(1, box_a.instance_variable_get(:@results)[0].fit_results.size)
|
124
|
+
assert_equal(1, box_a.instance_variable_get(:@results)[0].box_fitter.fit_results.size)
|
112
125
|
assert_equal(1, box_b.children.size)
|
113
126
|
assert_equal(2, box_b.start_number)
|
114
127
|
end
|
@@ -119,7 +132,7 @@ describe HexaPDF::Layout::ListBox do
|
|
119
132
|
box_a, box_b = box.split(100, 100, @frame)
|
120
133
|
assert_same(box, box_a)
|
121
134
|
assert_equal(:hide_first_marker, box_b.split_box?)
|
122
|
-
assert_equal(1, box_a.instance_variable_get(:@results)[0].fit_results.size)
|
135
|
+
assert_equal(1, box_a.instance_variable_get(:@results)[0].box_fitter.fit_results.size)
|
123
136
|
assert_equal(2, box_b.children.size)
|
124
137
|
assert_equal(1, box_b.start_number)
|
125
138
|
end
|
@@ -127,20 +140,22 @@ describe HexaPDF::Layout::ListBox do
|
|
127
140
|
|
128
141
|
describe "draw" do
|
129
142
|
before do
|
130
|
-
@canvas =
|
143
|
+
@canvas = @page.canvas
|
131
144
|
draw_block = lambda {|canvas, box| }
|
132
145
|
@fixed_size_boxes = 5.times.map { HexaPDF::Layout::Box.new(width: 20, height: 10, &draw_block) }
|
133
146
|
end
|
134
147
|
|
135
148
|
it "draws the result" do
|
136
|
-
box = create_box(children: @fixed_size_boxes[0, 2]
|
149
|
+
box = create_box(children: @fixed_size_boxes[0, 2],
|
150
|
+
style: {font_size: 11, fill_color: 0.5})
|
137
151
|
box.fit(100, 100, @frame)
|
138
152
|
box.draw(@canvas, 0, 100 - box.height)
|
139
153
|
operators = [
|
140
154
|
[:save_graphics_state],
|
141
|
-
[:set_font_and_size, [:F1,
|
155
|
+
[:set_font_and_size, [:F1, 11]],
|
156
|
+
[:set_device_gray_non_stroking_color, [0.5]],
|
142
157
|
[:begin_text],
|
143
|
-
[:set_text_matrix, [1, 0, 0, 1, 1.
|
158
|
+
[:set_text_matrix, [1, 0, 0, 1, 1.15, 92.487]],
|
144
159
|
[:show_text, ["\x95".b]],
|
145
160
|
[:end_text],
|
146
161
|
[:restore_graphics_state],
|
@@ -149,9 +164,10 @@ describe HexaPDF::Layout::ListBox do
|
|
149
164
|
[:restore_graphics_state],
|
150
165
|
|
151
166
|
[:save_graphics_state],
|
152
|
-
[:set_font_and_size, [:F1,
|
167
|
+
[:set_font_and_size, [:F1, 11]],
|
168
|
+
[:set_device_gray_non_stroking_color, [0.5]],
|
153
169
|
[:begin_text],
|
154
|
-
[:set_text_matrix, [1, 0, 0, 1, 1.
|
170
|
+
[:set_text_matrix, [1, 0, 0, 1, 1.15, 82.487]],
|
155
171
|
[:show_text, ["\x95".b]],
|
156
172
|
[:end_text],
|
157
173
|
[:restore_graphics_state],
|
@@ -162,16 +178,18 @@ describe HexaPDF::Layout::ListBox do
|
|
162
178
|
assert_operators(@canvas.contents, operators)
|
163
179
|
end
|
164
180
|
|
165
|
-
it "draws a
|
166
|
-
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle
|
181
|
+
it "draws a circle as marker" do
|
182
|
+
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle,
|
183
|
+
style: {font_size: 11, fill_color: 0.5})
|
167
184
|
box.fit(100, 100, @frame)
|
168
185
|
box.draw(@canvas, 0, 100 - box.height)
|
169
186
|
operators = [
|
170
187
|
[:save_graphics_state],
|
171
|
-
[:set_font_and_size, [:F1, 5]],
|
172
|
-
[:set_text_rise, [-
|
188
|
+
[:set_font_and_size, [:F1, 5.5]],
|
189
|
+
[:set_text_rise, [-6.111111]],
|
190
|
+
[:set_device_gray_non_stroking_color, [0.5]],
|
173
191
|
[:begin_text],
|
174
|
-
[:set_text_matrix, [1, 0, 0, 1, 0.
|
192
|
+
[:set_text_matrix, [1, 0, 0, 1, 0.1985, 100]],
|
175
193
|
[:show_text, ["m".b]],
|
176
194
|
[:end_text],
|
177
195
|
[:restore_graphics_state],
|
@@ -183,15 +201,17 @@ describe HexaPDF::Layout::ListBox do
|
|
183
201
|
end
|
184
202
|
|
185
203
|
it "draws a square as marker" do
|
186
|
-
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square
|
204
|
+
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square,
|
205
|
+
style: {font_size: 11, fill_color: 0.5})
|
187
206
|
box.fit(100, 100, @frame)
|
188
207
|
box.draw(@canvas, 0, 100 - box.height)
|
189
208
|
operators = [
|
190
209
|
[:save_graphics_state],
|
191
|
-
[:set_font_and_size, [:F1, 5]],
|
192
|
-
[:set_text_rise, [-
|
210
|
+
[:set_font_and_size, [:F1, 5.5]],
|
211
|
+
[:set_text_rise, [-6.111111]],
|
212
|
+
[:set_device_gray_non_stroking_color, [0.5]],
|
193
213
|
[:begin_text],
|
194
|
-
[:set_text_matrix, [1, 0, 0, 1,
|
214
|
+
[:set_text_matrix, [1, 0, 0, 1, 0.8145, 100]],
|
195
215
|
[:show_text, ["n".b]],
|
196
216
|
[:end_text],
|
197
217
|
[:restore_graphics_state],
|
@@ -204,14 +224,16 @@ describe HexaPDF::Layout::ListBox do
|
|
204
224
|
|
205
225
|
it "draws decimal numbers as marker" do
|
206
226
|
box = create_box(children: @fixed_size_boxes[0, 2], item_type: :decimal,
|
227
|
+
style: {font_size: 11, fill_color: 0.5},
|
207
228
|
content_indentation: 20)
|
208
229
|
box.fit(100, 100, @frame)
|
209
230
|
box.draw(@canvas, 0, 100 - box.height)
|
210
231
|
operators = [
|
211
232
|
[:save_graphics_state],
|
212
|
-
[:set_font_and_size, [:F1,
|
233
|
+
[:set_font_and_size, [:F1, 11]],
|
234
|
+
[:set_device_gray_non_stroking_color, [0.5]],
|
213
235
|
[:begin_text],
|
214
|
-
[:set_text_matrix, [1, 0, 0, 1,
|
236
|
+
[:set_text_matrix, [1, 0, 0, 1, 6.75, 92.487]],
|
215
237
|
[:show_text, ["1.".b]],
|
216
238
|
[:end_text],
|
217
239
|
[:restore_graphics_state],
|
@@ -220,9 +242,10 @@ describe HexaPDF::Layout::ListBox do
|
|
220
242
|
[:restore_graphics_state],
|
221
243
|
|
222
244
|
[:save_graphics_state],
|
223
|
-
[:set_font_and_size, [:F1,
|
245
|
+
[:set_font_and_size, [:F1, 11]],
|
246
|
+
[:set_device_gray_non_stroking_color, [0.5]],
|
224
247
|
[:begin_text],
|
225
|
-
[:set_text_matrix, [1, 0, 0, 1,
|
248
|
+
[:set_text_matrix, [1, 0, 0, 1, 6.75, 82.487]],
|
226
249
|
[:show_text, ["2.".b]],
|
227
250
|
[:end_text],
|
228
251
|
[:restore_graphics_state],
|
@@ -272,11 +295,5 @@ describe HexaPDF::Layout::ListBox do
|
|
272
295
|
]
|
273
296
|
assert_operators(@canvas.contents, operators)
|
274
297
|
end
|
275
|
-
|
276
|
-
it "fails for unknown item types" do
|
277
|
-
box = create_box(children: @fixed_size_boxes[0, 1], item_type: :unknown)
|
278
|
-
box.fit(100, 100, @frame)
|
279
|
-
assert_raises(HexaPDF::Error) { box.draw(@canvas, 0, 0) }
|
280
|
-
end
|
281
298
|
end
|
282
299
|
end
|
@@ -580,7 +580,10 @@ describe HexaPDF::Layout::Style::LinkLayer do
|
|
580
580
|
it "fails if more than one possible target is chosen" do
|
581
581
|
assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, uri: true) }
|
582
582
|
assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, file: true) }
|
583
|
+
assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, action: true) }
|
583
584
|
assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(uri: true, file: true) }
|
585
|
+
assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(uri: true, action: true) }
|
586
|
+
assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(file: true, action: true) }
|
584
587
|
end
|
585
588
|
|
586
589
|
it "fails if an invalid border is provided" do
|
@@ -656,6 +659,12 @@ describe HexaPDF::Layout::Style::LinkLayer do
|
|
656
659
|
assert_nil(annot[:Dest])
|
657
660
|
end
|
658
661
|
|
662
|
+
it "works for actions" do
|
663
|
+
annot = call_link(action: {Type: :Action, S: :SetOCGState})
|
664
|
+
assert_equal({Type: :Action, S: :SetOCGState}, annot[:A].value)
|
665
|
+
assert_nil(annot[:Dest])
|
666
|
+
end
|
667
|
+
|
659
668
|
it "works for destinations set via the 'link' custom box property" do
|
660
669
|
@box.properties['link'] = [@canvas.context, :FitH]
|
661
670
|
annot = call_link({})
|
@@ -773,6 +782,7 @@ describe HexaPDF::Layout::Style do
|
|
773
782
|
refute(@style.subscript)
|
774
783
|
refute(@style.superscript)
|
775
784
|
refute(@style.last_line_gap)
|
785
|
+
refute(@style.fill_horizontal)
|
776
786
|
assert_kind_of(HexaPDF::Layout::Style::Layers, @style.underlays)
|
777
787
|
assert_kind_of(HexaPDF::Layout::Style::Layers, @style.overlays)
|
778
788
|
end
|