prawn 0.1.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.
- data/COPYING +340 -0
- data/LICENSE +56 -0
- data/README +30 -0
- data/Rakefile +83 -0
- data/data/fonts/Activa.ttf +0 -0
- data/data/fonts/Chalkboard.ttf +0 -0
- data/data/fonts/Courier-Bold.afm +342 -0
- data/data/fonts/Courier-BoldOblique.afm +342 -0
- data/data/fonts/Courier-Oblique.afm +342 -0
- data/data/fonts/Courier.afm +342 -0
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/Helvetica-Bold.afm +2827 -0
- data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/data/fonts/Helvetica-Oblique.afm +3051 -0
- data/data/fonts/Helvetica.afm +3051 -0
- data/data/fonts/MustRead.html +19 -0
- data/data/fonts/Symbol.afm +213 -0
- data/data/fonts/Times-Bold.afm +2588 -0
- data/data/fonts/Times-BoldItalic.afm +2384 -0
- data/data/fonts/Times-Italic.afm +2667 -0
- data/data/fonts/Times-Roman.afm +2419 -0
- data/data/fonts/ZapfDingbats.afm +225 -0
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/shift_jis_text.txt +1 -0
- data/examples/addressbook.csv +6 -0
- data/examples/alignment.rb +16 -0
- data/examples/bounding_boxes.pdf +62 -0
- data/examples/bounding_boxes.rb +30 -0
- data/examples/canvas.pdf +81 -0
- data/examples/canvas.rb +12 -0
- data/examples/cell.rb +27 -0
- data/examples/currency.csv +1834 -0
- data/examples/curves.rb +10 -0
- data/examples/fancy_table.rb +48 -0
- data/examples/font_size.rb +19 -0
- data/examples/hexagon.rb +14 -0
- data/examples/image.pdf +0 -0
- data/examples/image.rb +23 -0
- data/examples/image2.rb +13 -0
- data/examples/inline_styles.pdf +117 -0
- data/examples/kerning.rb +27 -0
- data/examples/line.rb +31 -0
- data/examples/multi_page_layout.rb +14 -0
- data/examples/on_page_start.rb +17 -0
- data/examples/page_geometry.rb +28 -0
- data/examples/polygons.rb +16 -0
- data/examples/ruport_formatter.rb +47 -0
- data/examples/ruport_helpers.rb +17 -0
- data/examples/russian_boxes.rb +34 -0
- data/examples/simple_text.rb +15 -0
- data/examples/simple_text_ttf.rb +16 -0
- data/examples/sjis.rb +19 -0
- data/examples/table.rb +45 -0
- data/examples/table_bench.rb +92 -0
- data/examples/text_flow.rb +65 -0
- data/examples/utf8.rb +12 -0
- data/lib/prawn.rb +33 -0
- data/lib/prawn/compatibility.rb +33 -0
- data/lib/prawn/document.rb +334 -0
- data/lib/prawn/document/bounding_box.rb +253 -0
- data/lib/prawn/document/page_geometry.rb +78 -0
- data/lib/prawn/document/table.rb +253 -0
- data/lib/prawn/document/text.rb +346 -0
- data/lib/prawn/errors.rb +33 -0
- data/lib/prawn/font.rb +5 -0
- data/lib/prawn/font/cmap.rb +59 -0
- data/lib/prawn/font/metrics.rb +414 -0
- data/lib/prawn/font/wrapping.rb +45 -0
- data/lib/prawn/graphics.rb +285 -0
- data/lib/prawn/graphics/cell.rb +226 -0
- data/lib/prawn/images.rb +241 -0
- data/lib/prawn/images/jpg.rb +43 -0
- data/lib/prawn/images/png.rb +178 -0
- data/lib/prawn/pdf_object.rb +64 -0
- data/lib/prawn/reference.rb +47 -0
- data/spec/bounding_box_spec.rb +120 -0
- data/spec/box_calculation_spec.rb +17 -0
- data/spec/document_spec.rb +152 -0
- data/spec/graphics_spec.rb +250 -0
- data/spec/images_spec.rb +42 -0
- data/spec/jpg_spec.rb +25 -0
- data/spec/metrics_spec.rb +60 -0
- data/spec/pdf_object_spec.rb +102 -0
- data/spec/png_spec.rb +35 -0
- data/spec/reference_spec.rb +29 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/table_spec.rb +145 -0
- data/spec/text_spec.rb +190 -0
- data/vendor/font_ttf/ttf.rb +20 -0
- data/vendor/font_ttf/ttf/datatypes.rb +189 -0
- data/vendor/font_ttf/ttf/encodings.rb +140 -0
- data/vendor/font_ttf/ttf/exceptions.rb +28 -0
- data/vendor/font_ttf/ttf/file.rb +290 -0
- data/vendor/font_ttf/ttf/fontchunk.rb +77 -0
- data/vendor/font_ttf/ttf/table/cmap.rb +408 -0
- data/vendor/font_ttf/ttf/table/cvt.rb +49 -0
- data/vendor/font_ttf/ttf/table/fpgm.rb +48 -0
- data/vendor/font_ttf/ttf/table/gasp.rb +88 -0
- data/vendor/font_ttf/ttf/table/glyf.rb +452 -0
- data/vendor/font_ttf/ttf/table/head.rb +86 -0
- data/vendor/font_ttf/ttf/table/hhea.rb +96 -0
- data/vendor/font_ttf/ttf/table/hmtx.rb +98 -0
- data/vendor/font_ttf/ttf/table/kern.rb +186 -0
- data/vendor/font_ttf/ttf/table/loca.rb +75 -0
- data/vendor/font_ttf/ttf/table/maxp.rb +81 -0
- data/vendor/font_ttf/ttf/table/name.rb +222 -0
- data/vendor/font_ttf/ttf/table/os2.rb +172 -0
- data/vendor/font_ttf/ttf/table/post.rb +120 -0
- data/vendor/font_ttf/ttf/table/prep.rb +27 -0
- data/vendor/font_ttf/ttf/table/vhea.rb +45 -0
- data/vendor/font_ttf/ttf/table/vmtx.rb +36 -0
- metadata +180 -0
data/spec/images_spec.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
4
|
+
|
|
5
|
+
class ImageObserver
|
|
6
|
+
|
|
7
|
+
attr_accessor :page_xobjects
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@page_xobjects = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def resource_xobject(*params)
|
|
14
|
+
@page_xobjects.last << params.first
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def begin_page(*params)
|
|
18
|
+
@page_xobjects << []
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "the image() function" do
|
|
23
|
+
|
|
24
|
+
before(:each) do
|
|
25
|
+
@filename = "#{Prawn::BASEDIR}/data/images/pigs.jpg"
|
|
26
|
+
create_pdf
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should only embed an image once, even if it's added multiple times" do
|
|
30
|
+
@pdf.image @filename, :at => [100,100]
|
|
31
|
+
@pdf.image @filename, :at => [300,300]
|
|
32
|
+
|
|
33
|
+
images = observer(ImageObserver)
|
|
34
|
+
|
|
35
|
+
# there should be 2 images in the page resources
|
|
36
|
+
images.page_xobjects.first.size.should eql(2)
|
|
37
|
+
|
|
38
|
+
# but only 1 image xobject
|
|
39
|
+
@output.scan(/\/Type \/XObject/).size.should eql(1)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
data/spec/jpg_spec.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# Spec'ing the PNG class. Not complete yet - still needs to check the
|
|
4
|
+
# contents of palette and transparency to ensure they're correct.
|
|
5
|
+
# Need to find files that have these sections first.
|
|
6
|
+
|
|
7
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
8
|
+
|
|
9
|
+
describe "When reading a JPEG file" do
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
@filename = "#{Prawn::BASEDIR}/data/images/pigs.jpg"
|
|
13
|
+
@img_data = File.open(@filename, "rb") { |f| f.read }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should read the basic attributes correctly" do
|
|
17
|
+
jpg = Prawn::Images::JPG.new(@img_data)
|
|
18
|
+
|
|
19
|
+
jpg.width.should eql(604)
|
|
20
|
+
jpg.height.should eql(453)
|
|
21
|
+
jpg.bits.should eql(8)
|
|
22
|
+
jpg.channels.should eql(3)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# encoding: ASCII-8BIT
|
|
2
|
+
|
|
3
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
4
|
+
|
|
5
|
+
describe "adobe font metrics" do
|
|
6
|
+
|
|
7
|
+
setup do
|
|
8
|
+
@times = Prawn::Font::Metrics["Times-Roman"]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should calculate string width taking into account accented characters" do
|
|
12
|
+
@times.string_width("é", 12).should == @times.string_width("e", 12)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should calculate string width taking into account kerning pairs" do
|
|
16
|
+
@times.string_width("To", 12).should == 13.332
|
|
17
|
+
@times.string_width("To", 12, :kerning => true).should == 12.372
|
|
18
|
+
@times.string_width("Tö", 12, :kerning => true).should == 12.372
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should kern a string" do
|
|
22
|
+
@times.kern("To").should == ["T", 80, "o"]
|
|
23
|
+
@times.kern("Télé").should == ["T", 70, "\303\251l\303\251"]
|
|
24
|
+
@times.kern("Technology").should == ["T", 70, "echnology"]
|
|
25
|
+
@times.kern("Technology...").should == ["T", 70, "echnology", 65, "..."]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "ttf font metrics" do
|
|
31
|
+
|
|
32
|
+
setup do
|
|
33
|
+
@activa = Prawn::Font::Metrics["#{Prawn::BASEDIR}/data/fonts/Activa.ttf"]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should calculate string width taking into account accented characters" do
|
|
37
|
+
@activa.string_width("é", 12).should == @activa.string_width("e", 12)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should calculate string width taking into account kerning pairs" do
|
|
41
|
+
@activa.string_width("To", 12).should == 15.228
|
|
42
|
+
@activa.string_width("To", 12, :kerning => true).should.to_s == 12.996.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should kern a string" do
|
|
46
|
+
@activa.kern("To").should == ["\0007", 186.0, "\000R"]
|
|
47
|
+
|
|
48
|
+
# Does activa use kerning classes here? Ruby/TTF doesn't support
|
|
49
|
+
# format 2 kerning tables, so don't bother for now.
|
|
50
|
+
|
|
51
|
+
# @activa.kern("Télé").should == ["T", -186, "élé"]
|
|
52
|
+
|
|
53
|
+
@activa.kern("Technology").should == ["\0007", 186.0,
|
|
54
|
+
"\000H\000F\000K\000Q\000R\000O\000R\000J\000\\"]
|
|
55
|
+
@activa.kern("Technology...").should == ["\0007", 186.0,
|
|
56
|
+
"\000H\000F\000K\000Q\000R\000O\000R\000J\000\\", 88.0,
|
|
57
|
+
"\000\021\000\021\000\021"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
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::PdfObject(nil).should == "null"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should convert Ruby booleans to PDF booleans" do
|
|
13
|
+
Prawn::PdfObject(true).should == "true"
|
|
14
|
+
Prawn::PdfObject(false).should == "false"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should convert a Ruby number to PDF number" do
|
|
18
|
+
Prawn::PdfObject(1).should == "1"
|
|
19
|
+
Prawn::PdfObject(1.214112421).should == "1.214112421"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should convert a Ruby string to PDF string when inside a content stream" do
|
|
23
|
+
s = "I can has a string"
|
|
24
|
+
parse_pdf_object(Prawn::PdfObject(s, true)).should == s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should convert a Ruby string to a UTF-16 PDF string when outside a content stream" do
|
|
28
|
+
s = "I can has a string"
|
|
29
|
+
s_utf16 = "\xFE\xFF" + s.unpack("U*").pack("n*")
|
|
30
|
+
parse_pdf_object(Prawn::PdfObject(s, false)).should == s_utf16
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should escape parens when converting from Ruby string to PDF" do
|
|
34
|
+
s = 'I )(can has a string'
|
|
35
|
+
parse_pdf_object(Prawn::PdfObject(s, true)).should == s
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should handle ruby escaped parens when converting to PDF string" do
|
|
39
|
+
s = 'I can \\)( has string'
|
|
40
|
+
parse_pdf_object(Prawn::PdfObject(s, true)).should == s
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should convert a Ruby symbol to PDF name" do
|
|
44
|
+
Prawn::PdfObject(:my_symbol).should == "/my_symbol"
|
|
45
|
+
Prawn::PdfObject(:"A;Name_With−Various***Characters?").should ==
|
|
46
|
+
"/A;Name_With−Various***Characters?"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should not convert a whitespace containing Ruby symbol to a PDF name" do
|
|
50
|
+
lambda { Prawn::PdfObject(:"My Symbol With Spaces") }.
|
|
51
|
+
should raise_error(Prawn::Errors::FailedObjectConversion)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should convert a Ruby array to PDF Array when inside a content stream" do
|
|
55
|
+
Prawn::PdfObject([1,2,3]).should == "[1 2 3]"
|
|
56
|
+
parse_pdf_object(Prawn::PdfObject([[1,2],:foo,"Bar"], true)).should ==
|
|
57
|
+
[[1,2],:foo, "Bar"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should convert a Ruby array to PDF Array when outside a content stream" do
|
|
61
|
+
Prawn::PdfObject([1,2,3]).should == "[1 2 3]"
|
|
62
|
+
parse_pdf_object(Prawn::PdfObject([[1,2],:foo,"Bar"], false)).should ==
|
|
63
|
+
[[1,2],:foo, "\xFE\xFF\x00B\x00a\x00r"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should convert a Ruby hash to a PDF Dictionary when inside a content stream" do
|
|
67
|
+
dict = Prawn::PdfObject( {:foo => :bar,
|
|
68
|
+
"baz" => [1,2,3],
|
|
69
|
+
:bang => {:a => "what", :b => [:you, :say] }}, true )
|
|
70
|
+
|
|
71
|
+
res = parse_pdf_object(dict)
|
|
72
|
+
|
|
73
|
+
res[:foo].should == :bar
|
|
74
|
+
res[:baz].should == [1,2,3]
|
|
75
|
+
res[:bang].should == { :a => "what", :b => [:you, :say] }
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should convert a Ruby hash to a PDF Dictionary when outside a content stream" do
|
|
80
|
+
dict = Prawn::PdfObject( {:foo => :bar,
|
|
81
|
+
"baz" => [1,2,3],
|
|
82
|
+
:bang => {:a => "what", :b => [:you, :say] }}, false )
|
|
83
|
+
|
|
84
|
+
res = parse_pdf_object(dict)
|
|
85
|
+
|
|
86
|
+
res[:foo].should == :bar
|
|
87
|
+
res[:baz].should == [1,2,3]
|
|
88
|
+
res[:bang].should == { :a => "\xFE\xFF\x00w\x00h\x00a\x00t", :b => [:you, :say] }
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should not allow keys other than strings or symbols for PDF dicts" do
|
|
93
|
+
lambda { Prawn::PdfObject(:foo => :bar, :baz => :bang, 1 => 4) }.
|
|
94
|
+
should raise_error(Prawn::Errors::FailedObjectConversion)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "should convert a Prawn::Reference to a PDF indirect object reference" do
|
|
98
|
+
ref = Prawn::Reference(1,true)
|
|
99
|
+
Prawn::PdfObject(ref).should == ref.to_s
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
data/spec/png_spec.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# Spec'ing the PNG class. Not complete yet - still needs to check the
|
|
4
|
+
# contents of palette and transparency to ensure they're correct.
|
|
5
|
+
# Need to find files that have these sections first.
|
|
6
|
+
|
|
7
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
8
|
+
|
|
9
|
+
describe "When reading an RGB PNG file" do
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
@filename = "#{Prawn::BASEDIR}/data/images/ruport.png"
|
|
13
|
+
@data_filename = "#{Prawn::BASEDIR}/data/images/ruport_data.dat"
|
|
14
|
+
@img_data = File.open(@filename, "rb") { |f| f.read }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should read the attributes from the header chunk correctly" do
|
|
18
|
+
png = Prawn::Images::PNG.new(@img_data)
|
|
19
|
+
|
|
20
|
+
png.width.should eql(258)
|
|
21
|
+
png.height.should eql(105)
|
|
22
|
+
png.bits.should eql(8)
|
|
23
|
+
png.color_type.should eql(2)
|
|
24
|
+
png.compression_method.should eql(0)
|
|
25
|
+
png.filter_method.should eql(0)
|
|
26
|
+
png.interlace_method.should eql(0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should read the image data chunk correctly" do
|
|
30
|
+
png = Prawn::Images::PNG.new(@img_data)
|
|
31
|
+
data = File.open(@data_filename) { |f| f.read }
|
|
32
|
+
png.img_data.should eql(data)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
4
|
+
|
|
5
|
+
describe "A Reference object" do
|
|
6
|
+
it "should produce a PDF reference on #to_s call" do
|
|
7
|
+
ref = Prawn::Reference(1,true)
|
|
8
|
+
ref.to_s.should == "1 0 R"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should allow changing generation number" do
|
|
12
|
+
ref = Prawn::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 = Prawn::Reference(2,[1,"foo"])
|
|
19
|
+
ref.object.should == "2 0 obj\n#{Prawn::PdfObject([1,"foo"])}\nendobj\n"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should automatically open a stream when #<< is used" do
|
|
23
|
+
ref = Prawn::Reference(1, :Length => 41)
|
|
24
|
+
ref << "BT\n/F1 12 Tf\n72 712 Td\n( A stream ) Tj\nET"
|
|
25
|
+
ref.object.should == "1 0 obj\n<< /Length 41\n>>\nstream"+
|
|
26
|
+
"\nBT\n/F1 12 Tf\n72 712 Td\n( A stream ) Tj\nET" +
|
|
27
|
+
"\nendstream\nendobj\n"
|
|
28
|
+
end
|
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
puts "Prawn specs: Running on Ruby Version: #{RUBY_VERSION}"
|
|
4
|
+
|
|
5
|
+
require "rubygems"
|
|
6
|
+
require "spec"
|
|
7
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
8
|
+
require "prawn"
|
|
9
|
+
gem 'pdf-reader', ">=0.7.3"
|
|
10
|
+
require "pdf/reader"
|
|
11
|
+
|
|
12
|
+
def create_pdf
|
|
13
|
+
@pdf = Prawn::Document.new(:left_margin => 0,
|
|
14
|
+
:right_margin => 0,
|
|
15
|
+
:top_margin => 0,
|
|
16
|
+
:bottom_margin => 0)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def observer(klass)
|
|
20
|
+
@output = @pdf.render
|
|
21
|
+
obs = klass.new
|
|
22
|
+
PDF::Reader.string(@output,obs)
|
|
23
|
+
obs
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def parse_pdf_object(obj)
|
|
27
|
+
PDF::Reader::Parser.new(
|
|
28
|
+
PDF::Reader::Buffer.new(sio = StringIO.new(obj)), nil).parse_token
|
|
29
|
+
end
|
data/spec/table_spec.rb
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
4
|
+
|
|
5
|
+
describe "A table's width" do
|
|
6
|
+
it "should equal sum(col_widths)" do
|
|
7
|
+
pdf = Prawn::Document.new
|
|
8
|
+
table = Prawn::Document::Table.new( [%w[ a b c ], %w[d e f]], pdf,
|
|
9
|
+
:widths => { 0 => 50, 1 => 100, 2 => 150 })
|
|
10
|
+
|
|
11
|
+
table.width.should == 300
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should calculate unspecified column widths as "+
|
|
15
|
+
"(max(string_width) + 2*horizontal_padding)" do
|
|
16
|
+
pdf = Prawn::Document.new
|
|
17
|
+
hpad, fs = 3, 12
|
|
18
|
+
columns = 2
|
|
19
|
+
table = Prawn::Document::Table.new( [%w[ foo b ], %w[d foobar]], pdf,
|
|
20
|
+
:horizontal_padding => hpad, :font_size => fs)
|
|
21
|
+
|
|
22
|
+
col0_width = pdf.font_metrics.string_width("foo",fs)
|
|
23
|
+
col1_width = pdf.font_metrics.string_width("foobar",fs)
|
|
24
|
+
|
|
25
|
+
table.width.should == col0_width + col1_width + 2*columns*hpad
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should allow mixing autocalculated and preset"+
|
|
29
|
+
"column widths within a single table" do
|
|
30
|
+
|
|
31
|
+
pdf = Prawn::Document.new
|
|
32
|
+
hpad, fs = 10, 6
|
|
33
|
+
stretchy_columns = 2
|
|
34
|
+
|
|
35
|
+
col0_width = 50
|
|
36
|
+
col1_width = pdf.font_metrics.string_width("foo",fs)
|
|
37
|
+
col2_width = pdf.font_metrics.string_width("foobar",fs)
|
|
38
|
+
col3_width = 150
|
|
39
|
+
|
|
40
|
+
table = Prawn::Document::Table.new( [%w[snake foo b apple],
|
|
41
|
+
%w[kitten d foobar banana]], pdf,
|
|
42
|
+
:horizontal_padding => hpad, :font_size => fs,
|
|
43
|
+
:widths => { 0 => col0_width, 3 => col3_width } )
|
|
44
|
+
|
|
45
|
+
table.width.should == col1_width + col2_width + 2*stretchy_columns*hpad +
|
|
46
|
+
col0_width + col3_width
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should paginate large tables" do
|
|
51
|
+
# 30 rows fit on the table with default setting, 31 exceed.
|
|
52
|
+
data = [["foo"]] * 31
|
|
53
|
+
pdf = Prawn::Document.new
|
|
54
|
+
|
|
55
|
+
pdf.table data
|
|
56
|
+
pdf.page_count.should == 2
|
|
57
|
+
|
|
58
|
+
pdf.table data
|
|
59
|
+
pdf.page_count.should == 3
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should have a height of n rows + vertical padding" do
|
|
63
|
+
data = [["foo"],["bar"],["baaaz"]]
|
|
64
|
+
pdf = Prawn::Document.new
|
|
65
|
+
num_rows = data.length
|
|
66
|
+
vpad = 4
|
|
67
|
+
|
|
68
|
+
origin = pdf.y
|
|
69
|
+
pdf.table data, :vertical_padding => vpad
|
|
70
|
+
|
|
71
|
+
table_height = origin - pdf.y
|
|
72
|
+
|
|
73
|
+
font_height = pdf.font_metrics.font_height(12)
|
|
74
|
+
|
|
75
|
+
table_height.should be_close(num_rows*font_height + 2*vpad*num_rows + vpad, 0.001)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class TableTextObserver
|
|
81
|
+
attr_accessor :font_settings, :size, :strings
|
|
82
|
+
|
|
83
|
+
def initialize
|
|
84
|
+
@font_settings = []
|
|
85
|
+
@fonts = {}
|
|
86
|
+
@strings = []
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def resource_font(*params)
|
|
90
|
+
@fonts[params[0]] = params[1].basefont
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def set_text_font_and_size(*params)
|
|
94
|
+
@font_settings << { :name => @fonts[params[0]], :size => params[1] }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def show_text(*params)
|
|
98
|
+
@strings << params[0]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def show_text_with_positioning(*params)
|
|
102
|
+
# ignore kerning information
|
|
103
|
+
@strings << params[0].reject { |e| Numeric === e }.join
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
describe "A table's content" do
|
|
109
|
+
|
|
110
|
+
it "should output content cell by cell, row by row" do
|
|
111
|
+
data = [["foo","bar"],["baz","bang"]]
|
|
112
|
+
@pdf = Prawn::Document.new
|
|
113
|
+
@pdf.table(data)
|
|
114
|
+
output = observer(TableTextObserver)
|
|
115
|
+
output.strings.should == data.flatten
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should add headers to output when specified" do
|
|
119
|
+
data = [["foo","bar"],["baz","bang"]]
|
|
120
|
+
headers = %w[a b]
|
|
121
|
+
@pdf = Prawn::Document.new
|
|
122
|
+
@pdf.table(data, :headers => headers)
|
|
123
|
+
output = observer(TableTextObserver)
|
|
124
|
+
output.strings.should == headers + data.flatten
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "should repeat headers across pages" do
|
|
128
|
+
data = [["foo","bar"]]*30
|
|
129
|
+
headers = ["baz","foobar"]
|
|
130
|
+
@pdf = Prawn::Document.new
|
|
131
|
+
@pdf.table(data, :headers => headers)
|
|
132
|
+
output = observer(TableTextObserver)
|
|
133
|
+
output.strings.should == headers + data.flatten[0..-3] + headers +
|
|
134
|
+
data.flatten[-2..-1]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "should allow empty fields" do
|
|
138
|
+
lambda {
|
|
139
|
+
data = [["foo","bar"],["baz",""]]
|
|
140
|
+
@pdf = Prawn::Document.new
|
|
141
|
+
@pdf.table(data)
|
|
142
|
+
}.should_not raise_error
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
end
|