alphasights-prawn 0.10.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/HACKING +50 -0
- data/LICENSE +56 -0
- data/README +141 -0
- data/Rakefile +52 -0
- data/data/encodings/win_ansi.txt +29 -0
- 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/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/16bit.alpha +0 -0
- data/data/images/16bit.dat +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/rails.dat +0 -0
- data/data/images/rails.png +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/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +1 -0
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/hexagon.pdf +61 -0
- data/data/pdfs/indirect_reference.pdf +86 -0
- data/data/pdfs/nested_pages.pdf +118 -0
- data/data/pdfs/resources_as_indirect_object.pdf +83 -0
- data/data/pdfs/two_hexagons.pdf +90 -0
- data/data/pdfs/version_1_6.pdf +61 -0
- data/data/shift_jis_text.txt +1 -0
- data/examples/bounding_box/bounding_boxes.rb +43 -0
- data/examples/bounding_box/indentation.rb +34 -0
- data/examples/bounding_box/russian_boxes.rb +36 -0
- data/examples/bounding_box/stretched_nesting.rb +67 -0
- data/examples/builder/simple.rb +28 -0
- data/examples/example_helper.rb +4 -0
- data/examples/general/background.rb +23 -0
- data/examples/general/canvas.rb +15 -0
- data/examples/general/context_sensitive_headers.rb +37 -0
- data/examples/general/float.rb +11 -0
- data/examples/general/margin.rb +36 -0
- data/examples/general/measurement_units.rb +51 -0
- data/examples/general/metadata-info.rb +16 -0
- data/examples/general/multi_page_layout.rb +18 -0
- data/examples/general/outlines.rb +50 -0
- data/examples/general/page_geometry.rb +31 -0
- data/examples/general/page_numbering.rb +15 -0
- data/examples/general/repeaters.rb +47 -0
- data/examples/general/stamp.rb +41 -0
- data/examples/general/templates.rb +13 -0
- data/examples/graphics/basic_images.rb +23 -0
- data/examples/graphics/chunkable.rb +38 -0
- data/examples/graphics/cmyk.rb +12 -0
- data/examples/graphics/curves.rb +11 -0
- data/examples/graphics/hexagon.rb +13 -0
- data/examples/graphics/image_fit.rb +15 -0
- data/examples/graphics/image_flow.rb +37 -0
- data/examples/graphics/image_position.rb +17 -0
- data/examples/graphics/line.rb +32 -0
- data/examples/graphics/png_types.rb +22 -0
- data/examples/graphics/polygons.rb +16 -0
- data/examples/graphics/remote_images.rb +12 -0
- data/examples/graphics/rounded_polygons.rb +19 -0
- data/examples/graphics/rounded_rectangle.rb +20 -0
- data/examples/graphics/ruport_style_helpers.rb +19 -0
- data/examples/graphics/stroke_bounds.rb +20 -0
- data/examples/graphics/stroke_cap_and_join.rb +45 -0
- data/examples/graphics/stroke_dash.rb +42 -0
- data/examples/graphics/transformations.rb +52 -0
- data/examples/graphics/transparency.rb +26 -0
- data/examples/m17n/chinese_text_wrapping.rb +17 -0
- data/examples/m17n/euro.rb +15 -0
- data/examples/m17n/sjis.rb +28 -0
- data/examples/m17n/utf8.rb +13 -0
- data/examples/m17n/win_ansi_charset.rb +54 -0
- data/examples/security/hello_foo.rb +8 -0
- data/examples/table/bill.rb +53 -0
- data/examples/table/cell.rb +12 -0
- data/examples/table/checkerboard.rb +22 -0
- data/examples/table/header.rb +14 -0
- data/examples/table/inline_format_table.rb +12 -0
- data/examples/table/multi_page_table.rb +9 -0
- data/examples/table/simple_table.rb +24 -0
- data/examples/table/subtable.rb +12 -0
- data/examples/table/widths.rb +20 -0
- data/examples/text/alignment.rb +18 -0
- data/examples/text/character_spacing.rb +12 -0
- data/examples/text/dfont.rb +48 -0
- data/examples/text/family_based_styling.rb +24 -0
- data/examples/text/font_calculations.rb +91 -0
- data/examples/text/font_size.rb +33 -0
- data/examples/text/hyphenation.rb +45 -0
- data/examples/text/indent_paragraphs.rb +22 -0
- data/examples/text/inline_format.rb +103 -0
- data/examples/text/kerning.rb +30 -0
- data/examples/text/rotated.rb +98 -0
- data/examples/text/shaped_text_box.rb +31 -0
- data/examples/text/simple_text.rb +17 -0
- data/examples/text/simple_text_ttf.rb +17 -0
- data/examples/text/text_box.rb +88 -0
- data/examples/text/text_box_returning_excess.rb +51 -0
- data/examples/text/text_flow.rb +67 -0
- data/lib/prawn.rb +27 -0
- data/lib/prawn/canvas.rb +119 -0
- data/lib/prawn/chunkable.rb +37 -0
- data/lib/prawn/compatibility.rb +51 -0
- data/lib/prawn/core.rb +85 -0
- data/lib/prawn/core/annotations.rb +61 -0
- data/lib/prawn/core/byte_string.rb +9 -0
- data/lib/prawn/core/chunk.rb +36 -0
- data/lib/prawn/core/destinations.rb +90 -0
- data/lib/prawn/core/document_state.rb +78 -0
- data/lib/prawn/core/literal_string.rb +16 -0
- data/lib/prawn/core/name_tree.rb +165 -0
- data/lib/prawn/core/object_store.rb +236 -0
- data/lib/prawn/core/page.rb +179 -0
- data/lib/prawn/core/pdf_object.rb +108 -0
- data/lib/prawn/core/reference.rb +112 -0
- data/lib/prawn/core/text.rb +140 -0
- data/lib/prawn/core/text/formatted/arranger.rb +266 -0
- data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
- data/lib/prawn/core/text/formatted/wrap.rb +112 -0
- data/lib/prawn/core/text/line_wrap.rb +209 -0
- data/lib/prawn/core/text/wrap.rb +80 -0
- data/lib/prawn/document.rb +573 -0
- data/lib/prawn/document/bounding_box.rb +425 -0
- data/lib/prawn/document/graphics_state.rb +48 -0
- data/lib/prawn/document/internals.rb +170 -0
- data/lib/prawn/document/page_geometry.rb +136 -0
- data/lib/prawn/document/snapshot.rb +87 -0
- data/lib/prawn/document_builder.rb +51 -0
- data/lib/prawn/document_builder/command.rb +38 -0
- data/lib/prawn/document_builder/constructs.rb +2 -0
- data/lib/prawn/document_builder/constructs/flowing_text_construct.rb +18 -0
- data/lib/prawn/document_builder/constructs/path_construct.rb +9 -0
- data/lib/prawn/document_builder/layout.rb +25 -0
- data/lib/prawn/document_builder/modifications.rb +2 -0
- data/lib/prawn/document_builder/modifications/layout_modification.rb +9 -0
- data/lib/prawn/document_builder/modifications/path_modification.rb +9 -0
- data/lib/prawn/encoding.rb +121 -0
- data/lib/prawn/errors.rb +94 -0
- data/lib/prawn/font.rb +341 -0
- data/lib/prawn/font/afm.rb +225 -0
- data/lib/prawn/font/dfont.rb +42 -0
- data/lib/prawn/font/ttf.rb +350 -0
- data/lib/prawn/graphics.rb +325 -0
- data/lib/prawn/graphics/cap_style.rb +38 -0
- data/lib/prawn/graphics/color.rb +205 -0
- data/lib/prawn/graphics/dash.rb +71 -0
- data/lib/prawn/graphics/join_style.rb +38 -0
- data/lib/prawn/graphics/transformation.rb +156 -0
- data/lib/prawn/graphics/transparency.rb +99 -0
- data/lib/prawn/images.rb +348 -0
- data/lib/prawn/images/jpg.rb +46 -0
- data/lib/prawn/images/png.rb +226 -0
- data/lib/prawn/measurement_extensions.rb +46 -0
- data/lib/prawn/measurements.rb +71 -0
- data/lib/prawn/outline.rb +278 -0
- data/lib/prawn/repeater.rb +129 -0
- data/lib/prawn/security.rb +262 -0
- data/lib/prawn/security/arcfour.rb +51 -0
- data/lib/prawn/stamp.rb +126 -0
- data/lib/prawn/table.rb +421 -0
- data/lib/prawn/table/accessors.rb +180 -0
- data/lib/prawn/table/cell.rb +350 -0
- data/lib/prawn/table/cell/in_table.rb +27 -0
- data/lib/prawn/table/cell/subtable.rb +65 -0
- data/lib/prawn/table/cell/text.rb +125 -0
- data/lib/prawn/text.rb +449 -0
- data/lib/prawn/text/box.rb +392 -0
- data/lib/prawn/text/formatted.rb +4 -0
- data/lib/prawn/text/formatted/box.rb +228 -0
- data/lib/prawn/text/formatted/fragment.rb +181 -0
- data/lib/prawn/text/formatted/parser.rb +213 -0
- data/spec/annotations_spec.rb +90 -0
- data/spec/bounding_box_spec.rb +190 -0
- data/spec/cell_spec.rb +348 -0
- data/spec/destinations_spec.rb +15 -0
- data/spec/document_spec.rb +473 -0
- data/spec/font_spec.rb +324 -0
- data/spec/formatted_text_arranger_spec.rb +426 -0
- data/spec/formatted_text_box_spec.rb +756 -0
- data/spec/formatted_text_fragment_spec.rb +211 -0
- data/spec/graphics_spec.rb +446 -0
- data/spec/images_spec.rb +96 -0
- data/spec/inline_formatted_text_parser_spec.rb +502 -0
- data/spec/jpg_spec.rb +25 -0
- data/spec/line_wrap_spec.rb +341 -0
- data/spec/measurement_units_spec.rb +23 -0
- data/spec/name_tree_spec.rb +112 -0
- data/spec/object_store_spec.rb +160 -0
- data/spec/outline_spec.rb +269 -0
- data/spec/pdf_object_spec.rb +170 -0
- data/spec/png_spec.rb +237 -0
- data/spec/reference_spec.rb +82 -0
- data/spec/repeater_spec.rb +96 -0
- data/spec/security_spec.rb +120 -0
- data/spec/snapshot_spec.rb +138 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/stamp_spec.rb +108 -0
- data/spec/stroke_styles_spec.rb +163 -0
- data/spec/table_spec.rb +598 -0
- data/spec/template_spec.rb +158 -0
- data/spec/text_at_spec.rb +119 -0
- data/spec/text_box_spec.rb +742 -0
- data/spec/text_spacing_spec.rb +75 -0
- data/spec/text_spec.rb +333 -0
- data/spec/text_with_inline_formatting_spec.rb +193 -0
- data/spec/transparency_spec.rb +89 -0
- metadata +331 -0
|
@@ -0,0 +1,138 @@
|
|
|
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
|
+
# Because the Pages object, when restored, points to the snapshotted pages
|
|
68
|
+
# by identifier, we have to restore the snapshot into the same page objects,
|
|
69
|
+
# or else old pages will appear in the post-rollback document.
|
|
70
|
+
it "should restore the pages into the same objects" do
|
|
71
|
+
Prawn::Document.new do
|
|
72
|
+
old_page_object_id = state.page.dictionary.identifier
|
|
73
|
+
old_page_content_id = state.page.content.identifier
|
|
74
|
+
|
|
75
|
+
transaction do
|
|
76
|
+
start_new_page
|
|
77
|
+
rollback
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
state.page.dictionary.identifier.should == old_page_object_id
|
|
81
|
+
state.page.content.identifier.should == old_page_content_id
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "page object should refer to the page_content object after restore" do
|
|
87
|
+
|
|
88
|
+
Prawn::Document.new do
|
|
89
|
+
transaction do
|
|
90
|
+
start_new_page
|
|
91
|
+
rollback
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# should be the exact same object, not a clone
|
|
95
|
+
state.page.dictionary.data[:Contents].should == state.page.content
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe "with a stamp dictionary present" do
|
|
101
|
+
|
|
102
|
+
it "should properly commit if no error is raised" do
|
|
103
|
+
pdf = Prawn::Document.new do
|
|
104
|
+
create_stamp("test_stamp") { draw_text "This is shown", :at => [0,0] }
|
|
105
|
+
transaction do
|
|
106
|
+
stamp("test_stamp")
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
pdf.render.should =~ /\/Stamp1 Do/
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "should properly rollback when #rollback is called" do
|
|
113
|
+
pdf = Prawn::Document.new do
|
|
114
|
+
create_stamp("test_stamp") { draw_text "This is not shown", :at => [0,0] }
|
|
115
|
+
|
|
116
|
+
transaction do
|
|
117
|
+
stamp("test_stamp")
|
|
118
|
+
rollback
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
pdf.render.should.not =~ /\/Stamp1 Do/
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should restore page_number on rollback" do
|
|
127
|
+
Prawn::Document.new do
|
|
128
|
+
transaction do
|
|
129
|
+
5.times { start_new_page }
|
|
130
|
+
rollback
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
page_number.should == 1
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
puts "Prawn specs: Running on Ruby Version: #{RUBY_VERSION}"
|
|
4
|
+
|
|
5
|
+
require "rubygems"
|
|
6
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
|
7
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'vendor',
|
|
8
|
+
'pdf-inspector','lib')
|
|
9
|
+
require "prawn"
|
|
10
|
+
|
|
11
|
+
Prawn.debug = true
|
|
12
|
+
|
|
13
|
+
ruby_19 do
|
|
14
|
+
gem "test-unit", "=1.2.3"
|
|
15
|
+
end
|
|
16
|
+
require "test/spec"
|
|
17
|
+
require "mocha"
|
|
18
|
+
|
|
19
|
+
gem 'pdf-reader', ">=0.8"
|
|
20
|
+
require "pdf/reader"
|
|
21
|
+
require "pdf/inspector"
|
|
22
|
+
|
|
23
|
+
def create_pdf(klass=Prawn::Document)
|
|
24
|
+
@pdf = klass.new(:margin => 0)
|
|
25
|
+
end
|
|
26
|
+
|
data/spec/stamp_spec.rb
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "create_stamp before any page is added" do
|
|
4
|
+
it "should work with the font class" do
|
|
5
|
+
@pdf = Prawn::Document.new(:skip_page_creation => true)
|
|
6
|
+
lambda {
|
|
7
|
+
@pdf.create_stamp("my_stamp") do
|
|
8
|
+
@pdf.font.height
|
|
9
|
+
end
|
|
10
|
+
}.should.not.raise(Prawn::Errors::NotOnPage)
|
|
11
|
+
end
|
|
12
|
+
it "should work with setting color" do
|
|
13
|
+
@pdf = Prawn::Document.new(:skip_page_creation => true)
|
|
14
|
+
lambda {
|
|
15
|
+
@pdf.create_stamp("my_stamp") do
|
|
16
|
+
@pdf.fill_color = 'ff0000'
|
|
17
|
+
end
|
|
18
|
+
}.should.not.raise(Prawn::Errors::NotOnPage)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#stamp_at" do
|
|
23
|
+
it "should work" do
|
|
24
|
+
create_pdf
|
|
25
|
+
@pdf.create_stamp("MyStamp")
|
|
26
|
+
@pdf.stamp_at("MyStamp", [100, 200])
|
|
27
|
+
# I had modified PDF::Inspector::XObject to receive the
|
|
28
|
+
# invoke_xobject message and count the number of times it was
|
|
29
|
+
# called, but it was only called once, so I reverted checking the
|
|
30
|
+
# output with a regular expression
|
|
31
|
+
@pdf.render.should =~ /\/Stamp1 Do.*?/m
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "Document with a stamp" do
|
|
36
|
+
it "should raise NameTaken error when attempt to create stamp "+
|
|
37
|
+
"with same name as an existing stamp" do
|
|
38
|
+
create_pdf
|
|
39
|
+
@pdf.create_stamp("MyStamp")
|
|
40
|
+
lambda {
|
|
41
|
+
@pdf.create_stamp("MyStamp")
|
|
42
|
+
}.should.raise(Prawn::Errors::NameTaken)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should raise InvalidName error when attempt to create "+
|
|
46
|
+
"stamp with a blank name" do
|
|
47
|
+
create_pdf
|
|
48
|
+
lambda {
|
|
49
|
+
@pdf.create_stamp("")
|
|
50
|
+
}.should.raise(Prawn::Errors::InvalidName)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "a new XObject should be defined for each stamp created" do
|
|
54
|
+
create_pdf
|
|
55
|
+
@pdf.create_stamp("MyStamp")
|
|
56
|
+
@pdf.create_stamp("AnotherStamp")
|
|
57
|
+
@pdf.stamp("MyStamp")
|
|
58
|
+
@pdf.stamp("AnotherStamp")
|
|
59
|
+
|
|
60
|
+
inspector = PDF::Inspector::XObject.analyze(@pdf.render)
|
|
61
|
+
xobjects = inspector.page_xobjects.last
|
|
62
|
+
xobjects.length.should == 2
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "calling stamp with a name that does not match an existing stamp "+
|
|
66
|
+
"should raise UndefinedObjectName" do
|
|
67
|
+
create_pdf
|
|
68
|
+
@pdf.create_stamp("MyStamp")
|
|
69
|
+
lambda {
|
|
70
|
+
@pdf.stamp("OtherStamp")
|
|
71
|
+
}.should.raise(Prawn::Errors::UndefinedObjectName)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "stamp should be drawn into the document each time stamp is called" do
|
|
75
|
+
create_pdf
|
|
76
|
+
@pdf.create_stamp("MyStamp")
|
|
77
|
+
@pdf.stamp("MyStamp")
|
|
78
|
+
@pdf.stamp("MyStamp")
|
|
79
|
+
@pdf.stamp("MyStamp")
|
|
80
|
+
# I had modified PDF::Inspector::XObject to receive the
|
|
81
|
+
# invoke_xobject message and count the number of times it was
|
|
82
|
+
# called, but it was only called once, so I reverted checking the
|
|
83
|
+
# output with a regular expression
|
|
84
|
+
@pdf.render.should =~ /(\/Stamp1 Do.*?){3}/m
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "resources added during stamp creation should be added to the "+
|
|
88
|
+
"stamp XObject, not the page" do
|
|
89
|
+
create_pdf
|
|
90
|
+
@pdf.create_stamp("MyStamp") do
|
|
91
|
+
@pdf.transparent(0.5) { @pdf.circle_at([100, 100], :radius => 10)}
|
|
92
|
+
end
|
|
93
|
+
@pdf.stamp("MyStamp")
|
|
94
|
+
|
|
95
|
+
# Inspector::XObject does not give information about resources, so
|
|
96
|
+
# resorting to string matching
|
|
97
|
+
|
|
98
|
+
output = @pdf.render
|
|
99
|
+
objects = output.split("endobj")
|
|
100
|
+
objects.each do |object|
|
|
101
|
+
if object =~ /\/Type \/Page$/
|
|
102
|
+
object.should.not =~ /\/ExtGState/
|
|
103
|
+
elsif object =~ /\/Type \/XObject$/
|
|
104
|
+
object.should =~ /\/ExtGState/
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
4
|
+
|
|
5
|
+
describe "When stroking with default settings" do
|
|
6
|
+
before(:each) { create_pdf }
|
|
7
|
+
it "cap_style should be :butt" do
|
|
8
|
+
@pdf.cap_style.should == :butt
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "join_style should be :miter" do
|
|
12
|
+
@pdf.join_style.should == :miter
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "dashed? should be false" do
|
|
16
|
+
@pdf.should.not.be.dashed
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "Cap styles" do
|
|
21
|
+
before(:each) { create_pdf }
|
|
22
|
+
|
|
23
|
+
it "should be able to use assignment operator" do
|
|
24
|
+
@pdf.cap_style = :round
|
|
25
|
+
@pdf.cap_style.should == :round
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#cap_style(:butt)" do
|
|
29
|
+
it "rendered PDF should include butt style cap" do
|
|
30
|
+
@pdf.cap_style(:butt)
|
|
31
|
+
cap_style = PDF::Inspector::Graphics::CapStyle.analyze(@pdf.render).cap_style
|
|
32
|
+
cap_style.should == 0
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#cap_style(:round)" do
|
|
37
|
+
it "rendered PDF should include round style cap" do
|
|
38
|
+
@pdf.cap_style(:round)
|
|
39
|
+
cap_style = PDF::Inspector::Graphics::CapStyle.analyze(@pdf.render).cap_style
|
|
40
|
+
cap_style.should == 1
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#cap_style(:projecting_square)" do
|
|
45
|
+
it "rendered PDF should include projecting_square style cap" do
|
|
46
|
+
@pdf.cap_style(:projecting_square)
|
|
47
|
+
cap_style = PDF::Inspector::Graphics::CapStyle.analyze(@pdf.render).cap_style
|
|
48
|
+
cap_style.should == 2
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should carry the current cap style settings over to new pages" do
|
|
53
|
+
@pdf.cap_style(:round)
|
|
54
|
+
@pdf.start_new_page
|
|
55
|
+
cap_styles = PDF::Inspector::Graphics::CapStyle.analyze(@pdf.render)
|
|
56
|
+
cap_styles.cap_style_count.should == 2
|
|
57
|
+
cap_styles.cap_style.should == 1
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "Join styles" do
|
|
62
|
+
before(:each) { create_pdf }
|
|
63
|
+
|
|
64
|
+
it "should be able to use assignment operator" do
|
|
65
|
+
@pdf.join_style = :round
|
|
66
|
+
@pdf.join_style.should == :round
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "#join_style(:miter)" do
|
|
70
|
+
it "rendered PDF should include miter style join" do
|
|
71
|
+
@pdf.join_style(:miter)
|
|
72
|
+
join_style = PDF::Inspector::Graphics::JoinStyle.analyze(@pdf.render).join_style
|
|
73
|
+
join_style.should == 0
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "#join_style(:round)" do
|
|
78
|
+
it "rendered PDF should include round style join" do
|
|
79
|
+
@pdf.join_style(:round)
|
|
80
|
+
join_style = PDF::Inspector::Graphics::JoinStyle.analyze(@pdf.render).join_style
|
|
81
|
+
join_style.should == 1
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe "#join_style(:bevel)" do
|
|
86
|
+
it "rendered PDF should include bevel style join" do
|
|
87
|
+
@pdf.join_style(:bevel)
|
|
88
|
+
join_style = PDF::Inspector::Graphics::JoinStyle.analyze(@pdf.render).join_style
|
|
89
|
+
join_style.should == 2
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should carry the current join style settings over to new pages" do
|
|
94
|
+
@pdf.join_style(:round)
|
|
95
|
+
@pdf.start_new_page
|
|
96
|
+
join_styles = PDF::Inspector::Graphics::JoinStyle.analyze(@pdf.render)
|
|
97
|
+
join_styles.join_style_count.should == 2
|
|
98
|
+
join_styles.join_style.should == 1
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe "Dashes" do
|
|
103
|
+
before(:each) { create_pdf }
|
|
104
|
+
|
|
105
|
+
it "should be able to use assignment operator" do
|
|
106
|
+
@pdf.dash = 2
|
|
107
|
+
@pdf.should.be.dashed
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
describe "setting a dash" do
|
|
111
|
+
it "dashed? should be true" do
|
|
112
|
+
@pdf.dash(2)
|
|
113
|
+
@pdf.should.be.dashed
|
|
114
|
+
end
|
|
115
|
+
it "rendered PDF should include a stroked dash" do
|
|
116
|
+
@pdf.dash(2)
|
|
117
|
+
dashes = PDF::Inspector::Graphics::Dash.analyze(@pdf.render)
|
|
118
|
+
dashes.stroke_dash.should == [[2, 2], 0]
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe "setting a dash by passing a single argument" do
|
|
123
|
+
it "space between dashes should be the same length as the dash in the rendered PDF" do
|
|
124
|
+
@pdf.dash(2)
|
|
125
|
+
dashes = PDF::Inspector::Graphics::Dash.analyze(@pdf.render)
|
|
126
|
+
dashes.stroke_dash.should == [[2, 2], 0]
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe "with a space option that differs from the first argument" do
|
|
131
|
+
it "space between dashes in the rendered PDF should be different length than the length of the dash" do
|
|
132
|
+
@pdf.dash(2, :space => 3)
|
|
133
|
+
dashes = PDF::Inspector::Graphics::Dash.analyze(@pdf.render)
|
|
134
|
+
dashes.stroke_dash.should == [[2, 3], 0]
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe "with a non-zero phase option" do
|
|
139
|
+
it "rendered PDF should include a non-zero phase" do
|
|
140
|
+
@pdf.dash(2, :phase => 1)
|
|
141
|
+
dashes = PDF::Inspector::Graphics::Dash.analyze(@pdf.render)
|
|
142
|
+
dashes.stroke_dash.should == [[2, 2], 1]
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
describe "clearing stroke dash" do
|
|
147
|
+
it "should restore solid line" do
|
|
148
|
+
@pdf.dash(2)
|
|
149
|
+
@pdf.undash
|
|
150
|
+
dashes = PDF::Inspector::Graphics::Dash.analyze(@pdf.render)
|
|
151
|
+
dashes.stroke_dash.should == [[], 0]
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should carry the current dash settings over to new pages" do
|
|
156
|
+
@pdf.dash(2)
|
|
157
|
+
@pdf.start_new_page
|
|
158
|
+
dashes = PDF::Inspector::Graphics::Dash.analyze(@pdf.render)
|
|
159
|
+
dashes.stroke_dash_count.should == 2
|
|
160
|
+
dashes.stroke_dash.should == [[2, 2], 0]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
end
|
data/spec/table_spec.rb
ADDED
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
|
|
4
|
+
require 'set'
|
|
5
|
+
|
|
6
|
+
describe "Prawn::Table" do
|
|
7
|
+
|
|
8
|
+
describe "converting data to Cell objects" do
|
|
9
|
+
before(:each) do
|
|
10
|
+
@pdf = Prawn::Document.new
|
|
11
|
+
@table = @pdf.table([%w[R0C0 R0C1], %w[R1C0 R1C1]])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should return a Prawn::Table" do
|
|
15
|
+
@table.should.be.an.instance_of Prawn::Table
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should flatten the data into the @cells array in row-major order" do
|
|
19
|
+
@table.cells.map { |c| c.content }.should == %w[R0C0 R0C1 R1C0 R1C1]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should add row and column numbers to each cell" do
|
|
23
|
+
c = @table.cells.to_a.first
|
|
24
|
+
c.row.should == 0
|
|
25
|
+
c.column.should == 0
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should allow empty fields" do
|
|
29
|
+
lambda {
|
|
30
|
+
data = [["foo","bar"],["baz",""]]
|
|
31
|
+
@pdf.table(data)
|
|
32
|
+
}.should.not.raise
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# TODO: pending colspan
|
|
36
|
+
xit "should accurately count columns from data" do
|
|
37
|
+
# First data row may contain colspan which would hide true column count
|
|
38
|
+
data = [["Name:",{:text => "Some very long name", :colspan => 5}]]
|
|
39
|
+
pdf = Prawn::Document.new
|
|
40
|
+
table = Prawn::Table.new data, pdf
|
|
41
|
+
table.column_widths.length.should == 6
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "#initialize" do
|
|
46
|
+
before(:each) do
|
|
47
|
+
@pdf = Prawn::Document.new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should instance_eval a 0-arg block" do
|
|
51
|
+
initializer = mock()
|
|
52
|
+
initializer.expects(:kick).once
|
|
53
|
+
|
|
54
|
+
@pdf.table([["a"]]){
|
|
55
|
+
self.should.be.an.instance_of(Prawn::Table); initializer.kick }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should call a 1-arg block with the document as the argument" do
|
|
59
|
+
initializer = mock()
|
|
60
|
+
initializer.expects(:kick).once
|
|
61
|
+
|
|
62
|
+
@pdf.table([["a"]]){ |doc|
|
|
63
|
+
doc.should.be.an.instance_of(Prawn::Table); initializer.kick }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should proxy cell methods to #cells" do
|
|
67
|
+
table = @pdf.table([["a"]], :cell_style => { :padding => 11 })
|
|
68
|
+
table.cells[0, 0].padding.should == [11, 11, 11, 11]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should set row and column length" do
|
|
72
|
+
table = @pdf.table([["a", "b", "c"], ["d", "e", "f"]])
|
|
73
|
+
table.row_length.should == 2
|
|
74
|
+
table.column_length.should == 3
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should generate a text cell based on a String" do
|
|
78
|
+
t = @pdf.table([["foo"]])
|
|
79
|
+
t.cells[0,0].should.be.a.kind_of(Prawn::Table::Cell::Text)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should pass through a text cell" do
|
|
83
|
+
c = Prawn::Table::Cell::Text.new(@pdf, [0,0], :content => "foo")
|
|
84
|
+
t = @pdf.table([[c]])
|
|
85
|
+
t.cells[0,0].should == c
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "cell accessors" do
|
|
90
|
+
before(:each) do
|
|
91
|
+
@pdf = Prawn::Document.new
|
|
92
|
+
@table = @pdf.table([%w[R0C0 R0C1], %w[R1C0 R1C1]])
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "should select rows by number or range" do
|
|
96
|
+
Set.new(@table.row(0).map { |c| c.content }).should ==
|
|
97
|
+
Set.new(%w[R0C0 R0C1])
|
|
98
|
+
Set.new(@table.rows(0..1).map { |c| c.content }).should ==
|
|
99
|
+
Set.new(%w[R0C0 R0C1 R1C0 R1C1])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should select columns by number or range" do
|
|
103
|
+
Set.new(@table.column(0).map { |c| c.content }).should ==
|
|
104
|
+
Set.new(%w[R0C0 R1C0])
|
|
105
|
+
Set.new(@table.columns(0..1).map { |c| c.content }).should ==
|
|
106
|
+
Set.new(%w[R0C0 R0C1 R1C0 R1C1])
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "should allow rows and columns to be combined" do
|
|
110
|
+
@table.row(0).column(1).map { |c| c.content }.should == ["R0C1"]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "should accept a select block, returning a cell proxy" do
|
|
114
|
+
@table.cells.select { |c| c.content =~ /R0/ }.column(1).map{ |c|
|
|
115
|
+
c.content }.should == ["R0C1"]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should accept the [] method, returning a Cell or nil" do
|
|
119
|
+
@table.cells[0, 0].content.should == "R0C0"
|
|
120
|
+
@table.cells[12, 12].should.be.nil
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should proxy unknown methods to the cells" do
|
|
124
|
+
@table.cells.height = 200
|
|
125
|
+
@table.row(1).height = 100
|
|
126
|
+
|
|
127
|
+
@table.cells[0, 0].height.should == 200
|
|
128
|
+
@table.cells[1, 0].height.should == 100
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should accept the style method, proxying its calls to the cells" do
|
|
132
|
+
@table.cells.style(:height => 200, :width => 200)
|
|
133
|
+
@table.column(0).style(:width => 100)
|
|
134
|
+
|
|
135
|
+
@table.cells[0, 1].width.should == 200
|
|
136
|
+
@table.cells[1, 0].height.should == 200
|
|
137
|
+
@table.cells[1, 0].width.should == 100
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "should return the width of selected columns for #width" do
|
|
141
|
+
c0_width = @table.column(0).map{ |c| c.width }.max
|
|
142
|
+
c1_width = @table.column(1).map{ |c| c.width }.max
|
|
143
|
+
|
|
144
|
+
@table.column(0).width.should == c0_width
|
|
145
|
+
@table.column(1).width.should == c1_width
|
|
146
|
+
|
|
147
|
+
@table.columns(0..1).width.should == c0_width + c1_width
|
|
148
|
+
@table.cells.width.should == c0_width + c1_width
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "should return the height of selected rows for #height" do
|
|
152
|
+
r0_height = @table.row(0).map{ |c| c.height }.max
|
|
153
|
+
r1_height = @table.row(1).map{ |c| c.height }.max
|
|
154
|
+
|
|
155
|
+
@table.row(0).height.should == r0_height
|
|
156
|
+
@table.row(1).height.should == r1_height
|
|
157
|
+
|
|
158
|
+
@table.rows(0..1).height.should == r0_height + r1_height
|
|
159
|
+
@table.cells.height.should == r0_height + r1_height
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
describe "layout" do
|
|
164
|
+
before(:each) do
|
|
165
|
+
@pdf = Prawn::Document.new
|
|
166
|
+
@long_text = "The quick brown fox jumped over the lazy dogs. " * 5
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe "width" do
|
|
170
|
+
it "should raise an error if the given width is outside of range" do
|
|
171
|
+
lambda do
|
|
172
|
+
@pdf.table([["foo"]], :width => 1)
|
|
173
|
+
end.should.raise(Prawn::Errors::CannotFit)
|
|
174
|
+
|
|
175
|
+
lambda do
|
|
176
|
+
@pdf.table([[@long_text]], :width => @pdf.bounds.width + 100)
|
|
177
|
+
end.should.raise(Prawn::Errors::CannotFit)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "should accept the natural width for small tables" do
|
|
181
|
+
pad = 10 # default padding
|
|
182
|
+
@table = @pdf.table([["a"]])
|
|
183
|
+
@table.width.should == @table.cells[0, 0].natural_content_width + pad
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "width should equal sum(column_widths)" do
|
|
187
|
+
table = Prawn::Table.new([%w[ a b c ], %w[d e f]], @pdf) do
|
|
188
|
+
column(0).width = 50
|
|
189
|
+
column(1).width = 100
|
|
190
|
+
column(2).width = 150
|
|
191
|
+
end
|
|
192
|
+
table.width.should == 300
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "should calculate unspecified column widths as "+
|
|
196
|
+
"(max(string_width) + 2*horizontal_padding)" do
|
|
197
|
+
hpad, fs = 3, 12
|
|
198
|
+
columns = 2
|
|
199
|
+
table = Prawn::Table.new( [%w[ foo b ], %w[d foobar]], @pdf,
|
|
200
|
+
:cell_style => { :padding => hpad, :size => fs } )
|
|
201
|
+
|
|
202
|
+
col0_width = @pdf.width_of("foo", :size => fs)
|
|
203
|
+
col1_width = @pdf.width_of("foobar", :size => fs)
|
|
204
|
+
|
|
205
|
+
table.width.should == col0_width + col1_width + 2*columns*hpad
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "should allow mixing autocalculated and preset"+
|
|
209
|
+
"column widths within a single table" do
|
|
210
|
+
hpad, fs = 10, 6
|
|
211
|
+
stretchy_columns = 2
|
|
212
|
+
|
|
213
|
+
col0_width = 50
|
|
214
|
+
col1_width = @pdf.width_of("foo", :size => fs)
|
|
215
|
+
col2_width = @pdf.width_of("foobar", :size => fs)
|
|
216
|
+
col3_width = 150
|
|
217
|
+
|
|
218
|
+
table = Prawn::Table.new( [%w[snake foo b apple],
|
|
219
|
+
%w[kitten d foobar banana]], @pdf,
|
|
220
|
+
:cell_style => { :padding => hpad, :size => fs }) do
|
|
221
|
+
|
|
222
|
+
column(0).width = col0_width
|
|
223
|
+
column(3).width = col3_width
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
table.width.should == col1_width + col2_width +
|
|
227
|
+
2*stretchy_columns*hpad +
|
|
228
|
+
col0_width + col3_width
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "should not exceed the maximum width of the margin_box" do
|
|
232
|
+
expected_width = @pdf.margin_box.width
|
|
233
|
+
data = [
|
|
234
|
+
['This is a column with a lot of text that should comfortably exceed '+
|
|
235
|
+
'the width of a normal document margin_box width', 'Some more text',
|
|
236
|
+
'and then some more', 'Just a bit more to be extra sure']
|
|
237
|
+
]
|
|
238
|
+
table = Prawn::Table.new(data, @pdf)
|
|
239
|
+
|
|
240
|
+
table.width.should == expected_width
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "should not exceed the maximum width of the margin_box even with" +
|
|
244
|
+
"manual widths specified" do
|
|
245
|
+
expected_width = @pdf.margin_box.width
|
|
246
|
+
data = [
|
|
247
|
+
['This is a column with a lot of text that should comfortably exceed '+
|
|
248
|
+
'the width of a normal document margin_box width', 'Some more text',
|
|
249
|
+
'and then some more', 'Just a bit more to be extra sure']
|
|
250
|
+
]
|
|
251
|
+
table = Prawn::Table.new(data, @pdf) { column(1).width = 100 }
|
|
252
|
+
|
|
253
|
+
table.width.should == expected_width
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it "scales down only the non-preset column widths when the natural width" +
|
|
257
|
+
"exceeds the maximum width of the margin_box" do
|
|
258
|
+
expected_width = @pdf.margin_box.width
|
|
259
|
+
data = [
|
|
260
|
+
['This is a column with a lot of text that should comfortably exceed '+
|
|
261
|
+
'the width of a normal document margin_box width', 'Some more text',
|
|
262
|
+
'and then some more', 'Just a bit more to be extra sure']
|
|
263
|
+
]
|
|
264
|
+
table = Prawn::Table.new(data, @pdf) { column(1).width = 100; column(3).width = 50 }
|
|
265
|
+
|
|
266
|
+
table.width.should == expected_width
|
|
267
|
+
table.column_widths[1].should == 100
|
|
268
|
+
table.column_widths[3].should == 50
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "should allow width to be reset even after it has been calculated" do
|
|
272
|
+
@table = @pdf.table([[@long_text]])
|
|
273
|
+
@table.width
|
|
274
|
+
@table.width = 100
|
|
275
|
+
@table.width.should == 100
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it "should shrink columns evenly when two equal columns compete" do
|
|
279
|
+
@table = @pdf.table([["foo", @long_text], [@long_text, "foo"]])
|
|
280
|
+
@table.cells[0, 0].width.should == @table.cells[0, 1].width
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it "should grow columns evenly when equal deficient columns compete" do
|
|
284
|
+
@table = @pdf.table([["foo", "foobar"], ["foobar", "foo"]], :width => 500)
|
|
285
|
+
@table.cells[0, 0].width.should == @table.cells[0, 1].width
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it "should respect manual widths" do
|
|
289
|
+
@table = @pdf.table([%w[foo bar baz], %w[baz bar foo]], :width => 500) do
|
|
290
|
+
column(1).width = 60
|
|
291
|
+
end
|
|
292
|
+
@table.column(1).width.should == 60
|
|
293
|
+
@table.column(0).width.should == @table.column(2).width
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it "should be the width of the :width parameter" do
|
|
297
|
+
expected_width = 300
|
|
298
|
+
table = Prawn::Table.new( [%w[snake foo b apple],
|
|
299
|
+
%w[kitten d foobar banana]], @pdf,
|
|
300
|
+
:width => expected_width)
|
|
301
|
+
|
|
302
|
+
table.width.should == expected_width
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it "should not exceed the :width option" do
|
|
306
|
+
expected_width = 400
|
|
307
|
+
data = [
|
|
308
|
+
['This is a column with a lot of text that should comfortably exceed '+
|
|
309
|
+
'the width of a normal document margin_box width', 'Some more text',
|
|
310
|
+
'and then some more', 'Just a bit more to be extra sure']
|
|
311
|
+
]
|
|
312
|
+
table = Prawn::Table.new(data, @pdf, :width => expected_width)
|
|
313
|
+
|
|
314
|
+
table.width.should == expected_width
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "should not exceed the :width option even with manual widths specified" do
|
|
318
|
+
expected_width = 400
|
|
319
|
+
data = [
|
|
320
|
+
['This is a column with a lot of text that should comfortably exceed '+
|
|
321
|
+
'the width of a normal document margin_box width', 'Some more text',
|
|
322
|
+
'and then some more', 'Just a bit more to be extra sure']
|
|
323
|
+
]
|
|
324
|
+
table = Prawn::Table.new(data, @pdf, :width => expected_width) do
|
|
325
|
+
column(1).width = 100
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
table.width.should == expected_width
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# TODO: pending colspan
|
|
332
|
+
xit "should calculate unspecified column widths even " +
|
|
333
|
+
"with colspan cells declared" do
|
|
334
|
+
pdf = Prawn::Document.new
|
|
335
|
+
hpad, fs = 3, 5
|
|
336
|
+
columns = 3
|
|
337
|
+
|
|
338
|
+
data = [ [ { :text => 'foo', :colspan => 2 }, "foobar" ],
|
|
339
|
+
[ "foo", "foo", "foo" ] ]
|
|
340
|
+
table = Prawn::Table.new( data, pdf,
|
|
341
|
+
:horizontal_padding => hpad,
|
|
342
|
+
:font_size => fs )
|
|
343
|
+
|
|
344
|
+
col0_width = pdf.width_of("foo", :size => fs) # cell 1, 0
|
|
345
|
+
col1_width = pdf.width_of("foo", :size => fs) # cell 1, 1
|
|
346
|
+
col2_width = pdf.width_of("foobar", :size => fs) # cell 0, 1 (at col 2)
|
|
347
|
+
|
|
348
|
+
table.width.should == col0_width.ceil + col1_width.ceil +
|
|
349
|
+
col2_width.ceil + 2*columns*hpad
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
describe "height" do
|
|
354
|
+
it "should set all cells in a row to the same height" do
|
|
355
|
+
@table = @pdf.table([["foo", @long_text]])
|
|
356
|
+
@table.cells[0, 0].height.should == @table.cells[0, 1].height
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "should move y-position to the bottom of the table after drawing" do
|
|
360
|
+
old_y = @pdf.y
|
|
361
|
+
table = @pdf.table([["foo"]])
|
|
362
|
+
@pdf.y.should == old_y - table.height
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
it "should not wrap unnecessarily" do
|
|
366
|
+
# Test for FP errors and glitches
|
|
367
|
+
t = @pdf.table([["Bender Bending Rodriguez"]])
|
|
368
|
+
h = @pdf.height_of("one line")
|
|
369
|
+
(t.height - 10).should.be < h*1.5
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "should have a height of n rows" do
|
|
373
|
+
data = [["foo"],["bar"],["baaaz"]]
|
|
374
|
+
|
|
375
|
+
vpad = 4
|
|
376
|
+
origin = @pdf.y
|
|
377
|
+
@pdf.table data, :cell_style => { :padding => vpad }
|
|
378
|
+
|
|
379
|
+
table_height = origin - @pdf.y
|
|
380
|
+
font_height = @pdf.font.height
|
|
381
|
+
|
|
382
|
+
num_rows = data.length
|
|
383
|
+
table_height.should.be.close(
|
|
384
|
+
num_rows*font_height + 2*vpad*num_rows, 0.001 )
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
describe "Multi-page tables" do
|
|
392
|
+
it "should flow to the next page when hitting the bottom of the bounds" do
|
|
393
|
+
Prawn::Document.new { table([["foo"]] * 30) }.page_count.should == 1
|
|
394
|
+
Prawn::Document.new { table([["foo"]] * 31) }.page_count.should == 2
|
|
395
|
+
Prawn::Document.new { table([["foo"]] * 31); table([["foo"]] * 31) }.
|
|
396
|
+
page_count.should == 3
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it "should respect the containing bounds" do
|
|
400
|
+
Prawn::Document.new do
|
|
401
|
+
bounding_box([0, cursor], :width => bounds.width, :height => 72) do
|
|
402
|
+
table([["foo"]] * 4)
|
|
403
|
+
end
|
|
404
|
+
end.page_count.should == 2
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
describe "#style" do
|
|
409
|
+
it "should send #style to its first argument, passing the style hash and" +
|
|
410
|
+
" block" do
|
|
411
|
+
|
|
412
|
+
stylable = stub()
|
|
413
|
+
stylable.expects(:style).with(:foo => :bar).once.yields
|
|
414
|
+
|
|
415
|
+
block = stub()
|
|
416
|
+
block.expects(:kick).once
|
|
417
|
+
|
|
418
|
+
Prawn::Document.new do
|
|
419
|
+
table([["x"]]) { style(stylable, :foo => :bar) { block.kick } }
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
it "should default to {} for the hash argument" do
|
|
424
|
+
stylable = stub()
|
|
425
|
+
stylable.expects(:style).with({}).once
|
|
426
|
+
|
|
427
|
+
Prawn::Document.new do
|
|
428
|
+
table([["x"]]) { style(stylable) }
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
describe "row_colors" do
|
|
434
|
+
it "should allow array syntax for :row_colors" do
|
|
435
|
+
data = [["foo"], ["bar"], ["baz"]]
|
|
436
|
+
pdf = Prawn::Document.new
|
|
437
|
+
t = pdf.table(data, :row_colors => ['cccccc', 'ffffff'])
|
|
438
|
+
t.cells.map{|x| x.background_color}.should == %w[cccccc ffffff cccccc]
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "should ignore headers" do
|
|
442
|
+
data = [["header"], ["foo"], ["bar"], ["baz"]]
|
|
443
|
+
pdf = Prawn::Document.new
|
|
444
|
+
t = pdf.table(data, :header => true,
|
|
445
|
+
:row_colors => ['cccccc', 'ffffff']) do
|
|
446
|
+
row(0).background_color = '333333'
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
t.cells.map{|x| x.background_color}.should ==
|
|
450
|
+
%w[333333 cccccc ffffff cccccc]
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
describe "inking" do
|
|
455
|
+
before(:each) do
|
|
456
|
+
@pdf = Prawn::Document.new
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
it "should set the x-position of each cell based on widths" do
|
|
460
|
+
@table = @pdf.table([["foo", "bar", "baz"]])
|
|
461
|
+
|
|
462
|
+
x = 0
|
|
463
|
+
(0..2).each do |col|
|
|
464
|
+
cell = @table.cells[0, col]
|
|
465
|
+
cell.x.should == x
|
|
466
|
+
x += cell.width
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it "should set the y-position of each cell based on heights" do
|
|
471
|
+
y = 0
|
|
472
|
+
@table = @pdf.make_table([["foo"], ["bar"], ["baz"]])
|
|
473
|
+
|
|
474
|
+
(0..2).each do |row|
|
|
475
|
+
cell = @table.cells[row, 0]
|
|
476
|
+
cell.y.should.be.close(y, 0.01)
|
|
477
|
+
y -= cell.height
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
it "should output content cell by cell, row by row" do
|
|
482
|
+
data = [["foo","bar"],["baz","bang"]]
|
|
483
|
+
@pdf = Prawn::Document.new
|
|
484
|
+
@pdf.table(data)
|
|
485
|
+
output = PDF::Inspector::Text.analyze(@pdf.render)
|
|
486
|
+
output.strings.should == data.flatten
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
it "should not cause an error if rendering the very first row causes a " +
|
|
490
|
+
"page break" do
|
|
491
|
+
Prawn::Document.new do
|
|
492
|
+
arr = Array(1..5).collect{|i| ["cell #{i}"] }
|
|
493
|
+
|
|
494
|
+
move_down( y - (bounds.absolute_bottom + 3) )
|
|
495
|
+
|
|
496
|
+
lambda {
|
|
497
|
+
table(arr)
|
|
498
|
+
}.should.not.raise
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
it "should allow multiple inkings of the same table" do
|
|
503
|
+
pdf = Prawn::Document.new
|
|
504
|
+
t = Prawn::Table.new([["foo"]], pdf)
|
|
505
|
+
|
|
506
|
+
pdf.expects(:bounding_box).with{|(x, y), options| y.to_i == 495}.yields
|
|
507
|
+
pdf.expects(:bounding_box).with{|(x, y), options| y.to_i == 395}.yields
|
|
508
|
+
pdf.expects(:draw_text!).with{ |text, options| text == 'foo' }.twice
|
|
509
|
+
|
|
510
|
+
pdf.move_cursor_to(500)
|
|
511
|
+
t.draw
|
|
512
|
+
|
|
513
|
+
pdf.move_cursor_to(400)
|
|
514
|
+
t.draw
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
describe "headers" do
|
|
519
|
+
it "should add headers to output when specified" do
|
|
520
|
+
data = [["a", "b"], ["foo","bar"],["baz","bang"]]
|
|
521
|
+
@pdf = Prawn::Document.new
|
|
522
|
+
@pdf.table(data, :header => true)
|
|
523
|
+
output = PDF::Inspector::Text.analyze(@pdf.render)
|
|
524
|
+
output.strings.should == data.flatten
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
it "should repeat headers across pages" do
|
|
528
|
+
data = [["foo","bar"]]*30
|
|
529
|
+
headers = ["baz","foobar"]
|
|
530
|
+
@pdf = Prawn::Document.new
|
|
531
|
+
@pdf.table([headers] + data, :header => true)
|
|
532
|
+
output = PDF::Inspector::Text.analyze(@pdf.render)
|
|
533
|
+
output.strings.should == headers + data.flatten[0..-3] + headers +
|
|
534
|
+
data.flatten[-2..-1]
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
describe "nested tables" do
|
|
539
|
+
before(:each) do
|
|
540
|
+
@pdf = Prawn::Document.new
|
|
541
|
+
@subtable = Prawn::Table.new([["foo"]], @pdf)
|
|
542
|
+
@table = @pdf.table([[@subtable, "bar"]])
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
it "can be created from an Array" do
|
|
546
|
+
cell = Prawn::Table::Cell.make(@pdf, [["foo"]])
|
|
547
|
+
cell.should.be.an.instance_of(Prawn::Table::Cell::Subtable)
|
|
548
|
+
cell.subtable.should.be.an.instance_of(Prawn::Table)
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
it "defaults its padding to zero" do
|
|
552
|
+
@table.cells[0, 0].padding.should == [0, 0, 0, 0]
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it "has a subtable accessor" do
|
|
556
|
+
@table.cells[0, 0].subtable.should == @subtable
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
it "determines its dimensions from the subtable" do
|
|
560
|
+
@table.cells[0, 0].width.should == @subtable.width
|
|
561
|
+
@table.cells[0, 0].height.should == @subtable.height
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
describe "An invalid table" do
|
|
567
|
+
|
|
568
|
+
before(:each) do
|
|
569
|
+
@pdf = Prawn::Document.new
|
|
570
|
+
@bad_data = ["Single Nested Array"]
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
it "should raise error when invalid table data is given" do
|
|
574
|
+
assert_raises(Prawn::Errors::InvalidTableData) do
|
|
575
|
+
@pdf.table(@bad_data)
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
it "should raise an EmptyTableError with empty table data" do
|
|
580
|
+
lambda {
|
|
581
|
+
data = []
|
|
582
|
+
@pdf = Prawn::Document.new
|
|
583
|
+
@pdf.table(data)
|
|
584
|
+
}.should.raise( Prawn::Errors::EmptyTable )
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
it "should raise an EmptyTableError with nil table data" do
|
|
588
|
+
lambda {
|
|
589
|
+
data = nil
|
|
590
|
+
@pdf = Prawn::Document.new
|
|
591
|
+
@pdf.table(data)
|
|
592
|
+
}.should.raise( Prawn::Errors::EmptyTable )
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
end
|
|
598
|
+
|