hexapdf 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTERS +1 -1
- data/Rakefile +35 -50
- data/VERSION +1 -1
- data/lib/hexapdf/cli.rb +4 -0
- data/lib/hexapdf/cli/command.rb +6 -2
- data/lib/hexapdf/cli/image2pdf.rb +141 -0
- data/lib/hexapdf/cli/info.rb +1 -1
- data/lib/hexapdf/cli/inspect.rb +32 -2
- data/lib/hexapdf/cli/modify.rb +1 -1
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +130 -0
- data/lib/hexapdf/composer.rb +2 -2
- data/lib/hexapdf/configuration.rb +7 -1
- data/lib/hexapdf/content/canvas.rb +2 -2
- data/lib/hexapdf/content/graphic_object/arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -2
- data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/dictionary.rb +11 -3
- data/lib/hexapdf/dictionary_fields.rb +32 -3
- data/lib/hexapdf/document.rb +7 -3
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +21 -1
- data/lib/hexapdf/document/pages.rb +2 -2
- data/lib/hexapdf/encryption/standard_security_handler.rb +2 -2
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +2 -2
- data/lib/hexapdf/font/true_type/table/os2.rb +4 -4
- data/lib/hexapdf/font/true_type_wrapper.rb +16 -16
- data/lib/hexapdf/font/type1_wrapper.rb +16 -16
- data/lib/hexapdf/font_loader.rb +2 -0
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -0
- data/lib/hexapdf/font_loader/standard14.rb +5 -0
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/layout/box.rb +2 -2
- data/lib/hexapdf/layout/image_box.rb +1 -1
- data/lib/hexapdf/layout/style.rb +50 -24
- data/lib/hexapdf/layout/text_box.rb +1 -1
- data/lib/hexapdf/layout/text_fragment.rb +2 -2
- data/lib/hexapdf/layout/text_layouter.rb +14 -10
- data/lib/hexapdf/name_tree_node.rb +3 -3
- data/lib/hexapdf/number_tree_node.rb +3 -3
- data/lib/hexapdf/pdf_array.rb +207 -0
- data/lib/hexapdf/rectangle.rb +12 -12
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +6 -4
- data/lib/hexapdf/task/optimize.rb +3 -3
- data/lib/hexapdf/type.rb +2 -0
- data/lib/hexapdf/type/acro_form.rb +51 -0
- data/lib/hexapdf/type/acro_form/field.rb +129 -0
- data/lib/hexapdf/type/acro_form/form.rb +124 -0
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -0
- data/lib/hexapdf/type/annotations/link.rb +4 -15
- data/lib/hexapdf/type/annotations/markup_annotation.rb +2 -1
- data/lib/hexapdf/type/annotations/text.rb +3 -6
- data/lib/hexapdf/type/annotations/widget.rb +90 -0
- data/lib/hexapdf/type/catalog.rb +12 -9
- data/lib/hexapdf/type/cid_font.rb +3 -3
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +5 -2
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +2 -2
- data/lib/hexapdf/type/graphics_state_parameter.rb +11 -6
- data/lib/hexapdf/type/icon_fit.rb +58 -0
- data/lib/hexapdf/type/image.rb +14 -8
- data/lib/hexapdf/type/info.rb +2 -1
- data/lib/hexapdf/type/page.rb +4 -4
- data/lib/hexapdf/type/page_tree_node.rb +3 -7
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +4 -4
- data/lib/hexapdf/type/viewer_preferences.rb +7 -4
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/utils/sorted_tree_node.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/man/man1/hexapdf.1 +77 -8
- data/test/hexapdf/content/test_canvas.rb +2 -2
- data/test/hexapdf/content/test_processor.rb +3 -3
- data/test/hexapdf/document/test_files.rb +4 -4
- data/test/hexapdf/document/test_fonts.rb +13 -1
- data/test/hexapdf/document/test_images.rb +6 -6
- data/test/hexapdf/document/test_pages.rb +8 -8
- data/test/hexapdf/encryption/test_security_handler.rb +7 -7
- data/test/hexapdf/encryption/test_standard_security_handler.rb +5 -5
- data/test/hexapdf/font/test_true_type_wrapper.rb +2 -2
- data/test/hexapdf/font_loader/test_from_configuration.rb +4 -0
- data/test/hexapdf/font_loader/test_standard14.rb +10 -0
- data/test/hexapdf/image_loader/test_jpeg.rb +1 -1
- data/test/hexapdf/image_loader/test_png.rb +3 -3
- data/test/hexapdf/layout/test_box.rb +2 -2
- data/test/hexapdf/layout/test_frame.rb +1 -1
- data/test/hexapdf/layout/test_image_box.rb +1 -1
- data/test/hexapdf/layout/test_style.rb +18 -13
- data/test/hexapdf/layout/test_text_box.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +11 -6
- data/test/hexapdf/task/test_dereference.rb +2 -2
- data/test/hexapdf/task/test_optimize.rb +11 -11
- data/test/hexapdf/test_composer.rb +1 -1
- data/test/hexapdf/test_dictionary.rb +10 -2
- data/test/hexapdf/test_dictionary_fields.rb +27 -3
- data/test/hexapdf/test_document.rb +16 -15
- data/test/hexapdf/test_importer.rb +4 -4
- data/test/hexapdf/test_object.rb +1 -1
- data/test/hexapdf/test_pdf_array.rb +162 -0
- data/test/hexapdf/test_rectangle.rb +3 -5
- data/test/hexapdf/test_serializer.rb +1 -1
- data/test/hexapdf/test_stream.rb +1 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_field.rb +85 -0
- data/test/hexapdf/type/acro_form/test_form.rb +69 -0
- data/test/hexapdf/type/annotations/test_text.rb +2 -6
- data/test/hexapdf/type/annotations/test_widget.rb +24 -0
- data/test/hexapdf/type/test_annotation.rb +1 -1
- data/test/hexapdf/type/test_catalog.rb +1 -1
- data/test/hexapdf/type/test_cid_font.rb +3 -3
- data/test/hexapdf/type/test_font.rb +2 -2
- data/test/hexapdf/type/test_font_descriptor.rb +2 -1
- data/test/hexapdf/type/test_font_simple.rb +3 -3
- data/test/hexapdf/type/test_font_true_type.rb +6 -6
- data/test/hexapdf/type/test_font_type0.rb +5 -5
- data/test/hexapdf/type/test_font_type1.rb +8 -8
- data/test/hexapdf/type/test_font_type3.rb +4 -4
- data/test/hexapdf/type/test_image.rb +16 -12
- data/test/hexapdf/type/test_page.rb +11 -11
- data/test/hexapdf/type/test_page_tree_node.rb +20 -20
- data/test/hexapdf/type/test_resources.rb +6 -6
- data/test/hexapdf/type/test_trailer.rb +5 -2
- data/test/hexapdf/type/test_xref_stream.rb +1 -0
- data/test/hexapdf/utils/test_sorted_tree_node.rb +35 -35
- metadata +23 -7
- data/test/hexapdf/type/annotations/test_link.rb +0 -19
@@ -777,9 +777,9 @@ describe HexaPDF::Content::Canvas do
|
|
777
777
|
|
778
778
|
describe "xobject" do
|
779
779
|
before do
|
780
|
-
@image = @doc.add(Type: :XObject, Subtype: :Image, Width: 10, Height: 5)
|
780
|
+
@image = @doc.add({Type: :XObject, Subtype: :Image, Width: 10, Height: 5})
|
781
781
|
@image.source_path = File.join(TEST_DATA_DIR, 'images', 'gray.jpg')
|
782
|
-
@form = @doc.add(Type: :XObject, Subtype: :Form, BBox: [100, 50, 200, 100])
|
782
|
+
@form = @doc.add({Type: :XObject, Subtype: :Form, BBox: [100, 50, 200, 100]})
|
783
783
|
end
|
784
784
|
|
785
785
|
it "can use any xobject specified via a filename" do
|
@@ -117,9 +117,9 @@ describe HexaPDF::Content::Processor do
|
|
117
117
|
before do
|
118
118
|
@doc = HexaPDF::Document.new
|
119
119
|
@processor.process(:BT)
|
120
|
-
@processor.graphics_state.font = @font = @doc.add(Type: :Font, Subtype: :Type1,
|
121
|
-
|
122
|
-
|
120
|
+
@processor.graphics_state.font = @font = @doc.add({Type: :Font, Subtype: :Type1,
|
121
|
+
Encoding: :WinAnsiEncoding,
|
122
|
+
BaseFont: :"Times-Roman"})
|
123
123
|
@processor.graphics_state.font_size = 10
|
124
124
|
@processor.graphics_state.text_rise = 10
|
125
125
|
@processor.graphics_state.character_spacing = 1
|
@@ -50,9 +50,9 @@ describe HexaPDF::Document::Files do
|
|
50
50
|
|
51
51
|
describe "each" do
|
52
52
|
it "iterates only over named embedded files and file annotations if search=false" do
|
53
|
-
@doc.add(Type: :Filespec)
|
53
|
+
@doc.add({Type: :Filespec})
|
54
54
|
spec1 = @doc.files.add(__FILE__)
|
55
|
-
spec2 = @doc.add(Type: :Filespec)
|
55
|
+
spec2 = @doc.add({Type: :Filespec})
|
56
56
|
@doc.pages.add # page without annot
|
57
57
|
@doc.pages.add[:Annots] = [
|
58
58
|
{Subtype: :FileAttachment, FS: HexaPDF::Reference.new(spec1.oid, spec1.gen)},
|
@@ -64,8 +64,8 @@ describe HexaPDF::Document::Files do
|
|
64
64
|
|
65
65
|
it "iterates over all file specifications of the document if search=true" do
|
66
66
|
specs = []
|
67
|
-
specs << @doc.add(Type: :Filespec)
|
68
|
-
specs << @doc.add(Type: :Filespec)
|
67
|
+
specs << @doc.add({Type: :Filespec})
|
68
|
+
specs << @doc.add({Type: :Filespec})
|
69
69
|
assert_equal(specs, @doc.files.each(search: true).to_a)
|
70
70
|
end
|
71
71
|
end
|
@@ -37,7 +37,9 @@ describe HexaPDF::Document::Fonts do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "fails if the requested font is not found" do
|
40
|
-
|
40
|
+
@doc.config['font_loader'] << 'HexaPDF::FontLoader::Standard14'
|
41
|
+
error = assert_raises(HexaPDF::Error) { @doc.fonts.add("Unknown") }
|
42
|
+
assert_match(/Times \(none/, error.message)
|
41
43
|
end
|
42
44
|
|
43
45
|
it "raises an error if a font loader cannot be correctly retrieved" do
|
@@ -45,4 +47,14 @@ describe HexaPDF::Document::Fonts do
|
|
45
47
|
assert_raises(HexaPDF::Error) { @doc.fonts.add(:Other) }
|
46
48
|
end
|
47
49
|
end
|
50
|
+
|
51
|
+
it "returns the configured fonts" do
|
52
|
+
@doc.config['font_loader'] << 'HexaPDF::FontLoader::Standard14'
|
53
|
+
@doc.config['font_loader'] << 'HexaPDF::FontLoader::FromConfiguration'
|
54
|
+
@doc.config['font.map'] = {'Times' => {heavy: 'none', none: 'none'}, 'Other' => {none: 'none'}}
|
55
|
+
fonts = @doc.fonts.configured_fonts
|
56
|
+
assert_equal([:none], fonts['Symbol'])
|
57
|
+
assert_equal([:none, :bold, :italic, :bold_italic, :heavy], fonts['Times'])
|
58
|
+
assert_equal([:none], fonts['Other'])
|
59
|
+
end
|
48
60
|
end
|
@@ -60,12 +60,12 @@ describe HexaPDF::Document::Images do
|
|
60
60
|
it "iterates over all non-mask images" do
|
61
61
|
@doc.add(5)
|
62
62
|
images = []
|
63
|
-
images << @doc.add(Type: :XObject, Subtype: :Image)
|
64
|
-
images << @doc.add(Type: :XObject, Subtype: :Image, Mask: [5, 6])
|
65
|
-
images << @doc.add(Type: :XObject, Subtype: :Image,
|
66
|
-
|
67
|
-
images << @doc.add(Type: :XObject, Subtype: :Image,
|
68
|
-
|
63
|
+
images << @doc.add({Type: :XObject, Subtype: :Image})
|
64
|
+
images << @doc.add({Type: :XObject, Subtype: :Image, Mask: [5, 6]})
|
65
|
+
images << @doc.add({Type: :XObject, Subtype: :Image,
|
66
|
+
Mask: @doc.add({Type: :XObject, Subtype: :Image})})
|
67
|
+
images << @doc.add({Type: :XObject, Subtype: :Image,
|
68
|
+
SMask: @doc.add({Type: :XObject, Subtype: :Image})})
|
69
69
|
assert_equal(images.sort, @doc.images.to_a.sort)
|
70
70
|
end
|
71
71
|
end
|
@@ -17,7 +17,7 @@ describe HexaPDF::Document::Pages do
|
|
17
17
|
describe "add" do
|
18
18
|
it "adds a new empty page when no page is given" do
|
19
19
|
page = @doc.pages.add
|
20
|
-
assert_equal([page], @doc.pages.root[:Kids])
|
20
|
+
assert_equal([page], @doc.pages.root[:Kids].value)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "adds a new empty page with the given dimensions" do
|
@@ -34,9 +34,9 @@ describe HexaPDF::Document::Pages do
|
|
34
34
|
|
35
35
|
it "adds the given page to the end" do
|
36
36
|
page = @doc.pages.add
|
37
|
-
new_page = @doc.add(Type: :Page)
|
37
|
+
new_page = @doc.add({Type: :Page})
|
38
38
|
assert_same(new_page, @doc.pages.add(new_page))
|
39
|
-
assert_equal([page, new_page], @doc.pages.root[:Kids])
|
39
|
+
assert_equal([page, new_page], @doc.pages.root[:Kids].value)
|
40
40
|
end
|
41
41
|
|
42
42
|
it "fails if an unknown page format is given" do
|
@@ -46,10 +46,10 @@ describe HexaPDF::Document::Pages do
|
|
46
46
|
|
47
47
|
describe "<<" do
|
48
48
|
it "works like add but always needs a page returns self" do
|
49
|
-
page1 = @doc.add(Type: :Page)
|
50
|
-
page2 = @doc.add(Type: :Page)
|
49
|
+
page1 = @doc.add({Type: :Page})
|
50
|
+
page2 = @doc.add({Type: :Page})
|
51
51
|
@doc.pages << page1 << page2
|
52
|
-
assert_equal([page1, page2], @doc.pages.root[:Kids])
|
52
|
+
assert_equal([page1, page2], @doc.pages.root[:Kids].value)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
@@ -66,7 +66,7 @@ describe HexaPDF::Document::Pages do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it "insert a given page at a given index" do
|
69
|
-
new_page = @doc.add(Type: :Page)
|
69
|
+
new_page = @doc.add({Type: :Page})
|
70
70
|
assert_same(new_page, @doc.pages.insert(2, new_page))
|
71
71
|
assert_equal(new_page, @doc.pages.root[:Kids][2])
|
72
72
|
end
|
@@ -88,7 +88,7 @@ describe HexaPDF::Document::Pages do
|
|
88
88
|
page2 = @doc.pages.add
|
89
89
|
page3 = @doc.pages.add
|
90
90
|
assert_same(page2, @doc.pages.delete_at(1))
|
91
|
-
assert_equal([page1, page3], @doc.pages.root[:Kids])
|
91
|
+
assert_equal([page1, page3], @doc.pages.root[:Kids].value)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -201,14 +201,14 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
201
201
|
|
202
202
|
describe "set_up_decryption" do
|
203
203
|
it "wraps the given hash in an encryption dictionary class, uses it for its dict, returns it" do
|
204
|
-
dict = @handler.set_up_decryption(Filter: :test, V: 1)
|
204
|
+
dict = @handler.set_up_decryption({Filter: :test, V: 1})
|
205
205
|
assert_equal(dict, @handler.dict)
|
206
206
|
assert_kind_of(HexaPDF::Encryption::EncryptionDictionary, @handler.dict)
|
207
207
|
assert_equal({Filter: :test, V: 1}, @handler.dict.value)
|
208
208
|
end
|
209
209
|
|
210
210
|
it "doesn't modify the trailer's /Encrypt dictionary" do
|
211
|
-
@handler.set_up_decryption(Filter: :test, V: 4, Length: 128)
|
211
|
+
@handler.set_up_decryption({Filter: :test, V: 4, Length: 128})
|
212
212
|
assert_nil(@document.trailer[:Encrypt])
|
213
213
|
end
|
214
214
|
|
@@ -238,8 +238,8 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
238
238
|
end
|
239
239
|
|
240
240
|
it "selects the correct algorithm for string, stream and embedded file decryption" do
|
241
|
-
@handler.set_up_decryption(V: 4, StrF: :Mine, StmF: :Mine, EFF: :Mine,
|
242
|
-
|
241
|
+
@handler.set_up_decryption({V: 4, StrF: :Mine, StmF: :Mine, EFF: :Mine,
|
242
|
+
CF: {Mine: {CFM: :V2}}})
|
243
243
|
assert_equal(HexaPDF::Encryption::FastARC4, @handler.send(:embedded_file_algorithm))
|
244
244
|
assert_equal(HexaPDF::Encryption::FastARC4, @handler.send(:string_algorithm))
|
245
245
|
assert_equal(HexaPDF::Encryption::FastARC4, @handler.send(:stream_algorithm))
|
@@ -254,14 +254,14 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
254
254
|
|
255
255
|
it "fails for unsupported /V values in the dict" do
|
256
256
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
257
|
-
@handler.set_up_decryption(V: 3)
|
257
|
+
@handler.set_up_decryption({V: 3})
|
258
258
|
end
|
259
259
|
assert_match(/Unsupported encryption version/i, exp.message)
|
260
260
|
end
|
261
261
|
|
262
262
|
it "fails for unsupported crypt filter encryption methods" do
|
263
263
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
264
|
-
@handler.set_up_decryption(V: 4, StrF: :Mine, CF: {Mine: {CFM: :Unknown}})
|
264
|
+
@handler.set_up_decryption({V: 4, StrF: :Mine, CF: {Mine: {CFM: :Unknown}}})
|
265
265
|
end
|
266
266
|
assert_match(/Unsupported encryption method/i, exp.message)
|
267
267
|
end
|
@@ -269,7 +269,7 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
269
269
|
|
270
270
|
describe "decrypt" do
|
271
271
|
before do
|
272
|
-
@handler.set_up_decryption(V: 1)
|
272
|
+
@handler.set_up_decryption({V: 1})
|
273
273
|
@encrypted = @handler.encrypt_string('string', @obj)
|
274
274
|
@obj.value = {Key: @encrypted.dup, Array: [@encrypted.dup], Hash: {Another: @encrypted.dup}}
|
275
275
|
end
|
@@ -217,29 +217,29 @@ describe HexaPDF::Encryption::StandardSecurityHandler do
|
|
217
217
|
describe "prepare_decryption" do
|
218
218
|
it "fails if the /Filter value is incorrect" do
|
219
219
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
220
|
-
@handler.set_up_decryption(Filter: :NonStandard, V: 2)
|
220
|
+
@handler.set_up_decryption({Filter: :NonStandard, V: 2})
|
221
221
|
end
|
222
222
|
assert_match(/Invalid \/Filter/i, exp.message)
|
223
223
|
end
|
224
224
|
|
225
225
|
it "fails if the /R value is incorrect" do
|
226
226
|
exp = assert_raises(HexaPDF::UnsupportedEncryptionError) do
|
227
|
-
@handler.set_up_decryption(Filter: :Standard, V: 2, R: 5)
|
227
|
+
@handler.set_up_decryption({Filter: :Standard, V: 2, R: 5})
|
228
228
|
end
|
229
229
|
assert_match(/Invalid \/R/i, exp.message)
|
230
230
|
end
|
231
231
|
|
232
232
|
it "fails if the ID in the document's trailer is missing although it is needed" do
|
233
233
|
exp = assert_raises(HexaPDF::EncryptionError) do
|
234
|
-
@handler.set_up_decryption(Filter: :Standard, V: 2, R: 2)
|
234
|
+
@handler.set_up_decryption({Filter: :Standard, V: 2, R: 2})
|
235
235
|
end
|
236
236
|
assert_match(/Document ID/i, exp.message)
|
237
237
|
end
|
238
238
|
|
239
239
|
it "fails if the supplied password is invalid" do
|
240
240
|
exp = assert_raises(HexaPDF::EncryptionError) do
|
241
|
-
@handler.set_up_decryption(Filter: :Standard, V: 2, R: 6, U: 'a' * 48, O: 'a' * 48,
|
242
|
-
|
241
|
+
@handler.set_up_decryption({Filter: :Standard, V: 2, R: 6, U: 'a' * 48, O: 'a' * 48,
|
242
|
+
UE: 'a' * 32, OE: 'a' * 32})
|
243
243
|
end
|
244
244
|
assert_match(/Invalid password/i, exp.message)
|
245
245
|
end
|
@@ -114,7 +114,7 @@ describe HexaPDF::Font::TrueTypeWrapper do
|
|
114
114
|
cidfont[:CIDSystemInfo].value)
|
115
115
|
assert_equal(:Identity, cidfont[:CIDToGIDMap])
|
116
116
|
assert_equal(@font_wrapper.glyph(3).width, cidfont[:DW])
|
117
|
-
assert_equal([2, [glyph.width]], cidfont[:W])
|
117
|
+
assert_equal([2, [glyph.width]], cidfont[:W].value)
|
118
118
|
assert(cidfont.validate)
|
119
119
|
|
120
120
|
# Checking font descriptor
|
@@ -155,7 +155,7 @@ describe HexaPDF::Font::TrueTypeWrapper do
|
|
155
155
|
|
156
156
|
assert_equal(HexaPDF::Font::CMap.create_to_unicode_cmap([[3, ' '.ord], [glyph.id, 'H'.ord]]),
|
157
157
|
dict[:ToUnicode].stream)
|
158
|
-
assert_equal([glyph.id, [glyph.width]], dict[:DescendantFonts][0][:W])
|
158
|
+
assert_equal([glyph.id, [glyph.width]], dict[:DescendantFonts][0][:W].value)
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
@@ -32,4 +32,8 @@ describe HexaPDF::FontLoader::FromConfiguration do
|
|
32
32
|
it "returns nil for unknown fonts" do
|
33
33
|
assert_nil(@klass.call(@doc, "Unknown"))
|
34
34
|
end
|
35
|
+
|
36
|
+
it "returns a hash with all configured fonts" do
|
37
|
+
assert_equal({'font' => [:none]}, @klass.available_fonts(@doc))
|
38
|
+
end
|
35
39
|
end
|
@@ -20,4 +20,14 @@ describe HexaPDF::FontLoader::Standard14 do
|
|
20
20
|
it "returns nil for unknown fonts" do
|
21
21
|
assert_nil(@obj.call(@doc, "Unknown"))
|
22
22
|
end
|
23
|
+
|
24
|
+
it "returns a hash with all standard PDF fonts" do
|
25
|
+
assert_equal({
|
26
|
+
'Times' => [:none, :bold, :italic, :bold_italic],
|
27
|
+
'Helvetica' => [:none, :bold, :italic, :bold_italic],
|
28
|
+
'Courier' => [:none, :bold, :italic, :bold_italic],
|
29
|
+
'Symbol' => [:none], 'ZapfDingbats' => [:none]
|
30
|
+
},
|
31
|
+
@obj.available_fonts(@doc))
|
32
|
+
end
|
23
33
|
end
|
@@ -62,7 +62,7 @@ describe HexaPDF::ImageLoader::JPEG do
|
|
62
62
|
assert_equal(5, image[:Width])
|
63
63
|
assert_equal(5, image[:Height])
|
64
64
|
assert_equal(:DeviceCMYK, image[:ColorSpace])
|
65
|
-
assert_equal([1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0], image[:Decode])
|
65
|
+
assert_equal([1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0], image[:Decode].value)
|
66
66
|
assert_equal(File.binread(jpeg), image.stream)
|
67
67
|
end
|
68
68
|
|
@@ -29,7 +29,7 @@ describe HexaPDF::ImageLoader::PNG do
|
|
29
29
|
assert_equal(width, image[:Width])
|
30
30
|
assert_equal(height, image[:Height])
|
31
31
|
assert_equal(bpc, image[:BitsPerComponent])
|
32
|
-
assert_equal(color_space, image[:ColorSpace]) if color_space
|
32
|
+
assert_equal(color_space, @doc.unwrap(image[:ColorSpace])) if color_space
|
33
33
|
data = stream.map {|row| [row.map {|i| i.to_s(2).rjust(bpc, '0') }.join("")].pack('B*') }.join("")
|
34
34
|
assert_equal(data, image.stream)
|
35
35
|
end
|
@@ -111,7 +111,7 @@ describe HexaPDF::ImageLoader::PNG do
|
|
111
111
|
[253, 202, 151, 100, 50],
|
112
112
|
[253, 202, 151, 100, 49]]
|
113
113
|
assert_image(image, 5, 5, 8, :DeviceGray, data)
|
114
|
-
assert_equal([203, 203], image[:Mask])
|
114
|
+
assert_equal([203, 203], image[:Mask].value)
|
115
115
|
end
|
116
116
|
|
117
117
|
it "works for a greyscale png with a gamma value of 1" do
|
@@ -123,7 +123,7 @@ describe HexaPDF::ImageLoader::PNG do
|
|
123
123
|
it "works for a greyscale png with a gamma value of 1/1.5" do
|
124
124
|
png = @images.grep(/greyscale-with-gamma1\.5\.png/).first
|
125
125
|
image = @loader.load(@doc, png)
|
126
|
-
assert_equal([:CalGray, {WhitePoint: [1.0, 1.0, 1.0], Gamma: 1 / 1.5}], image[:ColorSpace])
|
126
|
+
assert_equal([:CalGray, {WhitePoint: [1.0, 1.0, 1.0], Gamma: 1 / 1.5}], image[:ColorSpace].value)
|
127
127
|
end
|
128
128
|
|
129
129
|
it "works for an indexed 1-bit png" do
|
@@ -6,8 +6,8 @@ require 'hexapdf/document'
|
|
6
6
|
require 'hexapdf/layout/box'
|
7
7
|
|
8
8
|
describe HexaPDF::Layout::Box do
|
9
|
-
def create_box(
|
10
|
-
HexaPDF::Layout::Box.new(
|
9
|
+
def create_box(**args, &block)
|
10
|
+
HexaPDF::Layout::Box.new(**args, &block)
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "::create" do
|
@@ -50,7 +50,7 @@ describe HexaPDF::Layout::Frame do
|
|
50
50
|
# checked whether the box coordinates are pos and whether the frame has the shape given by
|
51
51
|
# points.
|
52
52
|
def check_box(box_opts, pos, points)
|
53
|
-
@box = HexaPDF::Layout::Box.create(box_opts) {}
|
53
|
+
@box = HexaPDF::Layout::Box.create(**box_opts) {}
|
54
54
|
@canvas.expect(:translate, nil, pos)
|
55
55
|
assert(@frame.draw(@canvas, @box))
|
56
56
|
assert_equal(points, @frame.shape.polygons.map(&:to_a))
|
@@ -136,8 +136,8 @@ describe HexaPDF::Layout::Style::Quad do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
describe HexaPDF::Layout::Style::Border do
|
139
|
-
def create_border(
|
140
|
-
HexaPDF::Layout::Style::Border.new(
|
139
|
+
def create_border(**args)
|
140
|
+
HexaPDF::Layout::Style::Border.new(**args)
|
141
141
|
end
|
142
142
|
|
143
143
|
it "has accessors for with, color and style that return Quads" do
|
@@ -531,13 +531,13 @@ describe HexaPDF::Layout::Style::LinkLayer do
|
|
531
531
|
end
|
532
532
|
|
533
533
|
def call_link(hash)
|
534
|
-
link = HexaPDF::Layout::Style::LinkLayer.new(hash)
|
534
|
+
link = HexaPDF::Layout::Style::LinkLayer.new(**hash)
|
535
535
|
link.call(@canvas, @box)
|
536
536
|
@canvas.context[:Annots]&.first
|
537
537
|
end
|
538
538
|
|
539
539
|
it "does nothing if the context is not a page object" do
|
540
|
-
@canvas = HexaPDF::Document.new.add(Type: :XObject, Subtype: :Form).canvas
|
540
|
+
@canvas = HexaPDF::Document.new.add({Type: :XObject, Subtype: :Form}).canvas
|
541
541
|
assert_nil(call_link(dest: true))
|
542
542
|
end
|
543
543
|
|
@@ -545,28 +545,28 @@ describe HexaPDF::Layout::Style::LinkLayer do
|
|
545
545
|
annot = call_link(dest: true)
|
546
546
|
assert_equal(:Link, annot[:Subtype])
|
547
547
|
assert_equal([10, 10, 25, 20], annot[:Rect].value)
|
548
|
-
assert_equal([10, 10, 25, 10, 25, 20, 10, 20], annot[:QuadPoints])
|
548
|
+
assert_equal([10, 10, 25, 10, 25, 20, 10, 20], annot[:QuadPoints].value)
|
549
549
|
end
|
550
550
|
|
551
551
|
it "removes the border by default" do
|
552
552
|
annot = call_link(dest: true)
|
553
|
-
assert_equal([0, 0, 0], annot[:Border])
|
553
|
+
assert_equal([0, 0, 0], annot[:Border].value)
|
554
554
|
end
|
555
555
|
|
556
556
|
it "uses a default border if no specific border style is specified" do
|
557
557
|
annot = call_link(dest: true, border: true)
|
558
|
-
assert_equal([0, 0, 1], annot[:Border])
|
558
|
+
assert_equal([0, 0, 1], annot[:Border].value)
|
559
559
|
end
|
560
560
|
|
561
561
|
it "uses the specified border and border color" do
|
562
562
|
annot = call_link(dest: true, border: [10, 10, 2], border_color: [255])
|
563
|
-
assert_equal([10, 10, 2], annot[:Border])
|
564
|
-
assert_equal([1.0], annot[:C])
|
563
|
+
assert_equal([10, 10, 2], annot[:Border].value)
|
564
|
+
assert_equal([1.0], annot[:C].value)
|
565
565
|
end
|
566
566
|
|
567
567
|
it "works for simple destinations" do
|
568
568
|
annot = call_link(dest: [@canvas.context, :FitH])
|
569
|
-
assert_equal([@canvas.context, :FitH], annot[:Dest])
|
569
|
+
assert_equal([@canvas.context, :FitH], annot[:Dest].value)
|
570
570
|
assert_nil(annot[:A])
|
571
571
|
end
|
572
572
|
|
@@ -641,14 +641,14 @@ describe HexaPDF::Layout::Style do
|
|
641
641
|
assert_equal(100, @style.horizontal_scaling)
|
642
642
|
assert_equal(0, @style.text_rise)
|
643
643
|
assert_equal({}, @style.font_features)
|
644
|
-
assert_equal(
|
644
|
+
assert_equal(HexaPDF::Content::TextRenderingMode::FILL, @style.text_rendering_mode)
|
645
645
|
assert_equal([0], @style.fill_color.components)
|
646
646
|
assert_equal(1, @style.fill_alpha)
|
647
647
|
assert_equal([0], @style.stroke_color.components)
|
648
648
|
assert_equal(1, @style.stroke_alpha)
|
649
649
|
assert_equal(1, @style.stroke_width)
|
650
|
-
assert_equal(
|
651
|
-
assert_equal(
|
650
|
+
assert_equal(HexaPDF::Content::LineCapStyle::BUTT_CAP, @style.stroke_cap_style)
|
651
|
+
assert_equal(HexaPDF::Content::LineJoinStyle::MITER_JOIN, @style.stroke_join_style)
|
652
652
|
assert_equal(10.0, @style.stroke_miter_limit)
|
653
653
|
assert_equal(:left, @style.align)
|
654
654
|
assert_equal(:top, @style.valign)
|
@@ -677,6 +677,11 @@ describe HexaPDF::Layout::Style do
|
|
677
677
|
assert_equal([[5], 2], @style.stroke_dash_pattern.to_operands)
|
678
678
|
end
|
679
679
|
|
680
|
+
it "allows checking for valid values" do
|
681
|
+
error = assert_raises(ArgumentError) { @style.align = :none }
|
682
|
+
assert_match(/not a valid align value \(:left, :center, :right, :justify\)/, error.message)
|
683
|
+
end
|
684
|
+
|
680
685
|
it "allows checking whether a property has been set or accessed" do
|
681
686
|
refute(@style.align?)
|
682
687
|
assert_equal(:left, @style.align)
|