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.
Files changed (120) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +56 -0
  3. data/README +30 -0
  4. data/Rakefile +83 -0
  5. data/data/fonts/Activa.ttf +0 -0
  6. data/data/fonts/Chalkboard.ttf +0 -0
  7. data/data/fonts/Courier-Bold.afm +342 -0
  8. data/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/data/fonts/Courier-Oblique.afm +342 -0
  10. data/data/fonts/Courier.afm +342 -0
  11. data/data/fonts/DejaVuSans.ttf +0 -0
  12. data/data/fonts/Dustismo_Roman.ttf +0 -0
  13. data/data/fonts/Helvetica-Bold.afm +2827 -0
  14. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  15. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  16. data/data/fonts/Helvetica.afm +3051 -0
  17. data/data/fonts/MustRead.html +19 -0
  18. data/data/fonts/Symbol.afm +213 -0
  19. data/data/fonts/Times-Bold.afm +2588 -0
  20. data/data/fonts/Times-BoldItalic.afm +2384 -0
  21. data/data/fonts/Times-Italic.afm +2667 -0
  22. data/data/fonts/Times-Roman.afm +2419 -0
  23. data/data/fonts/ZapfDingbats.afm +225 -0
  24. data/data/fonts/comicsans.ttf +0 -0
  25. data/data/fonts/gkai00mp.ttf +0 -0
  26. data/data/images/dice.png +0 -0
  27. data/data/images/pigs.jpg +0 -0
  28. data/data/images/ruport.png +0 -0
  29. data/data/images/ruport_data.dat +0 -0
  30. data/data/images/ruport_transparent.png +0 -0
  31. data/data/images/stef.jpg +0 -0
  32. data/data/shift_jis_text.txt +1 -0
  33. data/examples/addressbook.csv +6 -0
  34. data/examples/alignment.rb +16 -0
  35. data/examples/bounding_boxes.pdf +62 -0
  36. data/examples/bounding_boxes.rb +30 -0
  37. data/examples/canvas.pdf +81 -0
  38. data/examples/canvas.rb +12 -0
  39. data/examples/cell.rb +27 -0
  40. data/examples/currency.csv +1834 -0
  41. data/examples/curves.rb +10 -0
  42. data/examples/fancy_table.rb +48 -0
  43. data/examples/font_size.rb +19 -0
  44. data/examples/hexagon.rb +14 -0
  45. data/examples/image.pdf +0 -0
  46. data/examples/image.rb +23 -0
  47. data/examples/image2.rb +13 -0
  48. data/examples/inline_styles.pdf +117 -0
  49. data/examples/kerning.rb +27 -0
  50. data/examples/line.rb +31 -0
  51. data/examples/multi_page_layout.rb +14 -0
  52. data/examples/on_page_start.rb +17 -0
  53. data/examples/page_geometry.rb +28 -0
  54. data/examples/polygons.rb +16 -0
  55. data/examples/ruport_formatter.rb +47 -0
  56. data/examples/ruport_helpers.rb +17 -0
  57. data/examples/russian_boxes.rb +34 -0
  58. data/examples/simple_text.rb +15 -0
  59. data/examples/simple_text_ttf.rb +16 -0
  60. data/examples/sjis.rb +19 -0
  61. data/examples/table.rb +45 -0
  62. data/examples/table_bench.rb +92 -0
  63. data/examples/text_flow.rb +65 -0
  64. data/examples/utf8.rb +12 -0
  65. data/lib/prawn.rb +33 -0
  66. data/lib/prawn/compatibility.rb +33 -0
  67. data/lib/prawn/document.rb +334 -0
  68. data/lib/prawn/document/bounding_box.rb +253 -0
  69. data/lib/prawn/document/page_geometry.rb +78 -0
  70. data/lib/prawn/document/table.rb +253 -0
  71. data/lib/prawn/document/text.rb +346 -0
  72. data/lib/prawn/errors.rb +33 -0
  73. data/lib/prawn/font.rb +5 -0
  74. data/lib/prawn/font/cmap.rb +59 -0
  75. data/lib/prawn/font/metrics.rb +414 -0
  76. data/lib/prawn/font/wrapping.rb +45 -0
  77. data/lib/prawn/graphics.rb +285 -0
  78. data/lib/prawn/graphics/cell.rb +226 -0
  79. data/lib/prawn/images.rb +241 -0
  80. data/lib/prawn/images/jpg.rb +43 -0
  81. data/lib/prawn/images/png.rb +178 -0
  82. data/lib/prawn/pdf_object.rb +64 -0
  83. data/lib/prawn/reference.rb +47 -0
  84. data/spec/bounding_box_spec.rb +120 -0
  85. data/spec/box_calculation_spec.rb +17 -0
  86. data/spec/document_spec.rb +152 -0
  87. data/spec/graphics_spec.rb +250 -0
  88. data/spec/images_spec.rb +42 -0
  89. data/spec/jpg_spec.rb +25 -0
  90. data/spec/metrics_spec.rb +60 -0
  91. data/spec/pdf_object_spec.rb +102 -0
  92. data/spec/png_spec.rb +35 -0
  93. data/spec/reference_spec.rb +29 -0
  94. data/spec/spec_helper.rb +29 -0
  95. data/spec/table_spec.rb +145 -0
  96. data/spec/text_spec.rb +190 -0
  97. data/vendor/font_ttf/ttf.rb +20 -0
  98. data/vendor/font_ttf/ttf/datatypes.rb +189 -0
  99. data/vendor/font_ttf/ttf/encodings.rb +140 -0
  100. data/vendor/font_ttf/ttf/exceptions.rb +28 -0
  101. data/vendor/font_ttf/ttf/file.rb +290 -0
  102. data/vendor/font_ttf/ttf/fontchunk.rb +77 -0
  103. data/vendor/font_ttf/ttf/table/cmap.rb +408 -0
  104. data/vendor/font_ttf/ttf/table/cvt.rb +49 -0
  105. data/vendor/font_ttf/ttf/table/fpgm.rb +48 -0
  106. data/vendor/font_ttf/ttf/table/gasp.rb +88 -0
  107. data/vendor/font_ttf/ttf/table/glyf.rb +452 -0
  108. data/vendor/font_ttf/ttf/table/head.rb +86 -0
  109. data/vendor/font_ttf/ttf/table/hhea.rb +96 -0
  110. data/vendor/font_ttf/ttf/table/hmtx.rb +98 -0
  111. data/vendor/font_ttf/ttf/table/kern.rb +186 -0
  112. data/vendor/font_ttf/ttf/table/loca.rb +75 -0
  113. data/vendor/font_ttf/ttf/table/maxp.rb +81 -0
  114. data/vendor/font_ttf/ttf/table/name.rb +222 -0
  115. data/vendor/font_ttf/ttf/table/os2.rb +172 -0
  116. data/vendor/font_ttf/ttf/table/post.rb +120 -0
  117. data/vendor/font_ttf/ttf/table/prep.rb +27 -0
  118. data/vendor/font_ttf/ttf/table/vhea.rb +45 -0
  119. data/vendor/font_ttf/ttf/table/vmtx.rb +36 -0
  120. metadata +180 -0
@@ -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
+
@@ -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
@@ -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
@@ -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
@@ -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