pdf-core 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -1,12 +0,0 @@
1
- # encoding: binary
2
- require_relative "spec_helper"
3
-
4
- describe "Decimal rounding" do
5
- it "should round floating point numbers to four decimal places" do
6
- PDF::Core.real(1.23456789).should == 1.2346
7
- end
8
-
9
- it "should be able to create a PDF parameter list of rounded decimals" do
10
- PDF::Core.real_params([1,2.34567,Math::PI]).should == "1.0 2.3457 3.1416"
11
- end
12
- end
@@ -1,30 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "PDF Document State" do
4
- before { @state = PDF::Core::DocumentState.new({}) }
5
-
6
- describe "initialization" do
7
- it { expect(@state.compress).to eq(false) }
8
- it { expect(@state.encrypt).to eq(false) }
9
- it { expect(@state.skip_encoding).to eq(false) }
10
- it { expect(@state.trailer).to eq({}) }
11
- end
12
-
13
- describe "normalize_metadata" do
14
- it { expect(@state.store.info.data[:Creator]).to eq("Prawn") }
15
- it { expect(@state.store.info.data[:Producer]).to eq("Prawn") }
16
- end
17
-
18
- describe "given a trailer ID with two values" do
19
- before do
20
- @state = PDF::Core::DocumentState.new({
21
- trailer: { :ID => ["myDoc","versionA"] }
22
- })
23
- end
24
-
25
- it "should contain the ID entry with two values in trailer" do
26
- expect(@state.trailer[:ID].count).to eq(2)
27
- end
28
- end
29
-
30
- end
@@ -1,34 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require_relative "spec_helper"
4
-
5
- FILTERS = {
6
- :FlateDecode => {'test' => "x\x9C+I-.\x01\x00\x04]\x01\xC1".force_encoding(Encoding::ASCII_8BIT) },
7
- :DCTDecode => {'test' => "test"}
8
- }
9
-
10
- FILTERS.each do |filter_name, examples|
11
- filter = PDF::Core::Filters.const_get(filter_name)
12
-
13
- describe "#{filter_name} filter" do
14
- it "should encode stream" do
15
- examples.each do |in_stream, out_stream|
16
- filter.encode(in_stream).should == out_stream
17
- end
18
- end
19
-
20
- it "should decode stream" do
21
- examples.each do |in_stream, out_stream|
22
- filter.decode(out_stream).should == in_stream
23
- end
24
- end
25
-
26
- it "should be symmetric" do
27
- examples.each do |in_stream, out_stream|
28
- filter.decode(filter.encode(in_stream)).should == in_stream
29
-
30
- filter.encode(filter.decode(out_stream)).should == out_stream
31
- end
32
- end
33
- end
34
- end
@@ -1,122 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- def tree_dump(tree)
4
- if tree.is_a?(PDF::Core::NameTree::Node)
5
- "[" + tree.children.map { |child| tree_dump(child) }.join(",") + "]"
6
- else
7
- "#{tree.name}=#{tree.value}"
8
- end
9
- end
10
-
11
- def tree_add(tree, *args)
12
- args.each do |(name, value)|
13
- tree.add(name, value)
14
- end
15
- end
16
-
17
- def tree_value(name, value)
18
- PDF::Core::NameTree::Value.new(name, value)
19
- end
20
-
21
- # FIXME: This is a dummy that's meant to stand in for a Prawn::Document.
22
- # It causes the tests to pass but I have no idea if it's really a
23
- # sufficient test double or not.
24
- class RefExposingDocument
25
- def initialize
26
- @object_store = []
27
- end
28
-
29
- attr_reader :object_store
30
-
31
- def ref!(obj)
32
- @object_store << obj
33
- end
34
- end
35
-
36
- describe "Name Tree" do
37
- before(:each) { @pdf = RefExposingDocument.new }
38
-
39
- it "should have no children when first initialized" do
40
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
41
- node.children.length.should == 0
42
- end
43
-
44
- it "should have no subtrees while child limit is not reached" do
45
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
46
- tree_add(node, ["one", 1], ["two", 2], ["three", 3])
47
- tree_dump(node).should == "[one=1,three=3,two=2]"
48
- end
49
-
50
- it "should split into subtrees when limit is exceeded" do
51
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
52
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
53
- tree_dump(node).should == "[[four=4,one=1],[three=3,two=2]]"
54
- end
55
-
56
- it "should create a two new references when root is split" do
57
- ref_count = @pdf.object_store.length
58
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
59
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
60
- @pdf.object_store.length.should == ref_count+2
61
- end
62
-
63
- it "should create a one new reference when subtree is split" do
64
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
65
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
66
-
67
- ref_count = @pdf.object_store.length # save when root is split
68
- tree_add(node, ["five", 5], ["six", 6], ["seven", 7])
69
- tree_dump(node).should == "[[five=5,four=4,one=1],[seven=7,six=6],[three=3,two=2]]"
70
- @pdf.object_store.length.should == ref_count+1
71
- end
72
-
73
- it "should keep tree balanced when subtree split cascades to root" do
74
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
75
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
76
- tree_add(node, ["five", 5], ["six", 6], ["seven", 7], ["eight", 8])
77
- tree_dump(node).should == "[[[eight=8,five=5],[four=4,one=1]],[[seven=7,six=6],[three=3,two=2]]]"
78
- end
79
-
80
- it "should maintain order of already properly ordered nodes" do
81
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
82
- tree_add(node, ["eight", 8], ["five", 5], ["four", 4], ["one", 1])
83
- tree_add(node, ['seven', 7], ['six', 6], ['three', 3], ['two', 2])
84
- tree_dump(node).should == "[[[eight=8,five=5],[four=4,one=1]],[[seven=7,six=6],[three=3,two=2]]]"
85
- end
86
-
87
- it "should emit only :Names key with to_hash if root is only node" do
88
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
89
- tree_add(node, ["one", 1], ["two", 2], ["three", 3])
90
- node.to_hash.should ==(
91
- { :Names => [tree_value("one", 1), tree_value("three", 3), tree_value("two", 2)] }
92
- )
93
- end
94
-
95
- it "should emit only :Kids key with to_hash if root has children" do
96
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
97
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
98
- node.to_hash.should ==({ :Kids => node.children.map { |child| child.ref } })
99
- end
100
-
101
- it "should emit :Limits and :Names keys with to_hash for leaf node" do
102
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
103
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
104
- node.children.first.to_hash.should ==(
105
- { :Limits => %w(four one),
106
- :Names => [tree_value("four", 4), tree_value("one", 1)] }
107
- )
108
- end
109
-
110
- it "should emit :Limits and :Kids keys with to_hash for inner node" do
111
- node = PDF::Core::NameTree::Node.new(@pdf, 3)
112
- tree_add(node, ["one", 1], ["two", 2], ["three", 3], ["four", 4])
113
- tree_add(node, ["five", 5], ["six", 6], ["seven", 7], ["eight", 8])
114
- tree_add(node, ["nine", 9], ["ten", 10], ["eleven", 11], ["twelve", 12])
115
- tree_add(node, ["thirteen", 13], ["fourteen", 14], ["fifteen", 15], ["sixteen", 16])
116
- node.children.first.to_hash.should ==(
117
- { :Limits => %w(eight one),
118
- :Kids => node.children.first.children.map { |child| child.ref } }
119
- )
120
- end
121
- end
122
-
@@ -1,49 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require_relative "spec_helper"
4
-
5
- describe "PDF::Core::ObjectStore" do
6
- before(:each) do
7
- @store = PDF::Core::ObjectStore.new
8
- end
9
-
10
- it "should create required roots by default, including info passed to new" do
11
- store = PDF::Core::ObjectStore.new(:info => {:Test => 3})
12
- store.size.should == 3 # 3 default roots
13
- store.info.data[:Test].should == 3
14
- store.pages.data[:Count].should == 0
15
- store.root.data[:Pages].should == store.pages
16
- end
17
-
18
-
19
- it "should add to its objects when ref() is called" do
20
- count = @store.size
21
- @store.ref("blah")
22
- @store.size.should == count + 1
23
- end
24
-
25
- it "should accept push with a Prawn::Reference" do
26
- r = PDF::Core::Reference(123, "blah")
27
- @store.push(r)
28
- @store[r.identifier].should == r
29
- end
30
-
31
- it "should accept arbitrary data and use it to create a Prawn::Reference" do
32
- @store.push(123, "blahblah")
33
- @store[123].data.should == "blahblah"
34
- end
35
-
36
- it "should be Enumerable, yielding in order of submission" do
37
- # higher IDs to bypass the default roots
38
- [10, 11, 12].each do |id|
39
- @store.push(id, "some data #{id}")
40
- end
41
- @store.map{|ref| ref.identifier}[-3..-1].should == [10, 11, 12]
42
- end
43
-
44
- it "should accept option to disabling PDF scaling in PDF clients" do
45
- @store = PDF::Core::ObjectStore.new(:print_scaling => :none)
46
- @store.root.data[:ViewerPreferences].should == {:PrintScaling => :None}
47
- end
48
-
49
- end
@@ -1,172 +0,0 @@
1
- # encoding: ASCII-8BIT
2
- require_relative "spec_helper"
3
-
4
- # See PDF Reference, Sixth Edition (1.7) pp51-60 for details
5
- describe "PDF Object Serialization" do
6
-
7
- it "should convert Ruby's nil to PDF null" do
8
- PDF::Core::PdfObject(nil).should == "null"
9
- end
10
-
11
- it "should convert Ruby booleans to PDF booleans" do
12
- PDF::Core::PdfObject(true).should == "true"
13
- PDF::Core::PdfObject(false).should == "false"
14
- end
15
-
16
- it "should convert a Ruby number to PDF number" do
17
- PDF::Core::PdfObject(42).should == "42"
18
-
19
- # numbers are rounded to four decimal places
20
- PDF::Core::PdfObject(1.214112421).should == "1.2141"
21
- end
22
-
23
- it "should convert a Ruby time object to a PDF timestamp" do
24
- t = Time.now
25
- PDF::Core::PdfObject(t).should == t.strftime("(D:%Y%m%d%H%M%S%z").chop.chop + "'00')"
26
- end
27
-
28
- it "should convert a Ruby string to PDF string when inside a content stream" do
29
- s = "I can has a string"
30
- PDF::Inspector.parse(PDF::Core::PdfObject(s, true)).should == s
31
- end
32
-
33
- it "should convert a Ruby string to a UTF-16 PDF string when outside a content stream" do
34
- s = "I can has a string"
35
- s_utf16 = "\xFE\xFF" + s.unpack("U*").pack("n*")
36
- PDF::Inspector.parse(PDF::Core::PdfObject(s, false)).should == s_utf16
37
- end
38
-
39
- it "should convert a Ruby string with characters outside the BMP to its " +
40
- "UTF-16 representation with a BOM" do
41
- # U+10192 ROMAN SEMUNCIA SIGN
42
- semuncia = [65938].pack("U")
43
- PDF::Core::PdfObject(semuncia, false).upcase.should == "<FEFFD800DD92>"
44
- end
45
-
46
- it "should pass through bytes regardless of content stream status for ByteString" do
47
- PDF::Core::PdfObject(PDF::Core::ByteString.new("\xDE\xAD\xBE\xEF")).upcase.
48
- should == "<DEADBEEF>"
49
- end
50
-
51
- it "should escape parens when converting from Ruby string to PDF" do
52
- s = 'I )(can has a string'
53
- PDF::Inspector.parse(PDF::Core::PdfObject(s, true)).should == s
54
- end
55
-
56
- it "should handle ruby escaped parens when converting to PDF string" do
57
- s = 'I can \\)( has string'
58
- PDF::Inspector.parse(PDF::Core::PdfObject(s, true)).should == s
59
- end
60
-
61
- it "should escape various strings correctly when converting a LiteralString" do
62
- ls = PDF::Core::LiteralString.new("abc")
63
- PDF::Core::PdfObject(ls).should == "(abc)"
64
-
65
- ls = PDF::Core::LiteralString.new("abc\x0Ade") # should escape \n
66
- PDF::Core::PdfObject(ls).should == "(abc\x5C\x0Ade)"
67
-
68
- ls = PDF::Core::LiteralString.new("abc\x0Dde") # should escape \r
69
- PDF::Core::PdfObject(ls).should == "(abc\x5C\x0Dde)"
70
-
71
- ls = PDF::Core::LiteralString.new("abc\x09de") # should escape \t
72
- PDF::Core::PdfObject(ls).should == "(abc\x5C\x09de)"
73
-
74
- ls = PDF::Core::LiteralString.new("abc\x08de") # should escape \b
75
- PDF::Core::PdfObject(ls).should == "(abc\x5C\x08de)"
76
-
77
- ls = PDF::Core::LiteralString.new("abc\x0Cde") # should escape \f
78
- PDF::Core::PdfObject(ls).should == "(abc\x5C\x0Cde)"
79
-
80
- ls = PDF::Core::LiteralString.new("abc(de") # should escape \(
81
- PDF::Core::PdfObject(ls).should == "(abc\x5C(de)"
82
-
83
- ls = PDF::Core::LiteralString.new("abc)de") # should escape \)
84
- PDF::Core::PdfObject(ls).should == "(abc\x5C)de)"
85
-
86
- ls = PDF::Core::LiteralString.new("abc\x5Cde") # should escape \\
87
- PDF::Core::PdfObject(ls).should == "(abc\x5C\x5Cde)"
88
- PDF::Core::PdfObject(ls).size.should == 9
89
- end
90
-
91
- it "should escape strings correctly when converting a LiteralString that is not utf-8" do
92
- data = "\x43\xaf\xc9\x7f\xef\xf\xe6\xa8\xcb\x5c\xaf\xd0"
93
- ls = PDF::Core::LiteralString.new(data)
94
- PDF::Core::PdfObject(ls).should == "(\x43\xaf\xc9\x7f\xef\xf\xe6\xa8\xcb\x5c\x5c\xaf\xd0)"
95
- end
96
-
97
- it "should convert a Ruby symbol to PDF name" do
98
- PDF::Core::PdfObject(:my_symbol).should == "/my_symbol"
99
- PDF::Core::PdfObject(:"A;Name_With-Various***Characters?").should ==
100
- "/A;Name_With-Various***Characters?"
101
- end
102
-
103
- it "should convert a whitespace or delimiter containing Ruby symbol to a PDF name" do
104
- PDF::Core::PdfObject(:"my symbol").should == "/my#20symbol"
105
- PDF::Core::PdfObject(:"my#symbol").should == "/my#23symbol"
106
- PDF::Core::PdfObject(:"my/symbol").should == "/my#2Fsymbol"
107
- PDF::Core::PdfObject(:"my(symbol").should == "/my#28symbol"
108
- PDF::Core::PdfObject(:"my)symbol").should == "/my#29symbol"
109
- PDF::Core::PdfObject(:"my<symbol").should == "/my#3Csymbol"
110
- PDF::Core::PdfObject(:"my>symbol").should == "/my#3Esymbol"
111
- end
112
-
113
- it "should convert a Ruby array to PDF Array when inside a content stream" do
114
- PDF::Core::PdfObject([1,2,3]).should == "[1 2 3]"
115
- PDF::Inspector.parse(PDF::Core::PdfObject([[1,2],:foo,"Bar"], true)).should ==
116
- [[1,2],:foo, "Bar"]
117
- end
118
-
119
- it "should convert a Ruby array to PDF Array when outside a content stream" do
120
- bar = "\xFE\xFF" + "Bar".unpack("U*").pack("n*")
121
- PDF::Core::PdfObject([1,2,3]).should == "[1 2 3]"
122
- PDF::Inspector.parse(PDF::Core::PdfObject([[1,2],:foo,"Bar"], false)).should ==
123
- [[1,2],:foo, bar]
124
- end
125
-
126
- it "should convert a Ruby hash to a PDF Dictionary when inside a content stream" do
127
- dict = PDF::Core::PdfObject( {:foo => :bar,
128
- "baz" => [1,2,3],
129
- :bang => {:a => "what", :b => [:you, :say] }}, true )
130
-
131
- res = PDF::Inspector.parse(dict)
132
-
133
- res[:foo].should == :bar
134
- res[:baz].should == [1,2,3]
135
- res[:bang].should == { :a => "what", :b => [:you, :say] }
136
-
137
- end
138
-
139
- it "should convert a Ruby hash to a PDF Dictionary when outside a content stream" do
140
- what = "\xFE\xFF" + "what".unpack("U*").pack("n*")
141
- dict = PDF::Core::PdfObject( {:foo => :bar,
142
- "baz" => [1,2,3],
143
- :bang => {:a => "what", :b => [:you, :say] }}, false )
144
-
145
- res = PDF::Inspector.parse(dict)
146
-
147
- res[:foo].should == :bar
148
- res[:baz].should == [1,2,3]
149
- res[:bang].should == { :a => what, :b => [:you, :say] }
150
-
151
- end
152
-
153
- it "should not allow keys other than strings or symbols for PDF dicts" do
154
- lambda { PDF::Core::PdfObject(:foo => :bar, :baz => :bang, 1 => 4) }.
155
- should raise_error(PDF::Core::Errors::FailedObjectConversion)
156
- end
157
-
158
- it "should convert a Prawn::Reference to a PDF indirect object reference" do
159
- ref = PDF::Core::Reference(1,true)
160
- PDF::Core::PdfObject(ref).should == ref.to_s
161
- end
162
-
163
- it "should convert a NameTree::Node to a PDF hash" do
164
- # FIXME: Soft dependench on Prawn::Document exists in Node
165
- node = PDF::Core::NameTree::Node.new(nil, 10)
166
- node.add "hello", 1.0
167
- node.add "world", 2.0
168
- data = PDF::Core::PdfObject(node)
169
- res = PDF::Inspector.parse(data)
170
- res.should == {:Names => ["hello", 1.0, "world", 2.0]}
171
- end
172
- end
@@ -1,62 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require_relative "spec_helper"
4
-
5
- describe "A Reference object" do
6
- it "should produce a PDF reference on #to_s call" do
7
- ref = PDF::Core::Reference(1,true)
8
- ref.to_s.should == "1 0 R"
9
- end
10
-
11
- it "should allow changing generation number" do
12
- ref = PDF::Core::Reference(1,true)
13
- ref.gen = 1
14
- ref.to_s.should == "1 1 R"
15
- end
16
-
17
- it "should generate a valid PDF object for the referenced data" do
18
- ref = PDF::Core::Reference(2,[1,"foo"])
19
- ref.object.should == "2 0 obj\n#{PDF::Core::PdfObject([1,"foo"])}\nendobj\n"
20
- end
21
-
22
- it "should include stream fileds in dictionary when serializing" do
23
- ref = PDF::Core::Reference(1, {})
24
- ref.stream << 'Hello'
25
- ref.object.should == "1 0 obj\n<< /Length 5\n>>\nstream\nHello\nendstream\nendobj\n"
26
- end
27
-
28
- it "should append data to stream when #<< is used" do
29
- ref = PDF::Core::Reference(1, {})
30
- ref << "BT\n/F1 12 Tf\n72 712 Td\n( A stream ) Tj\nET"
31
- ref.object.should == "1 0 obj\n<< /Length 41\n>>\nstream"+
32
- "\nBT\n/F1 12 Tf\n72 712 Td\n( A stream ) Tj\nET" +
33
- "\nendstream\nendobj\n"
34
- end
35
-
36
- it "should copy the data and stream from another ref on #replace" do
37
- from = PDF::Core::Reference(3, {:foo => 'bar'})
38
- from << "has a stream too"
39
-
40
- to = PDF::Core::Reference(4, {:foo => 'baz'})
41
- to.replace from
42
-
43
- # should preserve identifier but copy data and stream
44
- to.identifier.should == 4
45
- to.data.should == from.data
46
- to.stream.should == from.stream
47
- end
48
-
49
- it "should copy a compressed stream from a compressed ref on #replace" do
50
- from = PDF::Core::Reference(5, {:foo => 'bar'})
51
- from << "has a stream too " * 20
52
- from.stream.compress!
53
-
54
- to = PDF::Core::Reference(6, {:foo => 'baz'})
55
- to.replace from
56
-
57
- to.identifier.should == 6
58
- to.data.should == from.data
59
- to.stream.should == from.stream
60
- to.stream.compressed?.should == true
61
- end
62
- end