hexapdf 0.20.3 → 0.21.1
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 +42 -1
- data/README.md +5 -3
- data/Rakefile +10 -1
- data/examples/018-composer.rb +10 -10
- data/examples/020-column_box.rb +57 -0
- data/lib/hexapdf/cli/batch.rb +4 -6
- data/lib/hexapdf/cli/info.rb +5 -1
- data/lib/hexapdf/cli/inspect.rb +59 -0
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/composer.rb +147 -53
- data/lib/hexapdf/configuration.rb +7 -3
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/content/color_space.rb +1 -1
- data/lib/hexapdf/content/operator.rb +7 -7
- data/lib/hexapdf/content/parser.rb +3 -3
- data/lib/hexapdf/content/processor.rb +9 -9
- data/lib/hexapdf/document/signatures.rb +5 -4
- data/lib/hexapdf/document.rb +7 -0
- data/lib/hexapdf/encryption/aes.rb +9 -5
- data/lib/hexapdf/font/true_type/font.rb +7 -7
- data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
- data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +3 -3
- data/lib/hexapdf/font/true_type_wrapper.rb +9 -14
- data/lib/hexapdf/font/type1/font.rb +10 -12
- data/lib/hexapdf/font/type1_wrapper.rb +15 -17
- data/lib/hexapdf/layout/box.rb +12 -9
- data/lib/hexapdf/layout/column_box.rb +168 -0
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/style.rb +28 -8
- data/lib/hexapdf/layout/text_fragment.rb +10 -9
- data/lib/hexapdf/parser.rb +5 -0
- data/lib/hexapdf/tokenizer.rb +3 -3
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +6 -4
- data/lib/hexapdf/type/acro_form/choice_field.rb +2 -2
- data/lib/hexapdf/type/acro_form/field.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/resources.rb +4 -4
- data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +1 -1
- data/lib/hexapdf/type/signature.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +3 -3
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/xref_section.rb +1 -1
- data/test/hexapdf/common_tokenizer_tests.rb +5 -5
- data/test/hexapdf/content/test_graphics_state.rb +1 -0
- data/test/hexapdf/content/test_operator.rb +2 -2
- data/test/hexapdf/content/test_processor.rb +1 -1
- data/test/hexapdf/encryption/test_aes.rb +8 -0
- data/test/hexapdf/encryption/test_standard_security_handler.rb +23 -29
- data/test/hexapdf/filter/test_predictor.rb +16 -20
- data/test/hexapdf/font/test_type1_wrapper.rb +5 -1
- data/test/hexapdf/font/true_type/table/common.rb +1 -1
- data/test/hexapdf/font/true_type/table/test_cmap.rb +1 -1
- data/test/hexapdf/font/true_type/table/test_cmap_subtable.rb +1 -1
- data/test/hexapdf/image_loader/test_pdf.rb +6 -8
- data/test/hexapdf/image_loader/test_png.rb +2 -2
- data/test/hexapdf/layout/test_box.rb +11 -1
- data/test/hexapdf/layout/test_style.rb +23 -0
- data/test/hexapdf/layout/test_text_fragment.rb +21 -21
- data/test/hexapdf/test_composer.rb +115 -52
- data/test/hexapdf/test_dictionary.rb +2 -2
- data/test/hexapdf/test_document.rb +11 -9
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_parser.rb +13 -7
- data/test/hexapdf/test_serializer.rb +20 -22
- data/test/hexapdf/test_stream.rb +7 -9
- data/test/hexapdf/test_writer.rb +2 -2
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +1 -2
- data/test/hexapdf/type/acro_form/test_choice_field.rb +1 -1
- data/test/hexapdf/type/signature/common.rb +1 -1
- data/test/hexapdf/type/test_font_type0.rb +1 -1
- data/test/hexapdf/type/test_font_type1.rb +7 -7
- data/test/hexapdf/type/test_image.rb +13 -17
- metadata +4 -2
@@ -604,6 +604,26 @@ describe HexaPDF::Layout::Style do
|
|
604
604
|
end
|
605
605
|
end
|
606
606
|
|
607
|
+
describe "self.create" do
|
608
|
+
it "returns the provided style argument" do
|
609
|
+
assert_same(@style, HexaPDF::Layout::Style.create(@style))
|
610
|
+
end
|
611
|
+
|
612
|
+
it "creates a new Style object based on the passed hash" do
|
613
|
+
style = HexaPDF::Layout::Style.create(font_size: 10, fill_color: 'green')
|
614
|
+
assert_equal(10, style.font_size)
|
615
|
+
assert_equal('green', style.fill_color)
|
616
|
+
end
|
617
|
+
|
618
|
+
it "creates an empty Style object if nil is passed" do
|
619
|
+
assert_kind_of(HexaPDF::Layout::Style, HexaPDF::Layout::Style.create(nil))
|
620
|
+
end
|
621
|
+
|
622
|
+
it "raises an error if an invalid object is provided" do
|
623
|
+
assert_raises(ArgumentError) { HexaPDF::Layout::Style.create(5) }
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
607
627
|
it "can assign values on initialization" do
|
608
628
|
style = HexaPDF::Layout::Style.new(font_size: 10)
|
609
629
|
assert_equal(10, style.font_size)
|
@@ -692,6 +712,9 @@ describe HexaPDF::Layout::Style do
|
|
692
712
|
|
693
713
|
@style.stroke_dash_pattern(5, 2)
|
694
714
|
assert_equal([[5], 2], @style.stroke_dash_pattern.to_operands)
|
715
|
+
|
716
|
+
@style.line_spacing(1.2)
|
717
|
+
assert_equal([:proportional, 1.2], [@style.line_spacing.type, @style.line_spacing.value])
|
695
718
|
end
|
696
719
|
|
697
720
|
it "allows checking for valid values" do
|
@@ -20,7 +20,7 @@ describe HexaPDF::Layout::TextFragment do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
describe "create" do
|
23
|
-
it "creates a TextFragment from text and
|
23
|
+
it "creates a TextFragment from text and style" do
|
24
24
|
frag = HexaPDF::Layout::TextFragment.create("Tom", font: @font, font_size: 20,
|
25
25
|
font_features: {kern: true})
|
26
26
|
assert_equal(4, frag.items.length)
|
@@ -180,16 +180,16 @@ describe HexaPDF::Layout::TextFragment do
|
|
180
180
|
[:set_line_width, [5]],
|
181
181
|
[:set_line_cap_style, [1]],
|
182
182
|
[:set_line_dash_pattern, [[5], 0]]],
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
183
|
+
back: [[:end_text],
|
184
|
+
[:save_graphics_state],
|
185
|
+
[:set_device_gray_stroking_color, [0]],
|
186
|
+
[:set_line_width, [@fragment.style.calculated_underline_thickness]],
|
187
|
+
[:set_line_cap_style, [0]],
|
188
|
+
[:set_line_dash_pattern, [[], 0]],
|
189
|
+
[:move_to, [10, 15]],
|
190
|
+
[:line_to, [40.88, 15]],
|
191
|
+
[:stroke_path],
|
192
|
+
[:restore_graphics_state]])
|
193
193
|
end
|
194
194
|
|
195
195
|
it "draws the strikeout line" do
|
@@ -201,16 +201,16 @@ describe HexaPDF::Layout::TextFragment do
|
|
201
201
|
[:set_line_width, [5]],
|
202
202
|
[:set_line_cap_style, [1]],
|
203
203
|
[:set_line_dash_pattern, [[5], 0]]],
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
204
|
+
back: [[:end_text],
|
205
|
+
[:save_graphics_state],
|
206
|
+
[:set_device_gray_stroking_color, [0]],
|
207
|
+
[:set_line_width, [@fragment.style.calculated_strikeout_thickness]],
|
208
|
+
[:set_line_cap_style, [0]],
|
209
|
+
[:set_line_dash_pattern, [[], 0]],
|
210
|
+
[:move_to, [10, 21.01]],
|
211
|
+
[:line_to, [40.88, 21.01]],
|
212
|
+
[:stroke_path],
|
213
|
+
[:restore_graphics_state]])
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
@@ -19,7 +19,7 @@ describe HexaPDF::Composer do
|
|
19
19
|
assert_equal(36, @composer.frame.bottom)
|
20
20
|
assert_equal(523, @composer.frame.width)
|
21
21
|
assert_equal(770, @composer.frame.height)
|
22
|
-
|
22
|
+
assert_kind_of(HexaPDF::Layout::Style, @composer.style(:base))
|
23
23
|
end
|
24
24
|
|
25
25
|
it "allows the customization of the page size" do
|
@@ -86,83 +86,144 @@ describe HexaPDF::Composer do
|
|
86
86
|
assert_equal(806, @composer.y)
|
87
87
|
end
|
88
88
|
|
89
|
+
describe "style" do
|
90
|
+
it "creates a new style if it does not exist based on the base argument" do
|
91
|
+
@composer.style(:base, font_size: 20)
|
92
|
+
assert_equal(20, @composer.style(:newstyle, subscript: true).font_size)
|
93
|
+
refute( @composer.style(:base).subscript)
|
94
|
+
assert_equal(10, @composer.style(:another_new, base: nil).font_size)
|
95
|
+
assert(@composer.style(:yet_another_new, base: :newstyle).subscript)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns the named style" do
|
99
|
+
assert_kind_of(HexaPDF::Layout::Style, @composer.style(:base))
|
100
|
+
end
|
101
|
+
|
102
|
+
it "updates the style with the given properties" do
|
103
|
+
assert_equal(20, @composer.style(:base, font_size: 20).font_size)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
89
107
|
describe "text" do
|
90
|
-
|
91
|
-
|
92
|
-
@composer.define_singleton_method(:draw_box)
|
108
|
+
before do
|
109
|
+
test_self = self
|
110
|
+
@composer.define_singleton_method(:draw_box) do |arg|
|
111
|
+
test_self.instance_variable_set(:@box, arg)
|
112
|
+
end
|
113
|
+
end
|
93
114
|
|
115
|
+
it "creates a text box and draws it on the canvas" do
|
94
116
|
@composer.text("Test", width: 10, height: 15)
|
95
|
-
assert_equal(10, box.width)
|
96
|
-
assert_equal(15, box.height)
|
97
|
-
assert_same(@composer.document.fonts.add("Times"), box.style.font)
|
98
|
-
items = box.instance_variable_get(:@items)
|
117
|
+
assert_equal(10, @box.width)
|
118
|
+
assert_equal(15, @box.height)
|
119
|
+
assert_same(@composer.document.fonts.add("Times"), @box.style.font)
|
120
|
+
items = @box.instance_variable_get(:@items)
|
99
121
|
assert_equal(1, items.length)
|
100
|
-
assert_same(box.style, items.first.style)
|
122
|
+
assert_same(@box.style, items.first.style)
|
101
123
|
end
|
102
124
|
|
103
125
|
it "allows setting of a custom style" do
|
104
|
-
|
105
|
-
@composer.
|
106
|
-
|
107
|
-
@composer.
|
108
|
-
|
109
|
-
|
126
|
+
style = HexaPDF::Layout::Style.new(font_size: 20, font: ['Times', {variant: :bold}])
|
127
|
+
@composer.text("Test", style: style)
|
128
|
+
assert_same(@box.style, style)
|
129
|
+
assert_same(@composer.document.fonts.add("Times", variant: :bold), @box.style.font)
|
130
|
+
assert_equal(20, @box.style.font_size)
|
131
|
+
|
132
|
+
@composer.text("Test", style: {font_size: 20})
|
133
|
+
assert_equal(20, @box.style.font_size)
|
134
|
+
|
135
|
+
@composer.style(:named, font_size: 20)
|
136
|
+
@composer.text("Test", style: :named)
|
137
|
+
assert_equal(20, @box.style.font_size)
|
110
138
|
end
|
111
139
|
|
112
140
|
it "updates the used style with the provided options" do
|
113
|
-
|
114
|
-
@
|
141
|
+
@composer.text("Test", style: {subscript: true}, font_size: 20)
|
142
|
+
assert_equal(20, @box.style.font_size)
|
143
|
+
end
|
115
144
|
|
116
|
-
|
117
|
-
|
145
|
+
it "allows using a box style different from the text style" do
|
146
|
+
style = HexaPDF::Layout::Style.new(font_size: 20)
|
147
|
+
@composer.text("Test", box_style: style)
|
148
|
+
refute_same(@box.instance_variable_get(:@items).first.style, style)
|
149
|
+
assert_same(@box.style, style)
|
150
|
+
|
151
|
+
@composer.style(:named, font_size: 20)
|
152
|
+
@composer.text("Test", box_style: :named)
|
153
|
+
assert_equal(20, @box.style.font_size)
|
118
154
|
end
|
119
155
|
end
|
120
156
|
|
121
157
|
describe "formatted_text" do
|
122
|
-
|
123
|
-
|
124
|
-
@composer.define_singleton_method(:draw_box)
|
158
|
+
before do
|
159
|
+
test_self = self
|
160
|
+
@composer.define_singleton_method(:draw_box) do |arg|
|
161
|
+
test_self.instance_variable_set(:@box, arg)
|
162
|
+
end
|
163
|
+
end
|
125
164
|
|
165
|
+
it "creates a text box with the given text and draws it on the canvas" do
|
126
166
|
@composer.formatted_text(["Test"], width: 10, height: 15)
|
127
|
-
assert_equal(10, box.width)
|
128
|
-
assert_equal(15, box.height)
|
129
|
-
assert_equal(1, box.instance_variable_get(:@items).length)
|
167
|
+
assert_equal(10, @box.width)
|
168
|
+
assert_equal(15, @box.height)
|
169
|
+
assert_equal(1, @box.instance_variable_get(:@items).length)
|
130
170
|
end
|
131
171
|
|
132
|
-
it "a hash
|
133
|
-
|
134
|
-
@
|
172
|
+
it "allows using a hash with :text key instead of a simple string" do
|
173
|
+
@composer.formatted_text([{text: "Test"}])
|
174
|
+
items = @box.instance_variable_get(:@items)
|
175
|
+
assert_equal(4, items[0].items.length)
|
176
|
+
end
|
135
177
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
assert_equal(
|
140
|
-
assert_equal(:center, items.first.style.align)
|
141
|
-
assert_equal(10, box.style.font_size)
|
178
|
+
it "uses an empty string if the :text key for a hash is not specified" do
|
179
|
+
@composer.formatted_text([{font_size: "Test"}])
|
180
|
+
items = @box.instance_variable_get(:@items)
|
181
|
+
assert_equal(0, items[0].items.length)
|
142
182
|
end
|
143
183
|
|
144
|
-
it "
|
145
|
-
|
146
|
-
@
|
184
|
+
it "allows setting a custom base style for all parts" do
|
185
|
+
@composer.formatted_text(["Test", "other"], font_size: 20)
|
186
|
+
items = @box.instance_variable_get(:@items)
|
187
|
+
assert_equal(20, @box.style.font_size)
|
188
|
+
assert_equal(20, items[0].style.font_size)
|
189
|
+
assert_equal(20, items[1].style.font_size)
|
190
|
+
end
|
191
|
+
|
192
|
+
it "allows using custom style properties for a single part" do
|
193
|
+
@composer.formatted_text([{text: "Test", font_size: 20}, "test"], align: :center)
|
194
|
+
items = @box.instance_variable_get(:@items)
|
195
|
+
assert_equal(10, @box.style.font_size)
|
147
196
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
assert_equal(
|
152
|
-
assert_equal(
|
153
|
-
assert_equal(:center, items.first.style.align)
|
197
|
+
assert_equal(20, items[0].style.font_size)
|
198
|
+
assert_equal(:center, items[0].style.align)
|
199
|
+
|
200
|
+
assert_equal(10, items[1].style.font_size)
|
201
|
+
assert_equal(:center, items[1].style.align)
|
154
202
|
end
|
155
203
|
|
156
|
-
it "a
|
157
|
-
|
158
|
-
|
204
|
+
it "allows using a custom style as basis for a single part" do
|
205
|
+
@composer.formatted_text([{text: "Test", style: {font_size: 20}, subscript: true}, "test"],
|
206
|
+
align: :center)
|
207
|
+
items = @box.instance_variable_get(:@items)
|
208
|
+
assert_equal(10, @box.style.font_size)
|
159
209
|
|
160
|
-
|
161
|
-
items
|
162
|
-
|
163
|
-
|
164
|
-
assert_equal(
|
210
|
+
assert_equal(20, items[0].style.font_size)
|
211
|
+
assert_equal(:left, items[0].style.align)
|
212
|
+
assert(items[0].style.subscript)
|
213
|
+
|
214
|
+
assert_equal(10, items[1].style.font_size)
|
215
|
+
assert_equal(:center, items[1].style.align)
|
216
|
+
refute(items[1].style.subscript)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "allows specifying a link to an URL via the :link key" do
|
220
|
+
@composer.formatted_text([{text: "Test", link: "URI"}, {link: "URI"}, "test"])
|
221
|
+
items = @box.instance_variable_get(:@items)
|
222
|
+
assert_equal(3, items.length)
|
223
|
+
assert_equal(4, items[0].items.length, "text should be Test")
|
224
|
+
assert_equal(3, items[1].items.length, "text should be URI")
|
165
225
|
assert_equal([:link, {uri: 'URI'}], items[0].style.overlays.instance_variable_get(:@layers)[0])
|
226
|
+
refute(items[2].style.overlays?)
|
166
227
|
end
|
167
228
|
end
|
168
229
|
|
@@ -172,9 +233,11 @@ describe HexaPDF::Composer do
|
|
172
233
|
@composer.define_singleton_method(:draw_box) {|arg| box = arg }
|
173
234
|
image_path = File.join(TEST_DATA_DIR, 'images', 'gray.jpg')
|
174
235
|
|
175
|
-
@composer.image(image_path, width: 10, height: 15)
|
236
|
+
@composer.image(image_path, width: 10, height: 15, style: {font_size: 20}, subscript: true)
|
176
237
|
assert_equal(10, box.width)
|
177
238
|
assert_equal(15, box.height)
|
239
|
+
assert_equal(20, box.style.font_size)
|
240
|
+
assert(box.style.subscript)
|
178
241
|
assert_same(@composer.document.images.add(image_path), box.image)
|
179
242
|
end
|
180
243
|
end
|
@@ -476,16 +476,14 @@ describe HexaPDF::Document do
|
|
476
476
|
|
477
477
|
describe "write" do
|
478
478
|
it "writes the document to a file" do
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
assert_equal(200, doc.object(2).value)
|
485
|
-
end
|
486
|
-
ensure
|
487
|
-
file.unlink
|
479
|
+
file = Tempfile.new('hexapdf-write')
|
480
|
+
file.close
|
481
|
+
@io_doc.write(file.path)
|
482
|
+
HexaPDF::Document.open(file.path) do |doc|
|
483
|
+
assert_equal(200, doc.object(2).value)
|
488
484
|
end
|
485
|
+
ensure
|
486
|
+
file.unlink
|
489
487
|
end
|
490
488
|
|
491
489
|
it "writes the document to an IO object" do
|
@@ -666,4 +664,8 @@ describe HexaPDF::Document do
|
|
666
664
|
assert_raises(LocalJumpError) { @doc.cache(:a, :b) }
|
667
665
|
end
|
668
666
|
end
|
667
|
+
|
668
|
+
it "can be inspected and the output is not too large" do
|
669
|
+
assert_match(/HexaPDF::Document:\d+/, @doc.inspect)
|
670
|
+
end
|
669
671
|
end
|
data/test/hexapdf/test_object.rb
CHANGED
@@ -68,7 +68,7 @@ describe HexaPDF::Object do
|
|
68
68
|
|
69
69
|
it "works for arrays" do
|
70
70
|
obj = HexaPDF::PDFArray.new([:b, HexaPDF::Object.new(:a, oid: 3, document: @doc)],
|
71
|
-
|
71
|
+
oid: 1, document: @doc)
|
72
72
|
assert_equal([:b, :a], HexaPDF::Object.make_direct(obj))
|
73
73
|
end
|
74
74
|
end
|
data/test/hexapdf/test_parser.rb
CHANGED
@@ -109,7 +109,7 @@ describe HexaPDF::Parser do
|
|
109
109
|
|
110
110
|
it "treats indirect objects with invalid values as null objects" do
|
111
111
|
create_parser("1 0 obj <</test ( /other (end)>> endobj")
|
112
|
-
object, * =
|
112
|
+
object, * = @parser.parse_indirect_object
|
113
113
|
assert_nil(object)
|
114
114
|
end
|
115
115
|
|
@@ -475,33 +475,33 @@ describe HexaPDF::Parser do
|
|
475
475
|
describe "invalid numbering of main xref section" do
|
476
476
|
it "handles the xref if the numbering is off by N" do
|
477
477
|
create_parser(" 1 0 obj 1 endobj\n" \
|
478
|
-
|
478
|
+
"xref\n1 2\n0000000000 65535 f \n0000000001 00000 n \ntrailer\n<<>>\n")
|
479
479
|
section, _trailer = @parser.parse_xref_section_and_trailer(17)
|
480
480
|
assert_equal(HexaPDF::XRefSection.in_use_entry(1, 0, 1), section[1])
|
481
481
|
end
|
482
482
|
|
483
483
|
it "fails if the first entry is not the one for oid=0" do
|
484
484
|
create_parser(" 1 0 obj 1 endobj\n" \
|
485
|
-
|
485
|
+
"xref\n1 2\n0000000000 00005 f \n0000000001 00000 n \ntrailer\n<<>>\n")
|
486
486
|
exp = assert_raises(HexaPDF::MalformedPDFError) { @parser.parse_xref_section_and_trailer(17) }
|
487
487
|
assert_match(/Main.*invalid numbering/i, exp.message)
|
488
488
|
|
489
489
|
create_parser(" 1 0 obj 1 endobj\n" \
|
490
|
-
|
490
|
+
"xref\n1 2\n0000000001 00000 n \n0000000001 00000 n \ntrailer\n<<>>\n")
|
491
491
|
exp = assert_raises(HexaPDF::MalformedPDFError) { @parser.parse_xref_section_and_trailer(17) }
|
492
492
|
assert_match(/Main.*invalid numbering/i, exp.message)
|
493
493
|
end
|
494
494
|
|
495
495
|
it "fails if the tested entry position is invalid" do
|
496
496
|
create_parser(" 1 0 obj 1 endobj\n" \
|
497
|
-
|
497
|
+
"xref\n1 2\n0000000000 65535 f \n0000000005 00000 n \ntrailer\n<<>>\n")
|
498
498
|
exp = assert_raises(HexaPDF::MalformedPDFError) { @parser.parse_xref_section_and_trailer(17) }
|
499
499
|
assert_match(/Main.*invalid numbering/i, exp.message)
|
500
500
|
end
|
501
501
|
|
502
502
|
it "fails if the tested entry position's oid doesn't match the corrected entry oid" do
|
503
503
|
create_parser(" 2 0 obj 1 endobj\n" \
|
504
|
-
|
504
|
+
"xref\n1 2\n0000000000 65535 f \n0000000001 00000 n \ntrailer\n<<>>\n")
|
505
505
|
exp = assert_raises(HexaPDF::MalformedPDFError) { @parser.parse_xref_section_and_trailer(17) }
|
506
506
|
assert_match(/Main.*invalid numbering/i, exp.message)
|
507
507
|
end
|
@@ -580,6 +580,12 @@ describe HexaPDF::Parser do
|
|
580
580
|
@xref = HexaPDF::XRefSection.in_use_entry(1, 0, 100)
|
581
581
|
end
|
582
582
|
|
583
|
+
it "can tell us if the cross-reference table was reconstructed" do
|
584
|
+
create_parser("1 0 obj\n5\nendobj\ntrailer\n<</Size 1>>")
|
585
|
+
@parser.load_object(@xref)
|
586
|
+
assert(@parser.reconstructed?)
|
587
|
+
end
|
588
|
+
|
583
589
|
it "serially parses the contents" do
|
584
590
|
create_parser("1 0 obj\n5\nendobj\n1 0 obj\n6\nendobj\ntrailer\n<</Size 1>>")
|
585
591
|
assert_equal(6, @parser.load_object(@xref).value)
|
@@ -643,7 +649,7 @@ describe HexaPDF::Parser do
|
|
643
649
|
end
|
644
650
|
|
645
651
|
it "uses the first trailer in case of a linearized file" do
|
646
|
-
create_parser("1 0 obj\n<</Linearized true>>\nendobj\ntrailer <</Size 1/Prev
|
652
|
+
create_parser("1 0 obj\n<</Linearized true>>\nendobj\ntrailer <</Size 1/Prev 34>>\ntrailer <</Size 2>>")
|
647
653
|
assert_equal({Size: 1}, @parser.reconstructed_revision.trailer.value)
|
648
654
|
end
|
649
655
|
|
@@ -70,16 +70,16 @@ describe HexaPDF::Serializer do
|
|
70
70
|
|
71
71
|
it "serializes symbols" do
|
72
72
|
assert_serialized("/Name", :Name)
|
73
|
-
assert_serialized("/A;Name_With-Various***Chars?", 'A;Name_With-Various***Chars?'
|
74
|
-
assert_serialized("/1.2", '1.2'
|
75
|
-
assert_serialized("/$$",
|
76
|
-
assert_serialized("/@pattern",
|
77
|
-
assert_serialized('/.notdef', '.notdef'
|
78
|
-
assert_serialized('/lime#20Green', 'lime Green'
|
79
|
-
assert_serialized('/paired#28#29parentheses', 'paired()parentheses'
|
80
|
-
assert_serialized('/The_Key_of_F#23_Minor', 'The_Key_of_F#_Minor'
|
81
|
-
assert_serialized('/ ',
|
82
|
-
assert_serialized('/H#c3#b6#c3#9fgang',
|
73
|
+
assert_serialized("/A;Name_With-Various***Chars?", :'A;Name_With-Various***Chars?')
|
74
|
+
assert_serialized("/1.2", :'1.2')
|
75
|
+
assert_serialized("/$$", :$$)
|
76
|
+
assert_serialized("/@pattern", :@pattern)
|
77
|
+
assert_serialized('/.notdef', :'.notdef')
|
78
|
+
assert_serialized('/lime#20Green', :'lime Green')
|
79
|
+
assert_serialized('/paired#28#29parentheses', :'paired()parentheses')
|
80
|
+
assert_serialized('/The_Key_of_F#23_Minor', :'The_Key_of_F#_Minor')
|
81
|
+
assert_serialized('/ ', :"")
|
82
|
+
assert_serialized('/H#c3#b6#c3#9fgang', :Hößgang)
|
83
83
|
assert_serialized('/H#e8lp', "H\xE8lp".force_encoding('BINARY').intern)
|
84
84
|
end
|
85
85
|
|
@@ -101,18 +101,16 @@ describe HexaPDF::Serializer do
|
|
101
101
|
end
|
102
102
|
|
103
103
|
it "serializes time like objects" do
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
ENV['TZ'] = tz
|
115
|
-
end
|
104
|
+
tz = ENV['TZ']
|
105
|
+
ENV['TZ'] = 'Europe/Vienna'
|
106
|
+
assert_serialized("(D:20150416094100)", Time.new(2015, 04, 16, 9, 41, 0, 0))
|
107
|
+
assert_serialized("(D:20150416094100+01'00')", Time.new(2015, 04, 16, 9, 41, 0, 3600))
|
108
|
+
assert_serialized("(D:20150416094100-01'20')", Time.new(2015, 04, 16, 9, 41, 0, -4800))
|
109
|
+
assert_serialized("(D:20150416000000+02'00')", Date.parse("2015-04-16 9:41:00 +02:00"))
|
110
|
+
assert_serialized("(D:20150416094100+02'00')",
|
111
|
+
Time.parse("2015-04-16 9:41:00 +02:00").to_datetime)
|
112
|
+
ensure
|
113
|
+
ENV['TZ'] = tz
|
116
114
|
end
|
117
115
|
|
118
116
|
it "serializes HexaPDF objects" do
|
data/test/hexapdf/test_stream.rb
CHANGED
@@ -47,15 +47,13 @@ describe HexaPDF::StreamData do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
it "returns a fiber for a string representing a file name" do
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
file.unlink
|
58
|
-
end
|
50
|
+
file = Tempfile.new('hexapdf-stream')
|
51
|
+
file.write('source')
|
52
|
+
file.close
|
53
|
+
s = HexaPDF::StreamData.new(file.path)
|
54
|
+
assert_equal('source', s.fiber.resume)
|
55
|
+
ensure
|
56
|
+
file.unlink
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
data/test/hexapdf/test_writer.rb
CHANGED
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
|
|
40
40
|
219
|
41
41
|
%%EOF
|
42
42
|
3 0 obj
|
43
|
-
<</Producer(HexaPDF version 0.
|
43
|
+
<</Producer(HexaPDF version 0.21.1)>>
|
44
44
|
endobj
|
45
45
|
xref
|
46
46
|
3 1
|
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
|
|
72
72
|
141
|
73
73
|
%%EOF
|
74
74
|
6 0 obj
|
75
|
-
<</Producer(HexaPDF version 0.
|
75
|
+
<</Producer(HexaPDF version 0.21.1)>>
|
76
76
|
endobj
|
77
77
|
2 0 obj
|
78
78
|
<</Length 10>>stream
|
@@ -120,7 +120,7 @@ describe HexaPDF::Type::AcroForm::ChoiceField do
|
|
120
120
|
|
121
121
|
describe "option items" do
|
122
122
|
before do
|
123
|
-
@items = [["a", "Zx"], "\xFE\xFF".b << "Töne".encode('UTF-16BE').b, "H\xe4llo".b
|
123
|
+
@items = [["a", "Zx"], "\xFE\xFF".b << "Töne".encode('UTF-16BE').b, "H\xe4llo".b]
|
124
124
|
end
|
125
125
|
|
126
126
|
it "sets the option items" do
|
@@ -112,7 +112,7 @@ describe HexaPDF::Type::FontType0 do
|
|
112
112
|
end
|
113
113
|
|
114
114
|
it "calls the configured proc if no mapping is available" do
|
115
|
-
@font[:Encoding] = :
|
115
|
+
@font[:Encoding] = :'Identity-H'
|
116
116
|
@cid_font[:CIDSystemInfo][:Registry] = :Unknown
|
117
117
|
assert_raises(HexaPDF::Error) { @font.to_utf8(32) }
|
118
118
|
end
|
@@ -10,24 +10,24 @@ describe HexaPDF::Type::FontType1::StandardFonts do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "checks whether a given name corresponds to a standard font via #standard_font?" do
|
13
|
-
assert(@obj.standard_font?(:
|
13
|
+
assert(@obj.standard_font?(:'Times-Roman'))
|
14
14
|
assert(@obj.standard_font?(:TimesNewRoman))
|
15
15
|
refute(@obj.standard_font?(:LibreSans))
|
16
16
|
end
|
17
17
|
|
18
18
|
it "returns the standard PDF name for an alias via #standard_name" do
|
19
|
-
assert_equal(:
|
19
|
+
assert_equal(:'Times-Roman', @obj.standard_name(:TimesNewRoman))
|
20
20
|
end
|
21
21
|
|
22
22
|
describe "font" do
|
23
23
|
it "returns the Type1 font object for a given standard name" do
|
24
|
-
font = @obj.font(:
|
24
|
+
font = @obj.font(:'Times-Roman')
|
25
25
|
assert_equal("Times Roman", font.full_name)
|
26
26
|
end
|
27
27
|
|
28
28
|
it "caches the font for reuse" do
|
29
|
-
font = @obj.font(:
|
30
|
-
assert_same(font, @obj.font(:
|
29
|
+
font = @obj.font(:'Times-Roman')
|
30
|
+
assert_same(font, @obj.font(:'Times-Roman'))
|
31
31
|
end
|
32
32
|
|
33
33
|
it "returns nil if the given name doesn't belong to a standard font" do
|
@@ -40,7 +40,7 @@ describe HexaPDF::Type::FontType1 do
|
|
40
40
|
before do
|
41
41
|
@doc = HexaPDF::Document.new
|
42
42
|
@font = @doc.add({Type: :Font, Subtype: :Type1, Encoding: :WinAnsiEncoding,
|
43
|
-
BaseFont: :
|
43
|
+
BaseFont: :'Times-Roman'})
|
44
44
|
|
45
45
|
font_file = @doc.add({}, stream: <<-EOF)
|
46
46
|
/Encoding 256 array
|
@@ -95,7 +95,7 @@ describe HexaPDF::Type::FontType1 do
|
|
95
95
|
|
96
96
|
describe "bounding_box" do
|
97
97
|
it "returns the bounding box for a standard font" do
|
98
|
-
font = HexaPDF::Type::FontType1::StandardFonts.font(:
|
98
|
+
font = HexaPDF::Type::FontType1::StandardFonts.font(:'Times-Roman')
|
99
99
|
assert_equal(font.bounding_box, @font.bounding_box)
|
100
100
|
end
|
101
101
|
|