prawn 1.0.0.rc2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +9 -0
- data/COPYING +2 -2
- data/Gemfile +8 -15
- data/LICENSE +1 -1
- data/Rakefile +25 -16
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/license.md +8 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/lib/prawn.rb +85 -23
- data/lib/prawn/document.rb +134 -116
- data/lib/prawn/document/bounding_box.rb +33 -4
- data/lib/prawn/document/column_box.rb +18 -6
- data/lib/prawn/document/graphics_state.rb +11 -74
- data/lib/prawn/document/internals.rb +24 -23
- data/lib/prawn/document/span.rb +12 -10
- data/lib/prawn/encoding.rb +8 -9
- data/lib/prawn/errors.rb +13 -32
- data/lib/prawn/font.rb +137 -105
- data/lib/prawn/font/afm.rb +76 -32
- data/lib/prawn/font/dfont.rb +4 -3
- data/lib/prawn/font/ttf.rb +33 -25
- data/lib/prawn/font_metric_cache.rb +47 -0
- data/lib/prawn/graphics.rb +177 -57
- data/lib/prawn/graphics/cap_style.rb +4 -3
- data/lib/prawn/graphics/color.rb +5 -4
- data/lib/prawn/graphics/dash.rb +53 -31
- data/lib/prawn/graphics/join_style.rb +9 -7
- data/lib/prawn/graphics/patterns.rb +4 -15
- data/lib/prawn/graphics/transformation.rb +10 -9
- data/lib/prawn/graphics/transparency.rb +3 -1
- data/lib/prawn/{layout/grid.rb → grid.rb} +72 -54
- data/lib/prawn/image_handler.rb +42 -0
- data/lib/prawn/images.rb +58 -54
- data/lib/prawn/images/image.rb +6 -22
- data/lib/prawn/images/jpg.rb +20 -14
- data/lib/prawn/images/png.rb +58 -121
- data/lib/prawn/layout.rb +12 -15
- data/lib/prawn/measurement_extensions.rb +10 -6
- data/lib/prawn/measurements.rb +27 -21
- data/lib/prawn/outline.rb +108 -147
- data/lib/prawn/repeater.rb +10 -8
- data/lib/prawn/security.rb +59 -40
- data/lib/prawn/security/arcfour.rb +52 -0
- data/lib/prawn/soft_mask.rb +4 -4
- data/lib/prawn/stamp.rb +5 -3
- data/lib/prawn/table.rb +83 -60
- data/lib/prawn/table/cell.rb +17 -21
- data/lib/prawn/table/cell/image.rb +2 -3
- data/lib/prawn/table/cell/in_table.rb +8 -2
- data/lib/prawn/table/cell/span_dummy.rb +5 -0
- data/lib/prawn/table/cell/subtable.rb +3 -2
- data/lib/prawn/table/cell/text.rb +14 -12
- data/lib/prawn/table/cells.rb +58 -14
- data/lib/prawn/table/column_width_calculator.rb +61 -0
- data/lib/prawn/text.rb +27 -26
- data/lib/prawn/text/box.rb +12 -6
- data/lib/prawn/text/formatted.rb +5 -4
- data/lib/prawn/text/formatted/arranger.rb +290 -0
- data/lib/prawn/text/formatted/box.rb +85 -57
- data/lib/prawn/text/formatted/fragment.rb +11 -11
- data/lib/prawn/text/formatted/line_wrap.rb +266 -0
- data/lib/prawn/text/formatted/parser.rb +11 -4
- data/lib/prawn/text/formatted/wrap.rb +156 -0
- data/lib/prawn/utilities.rb +5 -3
- data/manual/document_and_page_options/document_and_page_options.rb +2 -1
- data/manual/document_and_page_options/metadata.rb +3 -3
- data/manual/document_and_page_options/page_size.rb +2 -2
- data/manual/document_and_page_options/print_scaling.rb +20 -0
- data/manual/example_file.rb +2 -7
- data/manual/example_helper.rb +62 -81
- data/manual/graphics/common_lines.rb +2 -0
- data/manual/graphics/helper.rb +11 -4
- data/manual/graphics/stroke_dash.rb +19 -14
- data/manual/manual/cover.rb +16 -0
- data/manual/manual/manual.rb +1 -5
- data/manual/text/fallback_fonts.rb +4 -4
- data/manual/text/formatted_text.rb +5 -5
- data/manual/text/inline.rb +2 -4
- data/manual/text/registering_families.rb +12 -12
- data/manual/text/single_usage.rb +4 -4
- data/manual/text/text.rb +0 -2
- data/prawn.gemspec +21 -13
- data/spec/acceptance/png.rb +23 -0
- data/spec/annotations_spec.rb +16 -32
- data/spec/bounding_box_spec.rb +22 -5
- data/spec/cell_spec.rb +49 -5
- data/spec/column_box_spec.rb +32 -0
- data/spec/destinations_spec.rb +5 -5
- data/spec/document_spec.rb +112 -118
- data/spec/extensions/encoding_helpers.rb +5 -2
- data/spec/font_metric_cache_spec.rb +52 -0
- data/spec/font_spec.rb +121 -120
- data/spec/formatted_text_arranger_spec.rb +24 -24
- data/spec/formatted_text_box_spec.rb +31 -32
- data/spec/formatted_text_fragment_spec.rb +2 -2
- data/spec/graphics_spec.rb +63 -45
- data/spec/grid_spec.rb +24 -13
- data/spec/image_handler_spec.rb +54 -0
- data/spec/images_spec.rb +34 -21
- data/spec/inline_formatted_text_parser_spec.rb +69 -20
- data/spec/jpg_spec.rb +3 -3
- data/spec/line_wrap_spec.rb +25 -14
- data/spec/measurement_units_spec.rb +5 -5
- data/spec/outline_spec.rb +68 -64
- data/spec/png_spec.rb +15 -18
- data/spec/reference_spec.rb +2 -82
- data/spec/repeater_spec.rb +1 -1
- data/spec/security_spec.rb +41 -9
- data/spec/soft_mask_spec.rb +0 -40
- data/spec/span_spec.rb +6 -11
- data/spec/spec_helper.rb +20 -2
- data/spec/stamp_spec.rb +19 -20
- data/spec/stroke_styles_spec.rb +31 -13
- data/spec/table/span_dummy_spec.rb +17 -0
- data/spec/table_spec.rb +268 -43
- data/spec/text_at_spec.rb +13 -27
- data/spec/text_box_spec.rb +35 -30
- data/spec/text_spec.rb +56 -40
- data/spec/transparency_spec.rb +5 -5
- metadata +214 -217
- data/README.md +0 -98
- data/data/fonts/Action Man.dfont +0 -0
- data/data/fonts/Activa.ttf +0 -0
- data/data/fonts/Chalkboard.ttf +0 -0
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/16bit.dat +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/data/images/rails.dat +0 -0
- data/data/images/rails.png +0 -0
- data/lib/prawn/compatibility.rb +0 -87
- data/lib/prawn/core.rb +0 -87
- data/lib/prawn/core/annotations.rb +0 -61
- data/lib/prawn/core/byte_string.rb +0 -9
- data/lib/prawn/core/destinations.rb +0 -90
- data/lib/prawn/core/document_state.rb +0 -79
- data/lib/prawn/core/literal_string.rb +0 -16
- data/lib/prawn/core/name_tree.rb +0 -177
- data/lib/prawn/core/object_store.rb +0 -320
- data/lib/prawn/core/page.rb +0 -212
- data/lib/prawn/core/pdf_object.rb +0 -125
- data/lib/prawn/core/reference.rb +0 -119
- data/lib/prawn/core/text.rb +0 -268
- data/lib/prawn/core/text/formatted/arranger.rb +0 -294
- data/lib/prawn/core/text/formatted/line_wrap.rb +0 -288
- data/lib/prawn/core/text/formatted/wrap.rb +0 -153
- data/lib/prawn/document/page_geometry.rb +0 -136
- data/lib/prawn/document/snapshot.rb +0 -89
- data/manual/manual/foreword.rb +0 -13
- data/manual/templates/full_template.rb +0 -23
- data/manual/templates/page_template.rb +0 -47
- data/manual/templates/templates.rb +0 -26
- data/manual/text/group.rb +0 -29
- data/spec/name_tree_spec.rb +0 -112
- data/spec/object_store_spec.rb +0 -170
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/snapshot_spec.rb +0 -186
- data/spec/template_spec.rb +0 -351
data/spec/pdf_object_spec.rb
DELETED
@@ -1,172 +0,0 @@
|
|
1
|
-
# encoding: ASCII-8BIT
|
2
|
-
|
3
|
-
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
4
|
-
|
5
|
-
# See PDF Reference, Sixth Edition (1.7) pp51-60 for details
|
6
|
-
describe "PDF Object Serialization" do
|
7
|
-
|
8
|
-
it "should convert Ruby's nil to PDF null" do
|
9
|
-
Prawn::Core::PdfObject(nil).should == "null"
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should convert Ruby booleans to PDF booleans" do
|
13
|
-
Prawn::Core::PdfObject(true).should == "true"
|
14
|
-
Prawn::Core::PdfObject(false).should == "false"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should convert a Ruby number to PDF number" do
|
18
|
-
Prawn::Core::PdfObject(1).should == "1"
|
19
|
-
Prawn::Core::PdfObject(1.214112421).should == "1.214112421"
|
20
|
-
# scientific notation is not valid in PDF
|
21
|
-
Prawn::Core::PdfObject(0.000005).should == "0.000005"
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should convert a Ruby time object to a PDF timestamp" do
|
25
|
-
t = Time.now
|
26
|
-
Prawn::Core::PdfObject(t).should == t.strftime("(D:%Y%m%d%H%M%S%z").chop.chop + "'00')"
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should convert a Ruby string to PDF string when inside a content stream" do
|
30
|
-
s = "I can has a string"
|
31
|
-
PDF::Inspector.parse(Prawn::Core::PdfObject(s, true)).should == s
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should convert a Ruby string to a UTF-16 PDF string when outside a content stream" do
|
35
|
-
s = "I can has a string"
|
36
|
-
s_utf16 = "\xFE\xFF" + s.unpack("U*").pack("n*")
|
37
|
-
PDF::Inspector.parse(Prawn::Core::PdfObject(s, false)).should == s_utf16
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should convert a Ruby string with characters outside the BMP to its " +
|
41
|
-
"UTF-16 representation with a BOM" do
|
42
|
-
# U+10192 ROMAN SEMUNCIA SIGN
|
43
|
-
semuncia = [65938].pack("U")
|
44
|
-
Prawn::Core::PdfObject(semuncia, false).upcase.should == "<FEFFD800DD92>"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should pass through bytes regardless of content stream status for ByteString" do
|
48
|
-
Prawn::Core::PdfObject(Prawn::Core::ByteString.new("\xDE\xAD\xBE\xEF")).upcase.
|
49
|
-
should == "<DEADBEEF>"
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should escape parens when converting from Ruby string to PDF" do
|
53
|
-
s = 'I )(can has a string'
|
54
|
-
PDF::Inspector.parse(Prawn::Core::PdfObject(s, true)).should == s
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should handle ruby escaped parens when converting to PDF string" do
|
58
|
-
s = 'I can \\)( has string'
|
59
|
-
PDF::Inspector.parse(Prawn::Core::PdfObject(s, true)).should == s
|
60
|
-
end
|
61
|
-
|
62
|
-
it "should escape various strings correctly when converting a LiteralString" do
|
63
|
-
ls = Prawn::Core::LiteralString.new("abc")
|
64
|
-
Prawn::Core::PdfObject(ls).should == "(abc)"
|
65
|
-
|
66
|
-
ls = Prawn::Core::LiteralString.new("abc\x0Ade") # should escape \n
|
67
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C\x0Ade)"
|
68
|
-
|
69
|
-
ls = Prawn::Core::LiteralString.new("abc\x0Dde") # should escape \r
|
70
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C\x0Dde)"
|
71
|
-
|
72
|
-
ls = Prawn::Core::LiteralString.new("abc\x09de") # should escape \t
|
73
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C\x09de)"
|
74
|
-
|
75
|
-
ls = Prawn::Core::LiteralString.new("abc\x08de") # should escape \b
|
76
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C\x08de)"
|
77
|
-
|
78
|
-
ls = Prawn::Core::LiteralString.new("abc\x0Cde") # should escape \f
|
79
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C\x0Cde)"
|
80
|
-
|
81
|
-
ls = Prawn::Core::LiteralString.new("abc(de") # should escape \(
|
82
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C(de)"
|
83
|
-
|
84
|
-
ls = Prawn::Core::LiteralString.new("abc)de") # should escape \)
|
85
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C)de)"
|
86
|
-
|
87
|
-
ls = Prawn::Core::LiteralString.new("abc\x5Cde") # should escape \\
|
88
|
-
Prawn::Core::PdfObject(ls).should == "(abc\x5C\x5Cde)"
|
89
|
-
Prawn::Core::PdfObject(ls).size.should == 9
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should escape strings correctly when converting a LiteralString that is not utf-8" do
|
93
|
-
data = "\x43\xaf\xc9\x7f\xef\xf\xe6\xa8\xcb\x5c\xaf\xd0"
|
94
|
-
ls = Prawn::Core::LiteralString.new(data)
|
95
|
-
Prawn::Core::PdfObject(ls).should == "(\x43\xaf\xc9\x7f\xef\xf\xe6\xa8\xcb\x5c\x5c\xaf\xd0)"
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should convert a Ruby symbol to PDF name" do
|
99
|
-
Prawn::Core::PdfObject(:my_symbol).should == "/my_symbol"
|
100
|
-
Prawn::Core::PdfObject(:"A;Name_With-Various***Characters?").should ==
|
101
|
-
"/A;Name_With-Various***Characters?"
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should convert a whitespace or delimiter containing Ruby symbol to a PDF name" do
|
105
|
-
Prawn::Core::PdfObject(:"my symbol").should == "/my#20symbol"
|
106
|
-
Prawn::Core::PdfObject(:"my#symbol").should == "/my#23symbol"
|
107
|
-
Prawn::Core::PdfObject(:"my/symbol").should == "/my#2Fsymbol"
|
108
|
-
Prawn::Core::PdfObject(:"my(symbol").should == "/my#28symbol"
|
109
|
-
Prawn::Core::PdfObject(:"my)symbol").should == "/my#29symbol"
|
110
|
-
Prawn::Core::PdfObject(:"my<symbol").should == "/my#3Csymbol"
|
111
|
-
Prawn::Core::PdfObject(:"my>symbol").should == "/my#3Esymbol"
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should convert a Ruby array to PDF Array when inside a content stream" do
|
115
|
-
Prawn::Core::PdfObject([1,2,3]).should == "[1 2 3]"
|
116
|
-
PDF::Inspector.parse(Prawn::Core::PdfObject([[1,2],:foo,"Bar"], true)).should ==
|
117
|
-
[[1,2],:foo, "Bar"]
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should convert a Ruby array to PDF Array when outside a content stream" do
|
121
|
-
bar = "\xFE\xFF" + "Bar".unpack("U*").pack("n*")
|
122
|
-
Prawn::Core::PdfObject([1,2,3]).should == "[1 2 3]"
|
123
|
-
PDF::Inspector.parse(Prawn::Core::PdfObject([[1,2],:foo,"Bar"], false)).should ==
|
124
|
-
[[1,2],:foo, bar]
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should convert a Ruby hash to a PDF Dictionary when inside a content stream" do
|
128
|
-
dict = Prawn::Core::PdfObject( {:foo => :bar,
|
129
|
-
"baz" => [1,2,3],
|
130
|
-
:bang => {:a => "what", :b => [:you, :say] }}, true )
|
131
|
-
|
132
|
-
res = PDF::Inspector.parse(dict)
|
133
|
-
|
134
|
-
res[:foo].should == :bar
|
135
|
-
res[:baz].should == [1,2,3]
|
136
|
-
res[:bang].should == { :a => "what", :b => [:you, :say] }
|
137
|
-
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should convert a Ruby hash to a PDF Dictionary when outside a content stream" do
|
141
|
-
what = "\xFE\xFF" + "what".unpack("U*").pack("n*")
|
142
|
-
dict = Prawn::Core::PdfObject( {:foo => :bar,
|
143
|
-
"baz" => [1,2,3],
|
144
|
-
:bang => {:a => "what", :b => [:you, :say] }}, false )
|
145
|
-
|
146
|
-
res = PDF::Inspector.parse(dict)
|
147
|
-
|
148
|
-
res[:foo].should == :bar
|
149
|
-
res[:baz].should == [1,2,3]
|
150
|
-
res[:bang].should == { :a => what, :b => [:you, :say] }
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should not allow keys other than strings or symbols for PDF dicts" do
|
155
|
-
lambda { Prawn::Core::PdfObject(:foo => :bar, :baz => :bang, 1 => 4) }.
|
156
|
-
should raise_error(Prawn::Errors::FailedObjectConversion)
|
157
|
-
end
|
158
|
-
|
159
|
-
it "should convert a Prawn::Reference to a PDF indirect object reference" do
|
160
|
-
ref = Prawn::Core::Reference(1,true)
|
161
|
-
Prawn::Core::PdfObject(ref).should == ref.to_s
|
162
|
-
end
|
163
|
-
|
164
|
-
it "should convert a NameTree::Node to a PDF hash" do
|
165
|
-
node = Prawn::Core::NameTree::Node.new(Prawn::Document.new, 10)
|
166
|
-
node.add "hello", 1.0
|
167
|
-
node.add "world", 2.0
|
168
|
-
data = Prawn::Core::PdfObject(node)
|
169
|
-
res = PDF::Inspector.parse(data)
|
170
|
-
res.should == {:Names => ["hello", 1.0, "world", 2.0]}
|
171
|
-
end
|
172
|
-
end
|
data/spec/snapshot_spec.rb
DELETED
@@ -1,186 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
4
|
-
|
5
|
-
describe "Prawn::Document#transaction" do
|
6
|
-
|
7
|
-
it "should properly commit if no error is raised" do
|
8
|
-
pdf = Prawn::Document.new do
|
9
|
-
transaction do
|
10
|
-
text "This is shown"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
text = PDF::Inspector::Text.analyze(pdf.render)
|
14
|
-
text.strings.should == ["This is shown"]
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should not display text if transaction is rolled back" do
|
18
|
-
pdf = Prawn::Document.new do
|
19
|
-
transaction do
|
20
|
-
text "This is not shown"
|
21
|
-
rollback
|
22
|
-
end
|
23
|
-
end
|
24
|
-
text = PDF::Inspector::Text.analyze(pdf.render)
|
25
|
-
text.strings.should == []
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should return true/false value indicating success of the transaction" do
|
29
|
-
Prawn::Document.new do
|
30
|
-
success = transaction { }
|
31
|
-
success.should == true
|
32
|
-
|
33
|
-
success = transaction { rollback }
|
34
|
-
success.should == false
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should support nested transactions" do
|
39
|
-
pdf = Prawn::Document.new do
|
40
|
-
transaction do
|
41
|
-
text "This is shown"
|
42
|
-
transaction do
|
43
|
-
text "and this is not"
|
44
|
-
rollback
|
45
|
-
end
|
46
|
-
text "and this is"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
text = PDF::Inspector::Text.analyze(pdf.render)
|
50
|
-
text.strings.should == ["This is shown", "and this is"]
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should allow rollback of multiple pages" do
|
54
|
-
pdf = Prawn::Document.new do
|
55
|
-
transaction do
|
56
|
-
5.times { start_new_page }
|
57
|
-
text "way out there and will never be shown"
|
58
|
-
rollback
|
59
|
-
end
|
60
|
-
text "This is the real text, only one page"
|
61
|
-
end
|
62
|
-
|
63
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
64
|
-
pages.size.should == 1
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should not propagate a RollbackTransaction outside its bounds" do
|
68
|
-
def add_lines(pdf)
|
69
|
-
100.times { |i| pdf.text "Line #{i}" }
|
70
|
-
end
|
71
|
-
|
72
|
-
Prawn::Document.new do |pdf|
|
73
|
-
lambda do
|
74
|
-
begin
|
75
|
-
pdf.group { add_lines(pdf) }
|
76
|
-
rescue Prawn::Errors::CannotGroup
|
77
|
-
add_lines(pdf)
|
78
|
-
end
|
79
|
-
end.should_not raise_error#(Prawn::Document::Snapshot::RollbackTransaction)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Because the Pages object, when restored, points to the snapshotted pages
|
84
|
-
# by identifier, we have to restore the snapshot into the same page objects,
|
85
|
-
# or else old pages will appear in the post-rollback document.
|
86
|
-
it "should restore the pages into the same objects" do
|
87
|
-
Prawn::Document.new do
|
88
|
-
old_page_object_id = state.page.dictionary.identifier
|
89
|
-
old_page_content_id = state.page.content.identifier
|
90
|
-
|
91
|
-
transaction do
|
92
|
-
start_new_page
|
93
|
-
rollback
|
94
|
-
end
|
95
|
-
|
96
|
-
state.page.dictionary.identifier.should == old_page_object_id
|
97
|
-
state.page.content.identifier.should == old_page_content_id
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
101
|
-
|
102
|
-
it "page object should refer to the page_content object after restore" do
|
103
|
-
|
104
|
-
Prawn::Document.new do
|
105
|
-
transaction do
|
106
|
-
start_new_page
|
107
|
-
rollback
|
108
|
-
end
|
109
|
-
|
110
|
-
# should be the exact same object, not a clone
|
111
|
-
state.page.dictionary.data[:Contents].should == state.page.content
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should restore bounds on rollback" do
|
117
|
-
Prawn::Document.new(:page_layout => :landscape) do
|
118
|
-
size = [bounds.width, bounds.height]
|
119
|
-
transaction do
|
120
|
-
start_new_page :layout => :portrait
|
121
|
-
rollback
|
122
|
-
end
|
123
|
-
[bounds.width, bounds.height].should == size
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should set new bounding box on start_new_page with different layout" do
|
128
|
-
Prawn::Document.new(:page_layout => :landscape) do
|
129
|
-
size = [bounds.width, bounds.height]
|
130
|
-
transaction do
|
131
|
-
start_new_page
|
132
|
-
rollback
|
133
|
-
end
|
134
|
-
|
135
|
-
start_new_page :layout => :portrait
|
136
|
-
[bounds.width, bounds.height].should == size.reverse
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should work with dests" do
|
141
|
-
Prawn::Document.new do |pdf|
|
142
|
-
pdf.add_dest("dest", pdf.dest_fit_horizontally(pdf.cursor, pdf.page))
|
143
|
-
pdf.text("Hello world")
|
144
|
-
lambda { pdf.transaction{} }.should_not raise_error
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
describe "with a stamp dictionary present" do
|
149
|
-
|
150
|
-
it "should properly commit if no error is raised" do
|
151
|
-
pdf = Prawn::Document.new do
|
152
|
-
create_stamp("test_stamp") { draw_text "This is shown", :at => [0,0] }
|
153
|
-
transaction do
|
154
|
-
stamp("test_stamp")
|
155
|
-
end
|
156
|
-
end
|
157
|
-
pdf.render.should =~ /\/Stamp1 Do/
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should properly rollback when #rollback is called" do
|
161
|
-
pdf = Prawn::Document.new do
|
162
|
-
create_stamp("test_stamp") { draw_text "This is not shown", :at => [0,0] }
|
163
|
-
|
164
|
-
transaction do
|
165
|
-
stamp("test_stamp")
|
166
|
-
rollback
|
167
|
-
end
|
168
|
-
end
|
169
|
-
pdf.render.should_not =~ /\/Stamp1 Do/
|
170
|
-
end
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
it "should restore page_number on rollback" do
|
175
|
-
Prawn::Document.new do
|
176
|
-
transaction do
|
177
|
-
5.times { start_new_page }
|
178
|
-
rollback
|
179
|
-
end
|
180
|
-
|
181
|
-
page_number.should == 1
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|
186
|
-
|
data/spec/template_spec.rb
DELETED
@@ -1,351 +0,0 @@
|
|
1
|
-
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
2
|
-
|
3
|
-
describe "Document built from a template" do
|
4
|
-
it "should have the same page count as the source document" do
|
5
|
-
filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
|
6
|
-
@pdf = Prawn::Document.new(:template => filename)
|
7
|
-
page_counter = PDF::Inspector::Page.analyze(@pdf.render)
|
8
|
-
|
9
|
-
page_counter.pages.size.should == 1
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should not set the template page's parent to the document pages catalog (especially with nested pages)" do
|
13
|
-
filename = "#{Prawn::DATADIR}/pdfs/nested_pages.pdf"
|
14
|
-
@pdf = Prawn::Document.new(:template => filename, :skip_page_creation => true)
|
15
|
-
@pdf.state.page.dictionary.data[:Parent].should_not == @pdf.state.store.pages
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
it "should have start with the Y cursor at the top of the document" do
|
20
|
-
filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
|
21
|
-
|
22
|
-
@pdf = Prawn::Document.new(:template => filename)
|
23
|
-
(@pdf.y == nil).should == false
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should respect margins set by Prawn" do
|
27
|
-
filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
|
28
|
-
|
29
|
-
@pdf = Prawn::Document.new(:template => filename, :margin => 0)
|
30
|
-
@pdf.page.margins.should == { :left => 0,
|
31
|
-
:right => 0,
|
32
|
-
:top => 0,
|
33
|
-
:bottom => 0 }
|
34
|
-
|
35
|
-
@pdf = Prawn::Document.new(:template => filename, :left_margin => 0)
|
36
|
-
|
37
|
-
@pdf.page.margins.should == { :left => 0,
|
38
|
-
:right => 36,
|
39
|
-
:top => 36,
|
40
|
-
:bottom => 36 }
|
41
|
-
|
42
|
-
@pdf.start_new_page(:right_margin => 0)
|
43
|
-
|
44
|
-
@pdf.page.margins.should == { :left => 0,
|
45
|
-
:right => 0,
|
46
|
-
:top => 36,
|
47
|
-
:bottom => 36 }
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should not add an extra restore_graphics_state operator to the end of any content stream" do
|
54
|
-
filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
|
55
|
-
|
56
|
-
@pdf = Prawn::Document.new(:template => filename)
|
57
|
-
output = StringIO.new(@pdf.render)
|
58
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
59
|
-
|
60
|
-
hash.each_value do |obj|
|
61
|
-
next unless obj.kind_of?(PDF::Reader::Stream)
|
62
|
-
|
63
|
-
data = obj.data.tr(" \n\r","")
|
64
|
-
data.include?("QQ").should == false
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should have a single page object if importing a single page template" do
|
69
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
70
|
-
|
71
|
-
@pdf = Prawn::Document.new(:template => filename)
|
72
|
-
output = StringIO.new(@pdf.render)
|
73
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
74
|
-
|
75
|
-
pages = hash.values.select { |obj| obj.kind_of?(Hash) && obj[:Type] == :Page }
|
76
|
-
|
77
|
-
pages.size.should == 1
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should have two content streams if importing a single page template" do
|
81
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
82
|
-
|
83
|
-
@pdf = Prawn::Document.new(:template => filename)
|
84
|
-
output = StringIO.new(@pdf.render)
|
85
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
86
|
-
|
87
|
-
streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
|
88
|
-
|
89
|
-
streams.size.should == 2
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should not die if using this PDF as a template" do
|
93
|
-
filename = "#{Prawn::DATADIR}/pdfs/complex_template.pdf"
|
94
|
-
|
95
|
-
lambda {
|
96
|
-
@pdf = Prawn::Document.new(:template => filename)
|
97
|
-
}.should_not raise_error
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
it "should have balance q/Q operators on all content streams" do
|
102
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
103
|
-
|
104
|
-
@pdf = Prawn::Document.new(:template => filename)
|
105
|
-
output = StringIO.new(@pdf.render)
|
106
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
107
|
-
|
108
|
-
streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
|
109
|
-
|
110
|
-
streams.each do |stream|
|
111
|
-
data = stream.unfiltered_data
|
112
|
-
data.scan("q").size.should == 1
|
113
|
-
data.scan("Q").size.should == 1
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
it "should allow text to be added to a single page template" do
|
118
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
119
|
-
|
120
|
-
@pdf = Prawn::Document.new(:template => filename)
|
121
|
-
|
122
|
-
@pdf.text "Adding some text"
|
123
|
-
|
124
|
-
text = PDF::Inspector::Text.analyze(@pdf.render)
|
125
|
-
text.strings.first.should == "Adding some text"
|
126
|
-
end
|
127
|
-
|
128
|
-
it "should allow PDFs with page resources behind an indirect object to be used as templates" do
|
129
|
-
filename = "#{Prawn::DATADIR}/pdfs/resources_as_indirect_object.pdf"
|
130
|
-
|
131
|
-
@pdf = Prawn::Document.new(:template => filename)
|
132
|
-
|
133
|
-
@pdf.text "Adding some text"
|
134
|
-
|
135
|
-
text = PDF::Inspector::Text.analyze(@pdf.render)
|
136
|
-
all_text = text.strings.join
|
137
|
-
all_text.include?("Adding some text").should == true
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should copy the PDF version from the template file" do
|
141
|
-
filename = "#{Prawn::DATADIR}/pdfs/version_1_6.pdf"
|
142
|
-
|
143
|
-
@pdf = Prawn::Document.new(:template => filename)
|
144
|
-
str = @pdf.render
|
145
|
-
str[0,8].should == "%PDF-1.6"
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should correctly add a TTF font to a template that has existing fonts" do
|
149
|
-
filename = "#{Prawn::DATADIR}/pdfs/contains_ttf_font.pdf"
|
150
|
-
@pdf = Prawn::Document.new(:template => filename)
|
151
|
-
@pdf.font "#{Prawn::DATADIR}/fonts/Chalkboard.ttf"
|
152
|
-
@pdf.move_down(40)
|
153
|
-
@pdf.text "Hi There"
|
154
|
-
|
155
|
-
output = StringIO.new(@pdf.render)
|
156
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
157
|
-
|
158
|
-
page_dict = hash.values.detect{ |obj| obj.is_a?(Hash) && obj[:Type] == :Page }
|
159
|
-
resources = page_dict[:Resources]
|
160
|
-
fonts = resources[:Font]
|
161
|
-
fonts.size.should == 2
|
162
|
-
end
|
163
|
-
|
164
|
-
it "should correctly import a template file that is missing a MediaBox entry" do
|
165
|
-
filename = "#{Prawn::DATADIR}/pdfs/page_without_mediabox.pdf"
|
166
|
-
|
167
|
-
@pdf = Prawn::Document.new(:template => filename)
|
168
|
-
str = @pdf.render
|
169
|
-
str[0,4].should == "%PDF"
|
170
|
-
end
|
171
|
-
|
172
|
-
context "with the template as a stream" do
|
173
|
-
it "should correctly import a template file from a stream" do
|
174
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
175
|
-
io = StringIO.new(File.binread(filename))
|
176
|
-
@pdf = Prawn::Document.new(:template => io)
|
177
|
-
str = @pdf.render
|
178
|
-
str[0,4].should == "%PDF"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
it "merges metadata info" do
|
183
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
184
|
-
info = { :Title => "Sample METADATA",
|
185
|
-
:Author => "Me",
|
186
|
-
:Subject => "Not Working",
|
187
|
-
:CreationDate => Time.now }
|
188
|
-
|
189
|
-
@pdf = Prawn::Document.new(:template => filename, :info => info)
|
190
|
-
output = StringIO.new(@pdf.render)
|
191
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
192
|
-
info.keys.each { |k| hash[hash.trailer[:Info]].keys.include?(k).should == true }
|
193
|
-
end
|
194
|
-
|
195
|
-
end
|
196
|
-
|
197
|
-
describe "Document#start_new_page with :template option" do
|
198
|
-
filename = "#{Prawn::BASEDIR}/spec/data/curves.pdf"
|
199
|
-
|
200
|
-
it "should set the imported page's parent to the document pages catalog" do
|
201
|
-
@pdf = Prawn::Document.new()
|
202
|
-
@pdf.start_new_page(:template => filename)
|
203
|
-
@pdf.state.page.dictionary.data[:Parent].should == @pdf.state.store.pages
|
204
|
-
end
|
205
|
-
|
206
|
-
it "should set start the Y cursor at the top of the page" do
|
207
|
-
@pdf = Prawn::Document.new()
|
208
|
-
@pdf.start_new_page(:template => filename)
|
209
|
-
(@pdf.y == nil).should == false
|
210
|
-
end
|
211
|
-
|
212
|
-
it "should respect margins set by Prawn" do
|
213
|
-
@pdf = Prawn::Document.new(:margin => 0)
|
214
|
-
@pdf.start_new_page(:template => filename)
|
215
|
-
@pdf.page.margins.should == { :left => 0,
|
216
|
-
:right => 0,
|
217
|
-
:top => 0,
|
218
|
-
:bottom => 0 }
|
219
|
-
|
220
|
-
@pdf = Prawn::Document.new(:left_margin => 0)
|
221
|
-
@pdf.start_new_page(:template => filename)
|
222
|
-
@pdf.page.margins.should == { :left => 0,
|
223
|
-
:right => 36,
|
224
|
-
:top => 36,
|
225
|
-
:bottom => 36 }
|
226
|
-
@pdf.start_new_page(:template => filename, :right_margin => 0)
|
227
|
-
@pdf.page.margins.should == { :left => 0,
|
228
|
-
:right => 0,
|
229
|
-
:top => 36,
|
230
|
-
:bottom => 36 }
|
231
|
-
end
|
232
|
-
|
233
|
-
it "should not add an extra restore_graphics_state operator to the end of any content stream" do
|
234
|
-
@pdf = Prawn::Document.new
|
235
|
-
@pdf.start_new_page(:template => filename)
|
236
|
-
output = StringIO.new(@pdf.render)
|
237
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
238
|
-
|
239
|
-
hash.each_value do |obj|
|
240
|
-
next unless obj.kind_of?(PDF::Reader::Stream)
|
241
|
-
|
242
|
-
data = obj.data.tr(" \n\r","")
|
243
|
-
data.include?("QQ").should == false
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
it "should have two content streams if importing a single page template" do
|
248
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
249
|
-
@pdf = Prawn::Document.new()
|
250
|
-
@pdf.start_new_page(:template => filename)
|
251
|
-
output = StringIO.new(@pdf.render)
|
252
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
253
|
-
pages = hash.values.find {|obj| obj.is_a?(Hash) && obj[:Type] == :Pages}[:Kids]
|
254
|
-
template_page = hash[pages[1]]
|
255
|
-
template_page[:Contents].size.should == 2
|
256
|
-
end
|
257
|
-
|
258
|
-
it "should have balance q/Q operators on all content streams" do
|
259
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
260
|
-
|
261
|
-
@pdf = Prawn::Document.new()
|
262
|
-
@pdf.start_new_page(:template => filename)
|
263
|
-
output = StringIO.new(@pdf.render)
|
264
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
265
|
-
|
266
|
-
streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }
|
267
|
-
|
268
|
-
streams.each do |stream|
|
269
|
-
data = stream.unfiltered_data
|
270
|
-
data.scan("q").size.should == 1
|
271
|
-
data.scan("Q").size.should == 1
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
it "should allow text to be added to a single page template" do
|
276
|
-
|
277
|
-
@pdf = Prawn::Document.new()
|
278
|
-
@pdf.start_new_page(:template => filename)
|
279
|
-
|
280
|
-
@pdf.text "Adding some text"
|
281
|
-
|
282
|
-
text = PDF::Inspector::Text.analyze(@pdf.render)
|
283
|
-
text.strings.first.should == "Adding some text"
|
284
|
-
end
|
285
|
-
|
286
|
-
it "should allow PDFs with page resources behind an indirect object to be used as templates" do
|
287
|
-
filename = "#{Prawn::DATADIR}/pdfs/resources_as_indirect_object.pdf"
|
288
|
-
|
289
|
-
@pdf = Prawn::Document.new()
|
290
|
-
@pdf.start_new_page(:template => filename)
|
291
|
-
|
292
|
-
@pdf.text "Adding some text"
|
293
|
-
|
294
|
-
text = PDF::Inspector::Text.analyze(@pdf.render)
|
295
|
-
all_text = text.strings.join
|
296
|
-
all_text.include?("Adding some text").should == true
|
297
|
-
end
|
298
|
-
|
299
|
-
it "should correctly add a TTF font to a template that has existing fonts" do
|
300
|
-
filename = "#{Prawn::DATADIR}/pdfs/contains_ttf_font.pdf"
|
301
|
-
@pdf = Prawn::Document.new()
|
302
|
-
@pdf.start_new_page(:template => filename)
|
303
|
-
@pdf.font "#{Prawn::DATADIR}/fonts/Chalkboard.ttf"
|
304
|
-
@pdf.move_down(40)
|
305
|
-
@pdf.text "Hi There"
|
306
|
-
|
307
|
-
output = StringIO.new(@pdf.render)
|
308
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
309
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
310
|
-
pages = hash.values.find {|obj| obj.is_a?(Hash) && obj[:Type] == :Pages}[:Kids]
|
311
|
-
template_page = hash[pages[1]]
|
312
|
-
resources = template_page[:Resources]
|
313
|
-
fonts = resources[:Font]
|
314
|
-
fonts.size.should == 2
|
315
|
-
end
|
316
|
-
|
317
|
-
it "indexes template pages when used multiple times" do
|
318
|
-
filename = "#{Prawn::DATADIR}/pdfs/multipage_template.pdf"
|
319
|
-
@repeated_pdf = Prawn::Document.new()
|
320
|
-
3.times { @repeated_pdf.start_new_page(:template => filename) }
|
321
|
-
repeated_hash = PDF::Reader::ObjectHash.new(StringIO.new(@repeated_pdf.render))
|
322
|
-
@sequential_pdf = Prawn::Document.new()
|
323
|
-
(1..3).each { |p| @sequential_pdf.start_new_page(:template => filename, :template_page => p ) }
|
324
|
-
sequential_hash = PDF::Reader::ObjectHash.new(StringIO.new(@sequential_pdf.render))
|
325
|
-
(repeated_hash.size < sequential_hash.size).should == true
|
326
|
-
end
|
327
|
-
|
328
|
-
context "with the template as a stream" do
|
329
|
-
it "should correctly import a template file from a stream" do
|
330
|
-
filename = "#{Prawn::DATADIR}/pdfs/hexagon.pdf"
|
331
|
-
io = StringIO.new(File.binread(filename))
|
332
|
-
|
333
|
-
@pdf = Prawn::Document.new()
|
334
|
-
@pdf.start_new_page(:template => io)
|
335
|
-
|
336
|
-
str = @pdf.render
|
337
|
-
str[0,4].should == "%PDF"
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
context "using template_page option" do
|
342
|
-
it "uses the specified page option" do
|
343
|
-
filename = "#{Prawn::DATADIR}/pdfs/multipage_template.pdf"
|
344
|
-
@pdf = Prawn::Document.new()
|
345
|
-
@pdf.start_new_page(:template => filename, :template_page => 2)
|
346
|
-
text = PDF::Inspector::Text.analyze(@pdf.render)
|
347
|
-
text.strings.first.should == "This is template page 2"
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
end
|