prawn 0.11.1 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (353) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +10 -0
  3. data/COPYING +2 -2
  4. data/GPLv2 +340 -0
  5. data/GPLv3 +674 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +1 -1
  8. data/Rakefile +29 -38
  9. data/data/images/16bit.alpha +0 -0
  10. data/data/images/16bit.color +0 -0
  11. data/data/images/dice.alpha +0 -0
  12. data/data/images/dice.color +0 -0
  13. data/data/images/indexed_color.dat +0 -0
  14. data/data/images/indexed_color.png +0 -0
  15. data/data/images/page_white_text.alpha +0 -0
  16. data/data/images/page_white_text.color +0 -0
  17. data/data/pdfs/nested_pages.pdf +13 -13
  18. data/lib/prawn/document/bounding_box.rb +87 -12
  19. data/lib/prawn/document/column_box.rb +57 -28
  20. data/lib/prawn/document/graphics_state.rb +11 -74
  21. data/lib/prawn/document/internals.rb +25 -23
  22. data/lib/prawn/document/snapshot.rb +11 -8
  23. data/lib/prawn/document/span.rb +12 -10
  24. data/lib/prawn/document.rb +250 -194
  25. data/lib/prawn/encoding.rb +9 -10
  26. data/lib/prawn/errors.rb +18 -29
  27. data/lib/prawn/font/afm.rb +52 -41
  28. data/lib/prawn/font/dfont.rb +4 -3
  29. data/lib/prawn/font/ttf.rb +44 -48
  30. data/lib/prawn/font.rb +138 -88
  31. data/lib/prawn/font_metric_cache.rb +47 -0
  32. data/lib/prawn/graphics/cap_style.rb +4 -3
  33. data/lib/prawn/graphics/color.rb +13 -5
  34. data/lib/prawn/graphics/dash.rb +53 -31
  35. data/lib/prawn/graphics/join_style.rb +9 -7
  36. data/lib/prawn/graphics/patterns.rb +138 -0
  37. data/lib/prawn/graphics/transformation.rb +10 -9
  38. data/lib/prawn/graphics/transparency.rb +3 -1
  39. data/lib/prawn/graphics.rb +316 -61
  40. data/lib/prawn/image_handler.rb +36 -0
  41. data/lib/prawn/images/image.rb +49 -0
  42. data/lib/prawn/images/jpg.rb +21 -15
  43. data/lib/prawn/images/png.rb +62 -119
  44. data/lib/prawn/images.rb +89 -108
  45. data/lib/prawn/layout/grid.rb +66 -54
  46. data/lib/prawn/layout.rb +10 -15
  47. data/lib/prawn/measurement_extensions.rb +10 -6
  48. data/lib/prawn/measurements.rb +27 -21
  49. data/lib/prawn/outline.rb +6 -308
  50. data/lib/prawn/repeater.rb +11 -9
  51. data/lib/prawn/security/arcfour.rb +1 -0
  52. data/lib/prawn/security.rb +55 -33
  53. data/lib/prawn/soft_mask.rb +96 -0
  54. data/lib/prawn/stamp.rb +5 -3
  55. data/lib/prawn/table/cell/image.rb +69 -0
  56. data/lib/prawn/table/cell/in_table.rb +4 -2
  57. data/lib/prawn/table/cell/span_dummy.rb +93 -0
  58. data/lib/prawn/table/cell/subtable.rb +2 -2
  59. data/lib/prawn/table/cell/text.rb +44 -26
  60. data/lib/prawn/table/cell.rb +302 -50
  61. data/lib/prawn/table/cells.rb +147 -49
  62. data/lib/prawn/table/column_width_calculator.rb +61 -0
  63. data/lib/prawn/table.rb +297 -118
  64. data/lib/prawn/text/box.rb +21 -5
  65. data/lib/prawn/text/formatted/arranger.rb +290 -0
  66. data/lib/prawn/text/formatted/box.rb +103 -59
  67. data/lib/prawn/text/formatted/fragment.rb +34 -23
  68. data/lib/prawn/text/formatted/line_wrap.rb +266 -0
  69. data/lib/prawn/text/formatted/parser.rb +15 -5
  70. data/lib/prawn/text/formatted/wrap.rb +150 -0
  71. data/lib/prawn/text/formatted.rb +5 -4
  72. data/lib/prawn/text.rb +38 -24
  73. data/lib/prawn/utilities.rb +46 -0
  74. data/lib/prawn.rb +85 -20
  75. data/manual/basic_concepts/adding_pages.rb +27 -0
  76. data/manual/basic_concepts/basic_concepts.rb +34 -0
  77. data/manual/basic_concepts/creation.rb +39 -0
  78. data/manual/basic_concepts/cursor.rb +33 -0
  79. data/manual/basic_concepts/measurement.rb +25 -0
  80. data/manual/basic_concepts/origin.rb +38 -0
  81. data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
  82. data/manual/bounding_box/bounding_box.rb +39 -0
  83. data/manual/bounding_box/bounds.rb +49 -0
  84. data/manual/bounding_box/canvas.rb +24 -0
  85. data/manual/bounding_box/creation.rb +23 -0
  86. data/manual/bounding_box/indentation.rb +46 -0
  87. data/manual/bounding_box/nesting.rb +45 -0
  88. data/manual/bounding_box/russian_boxes.rb +40 -0
  89. data/manual/bounding_box/stretchy.rb +31 -0
  90. data/manual/document_and_page_options/background.rb +27 -0
  91. data/manual/document_and_page_options/document_and_page_options.rb +32 -0
  92. data/manual/document_and_page_options/metadata.rb +23 -0
  93. data/manual/document_and_page_options/page_margins.rb +38 -0
  94. data/manual/document_and_page_options/page_size.rb +34 -0
  95. data/manual/document_and_page_options/print_scaling.rb +20 -0
  96. data/manual/example_file.rb +111 -0
  97. data/manual/example_helper.rb +411 -0
  98. data/manual/example_package.rb +53 -0
  99. data/manual/example_section.rb +46 -0
  100. data/manual/graphics/circle_and_ellipse.rb +22 -0
  101. data/manual/graphics/color.rb +24 -0
  102. data/manual/graphics/common_lines.rb +30 -0
  103. data/manual/graphics/fill_and_stroke.rb +42 -0
  104. data/manual/graphics/fill_rules.rb +37 -0
  105. data/manual/graphics/gradients.rb +37 -0
  106. data/manual/graphics/graphics.rb +58 -0
  107. data/manual/graphics/helper.rb +24 -0
  108. data/manual/graphics/line_width.rb +35 -0
  109. data/manual/graphics/lines_and_curves.rb +41 -0
  110. data/manual/graphics/polygon.rb +29 -0
  111. data/manual/graphics/rectangle.rb +21 -0
  112. data/manual/graphics/rotate.rb +28 -0
  113. data/manual/graphics/scale.rb +41 -0
  114. data/manual/graphics/soft_masks.rb +46 -0
  115. data/manual/graphics/stroke_cap.rb +31 -0
  116. data/manual/graphics/stroke_dash.rb +48 -0
  117. data/manual/graphics/stroke_join.rb +30 -0
  118. data/manual/graphics/translate.rb +29 -0
  119. data/manual/graphics/transparency.rb +35 -0
  120. data/manual/images/absolute_position.rb +23 -0
  121. data/manual/images/fit.rb +21 -0
  122. data/manual/images/horizontal.rb +25 -0
  123. data/manual/images/images.rb +40 -0
  124. data/manual/images/plain_image.rb +18 -0
  125. data/manual/images/scale.rb +22 -0
  126. data/manual/images/vertical.rb +28 -0
  127. data/manual/images/width_and_height.rb +25 -0
  128. data/manual/layout/boxes.rb +27 -0
  129. data/manual/layout/content.rb +25 -0
  130. data/manual/layout/layout.rb +28 -0
  131. data/manual/layout/simple_grid.rb +23 -0
  132. data/manual/manual/cover.rb +36 -0
  133. data/manual/manual/foreword.rb +85 -0
  134. data/manual/manual/how_to_read_this_manual.rb +41 -0
  135. data/manual/manual/manual.rb +34 -0
  136. data/manual/outline/add_subsection_to.rb +61 -0
  137. data/manual/outline/insert_section_after.rb +47 -0
  138. data/manual/outline/outline.rb +32 -0
  139. data/manual/outline/sections_and_pages.rb +67 -0
  140. data/manual/repeatable_content/page_numbering.rb +54 -0
  141. data/manual/repeatable_content/repeatable_content.rb +31 -0
  142. data/manual/repeatable_content/repeater.rb +55 -0
  143. data/manual/repeatable_content/stamp.rb +41 -0
  144. data/manual/security/encryption.rb +31 -0
  145. data/manual/security/permissions.rb +38 -0
  146. data/manual/security/security.rb +28 -0
  147. data/manual/syntax_highlight.rb +52 -0
  148. data/manual/table/basic_block.rb +53 -0
  149. data/manual/table/before_rendering_page.rb +26 -0
  150. data/manual/table/cell_border_lines.rb +24 -0
  151. data/manual/table/cell_borders_and_bg.rb +31 -0
  152. data/manual/table/cell_dimensions.rb +30 -0
  153. data/manual/table/cell_text.rb +38 -0
  154. data/manual/table/column_widths.rb +30 -0
  155. data/manual/table/content_and_subtables.rb +39 -0
  156. data/manual/table/creation.rb +27 -0
  157. data/manual/table/filtering.rb +36 -0
  158. data/manual/table/flow_and_header.rb +17 -0
  159. data/manual/table/image_cells.rb +33 -0
  160. data/manual/table/position.rb +29 -0
  161. data/manual/table/row_colors.rb +20 -0
  162. data/manual/table/span.rb +30 -0
  163. data/manual/table/style.rb +22 -0
  164. data/manual/table/table.rb +52 -0
  165. data/manual/table/width.rb +27 -0
  166. data/manual/text/alignment.rb +44 -0
  167. data/manual/text/color.rb +24 -0
  168. data/manual/text/column_box.rb +32 -0
  169. data/manual/text/fallback_fonts.rb +37 -0
  170. data/manual/text/font.rb +41 -0
  171. data/manual/text/font_size.rb +45 -0
  172. data/manual/text/font_style.rb +23 -0
  173. data/manual/text/formatted_callbacks.rb +60 -0
  174. data/manual/text/formatted_text.rb +54 -0
  175. data/manual/text/free_flowing_text.rb +51 -0
  176. data/manual/text/group.rb +31 -0
  177. data/manual/text/inline.rb +43 -0
  178. data/manual/text/kerning_and_character_spacing.rb +39 -0
  179. data/manual/text/leading.rb +25 -0
  180. data/manual/text/line_wrapping.rb +41 -0
  181. data/manual/text/paragraph_indentation.rb +26 -0
  182. data/manual/text/positioned_text.rb +38 -0
  183. data/manual/text/registering_families.rb +48 -0
  184. data/manual/text/rendering_and_color.rb +37 -0
  185. data/manual/text/right_to_left_text.rb +43 -0
  186. data/manual/text/rotation.rb +43 -0
  187. data/manual/text/single_usage.rb +37 -0
  188. data/manual/text/text.rb +75 -0
  189. data/manual/text/text_box_excess.rb +32 -0
  190. data/manual/text/text_box_extensions.rb +45 -0
  191. data/manual/text/text_box_overflow.rb +44 -0
  192. data/manual/text/utf8.rb +28 -0
  193. data/{examples/m17n → manual/text}/win_ansi_charset.rb +14 -10
  194. data/prawn.gemspec +27 -17
  195. data/spec/acceptance/png.rb +23 -0
  196. data/spec/annotations_spec.rb +16 -32
  197. data/spec/bounding_box_spec.rb +284 -2
  198. data/spec/cell_spec.rb +169 -38
  199. data/spec/column_box_spec.rb +65 -0
  200. data/spec/data/curves.pdf +66 -0
  201. data/spec/destinations_spec.rb +5 -5
  202. data/spec/document_spec.rb +212 -113
  203. data/spec/extensions/encoding_helpers.rb +9 -0
  204. data/spec/extensions/mocha.rb +2 -3
  205. data/spec/font_metric_cache_spec.rb +52 -0
  206. data/spec/font_spec.rb +205 -95
  207. data/spec/formatted_text_arranger_spec.rb +43 -43
  208. data/spec/formatted_text_box_spec.rb +63 -24
  209. data/spec/formatted_text_fragment_spec.rb +8 -8
  210. data/spec/graphics_spec.rb +175 -68
  211. data/spec/grid_spec.rb +26 -15
  212. data/spec/image_handler_spec.rb +54 -0
  213. data/spec/images_spec.rb +58 -30
  214. data/spec/inline_formatted_text_parser_spec.rb +73 -19
  215. data/spec/jpg_spec.rb +4 -4
  216. data/spec/line_wrap_spec.rb +28 -28
  217. data/spec/measurement_units_spec.rb +6 -6
  218. data/spec/object_store_spec.rb +17 -106
  219. data/spec/outline_spec.rb +103 -63
  220. data/spec/png_spec.rb +25 -25
  221. data/spec/reference_spec.rb +8 -65
  222. data/spec/repeater_spec.rb +25 -11
  223. data/spec/security_spec.rb +44 -12
  224. data/spec/snapshot_spec.rb +38 -6
  225. data/spec/soft_mask_spec.rb +117 -0
  226. data/spec/span_spec.rb +10 -15
  227. data/spec/spec_helper.rb +32 -8
  228. data/spec/stamp_spec.rb +29 -30
  229. data/spec/stroke_styles_spec.rb +36 -18
  230. data/spec/table/span_dummy_spec.rb +17 -0
  231. data/spec/table_spec.rb +850 -104
  232. data/spec/text_at_spec.rb +19 -33
  233. data/spec/text_box_spec.rb +117 -64
  234. data/spec/text_rendering_mode_spec.rb +5 -5
  235. data/spec/text_spacing_spec.rb +20 -2
  236. data/spec/text_spec.rb +111 -59
  237. data/spec/transparency_spec.rb +5 -5
  238. metadata +477 -328
  239. data/HACKING +0 -50
  240. data/README +0 -141
  241. data/data/fonts/Action Man.dfont +0 -0
  242. data/data/fonts/Activa.ttf +0 -0
  243. data/data/fonts/Chalkboard.ttf +0 -0
  244. data/data/fonts/DejaVuSans.ttf +0 -0
  245. data/data/fonts/Dustismo_Roman.ttf +0 -0
  246. data/data/fonts/comicsans.ttf +0 -0
  247. data/data/fonts/gkai00mp.ttf +0 -0
  248. data/data/images/16bit.dat +0 -0
  249. data/data/images/dice.dat +0 -0
  250. data/data/images/page_white_text.dat +0 -0
  251. data/data/images/rails.dat +0 -0
  252. data/data/images/rails.png +0 -0
  253. data/examples/bounding_box/bounding_boxes.rb +0 -44
  254. data/examples/bounding_box/indentation.rb +0 -35
  255. data/examples/bounding_box/russian_boxes.rb +0 -37
  256. data/examples/bounding_box/stretched_nesting.rb +0 -68
  257. data/examples/example_helper.rb +0 -8
  258. data/examples/general/background.rb +0 -24
  259. data/examples/general/canvas.rb +0 -16
  260. data/examples/general/context_sensitive_headers.rb +0 -38
  261. data/examples/general/float.rb +0 -12
  262. data/examples/general/margin.rb +0 -37
  263. data/examples/general/measurement_units.rb +0 -52
  264. data/examples/general/metadata-info.rb +0 -17
  265. data/examples/general/multi_page_layout.rb +0 -19
  266. data/examples/general/outlines.rb +0 -67
  267. data/examples/general/page_geometry.rb +0 -32
  268. data/examples/general/page_numbering.rb +0 -40
  269. data/examples/general/page_templates.rb +0 -20
  270. data/examples/general/repeaters.rb +0 -48
  271. data/examples/general/stamp.rb +0 -42
  272. data/examples/general/templates.rb +0 -14
  273. data/examples/graphics/basic_images.rb +0 -24
  274. data/examples/graphics/cmyk.rb +0 -13
  275. data/examples/graphics/curves.rb +0 -12
  276. data/examples/graphics/gradient.rb +0 -23
  277. data/examples/graphics/hexagon.rb +0 -14
  278. data/examples/graphics/image_fit.rb +0 -16
  279. data/examples/graphics/image_flow.rb +0 -38
  280. data/examples/graphics/image_position.rb +0 -18
  281. data/examples/graphics/line.rb +0 -33
  282. data/examples/graphics/png_types.rb +0 -23
  283. data/examples/graphics/polygons.rb +0 -17
  284. data/examples/graphics/remote_images.rb +0 -13
  285. data/examples/graphics/rounded_polygons.rb +0 -20
  286. data/examples/graphics/rounded_rectangle.rb +0 -21
  287. data/examples/graphics/ruport_style_helpers.rb +0 -20
  288. data/examples/graphics/stroke_bounds.rb +0 -21
  289. data/examples/graphics/stroke_cap_and_join.rb +0 -46
  290. data/examples/graphics/stroke_dash.rb +0 -43
  291. data/examples/graphics/transformations.rb +0 -53
  292. data/examples/graphics/transparency.rb +0 -27
  293. data/examples/grid/bounding_boxes.rb +0 -22
  294. data/examples/grid/column_gutter_grid.rb +0 -21
  295. data/examples/grid/multi_boxes.rb +0 -52
  296. data/examples/grid/show_grid.rb +0 -14
  297. data/examples/grid/simple_grid.rb +0 -21
  298. data/examples/m17n/chinese_text_wrapping.rb +0 -18
  299. data/examples/m17n/euro.rb +0 -16
  300. data/examples/m17n/full_win_ansi_character_list.rb +0 -20
  301. data/examples/m17n/sjis.rb +0 -29
  302. data/examples/m17n/utf8.rb +0 -14
  303. data/examples/security/hello_foo.rb +0 -9
  304. data/examples/table/bill.rb +0 -54
  305. data/examples/table/borders.rb +0 -25
  306. data/examples/table/cell.rb +0 -13
  307. data/examples/table/checkerboard.rb +0 -23
  308. data/examples/table/header.rb +0 -15
  309. data/examples/table/inline_format_table.rb +0 -13
  310. data/examples/table/multi_page_table.rb +0 -10
  311. data/examples/table/simple_table.rb +0 -25
  312. data/examples/table/subtable.rb +0 -13
  313. data/examples/table/widths.rb +0 -21
  314. data/examples/text/alignment.rb +0 -19
  315. data/examples/text/character_spacing.rb +0 -13
  316. data/examples/text/dfont.rb +0 -49
  317. data/examples/text/family_based_styling.rb +0 -25
  318. data/examples/text/font_calculations.rb +0 -92
  319. data/examples/text/font_size.rb +0 -34
  320. data/examples/text/hyphenation.rb +0 -45
  321. data/examples/text/indent_paragraphs.rb +0 -24
  322. data/examples/text/inline_format.rb +0 -104
  323. data/examples/text/kerning.rb +0 -31
  324. data/examples/text/rendering_mode.rb +0 -21
  325. data/examples/text/rotated.rb +0 -99
  326. data/examples/text/shaped_text_box.rb +0 -32
  327. data/examples/text/simple_text.rb +0 -18
  328. data/examples/text/simple_text_ttf.rb +0 -18
  329. data/examples/text/span.rb +0 -30
  330. data/examples/text/text_box.rb +0 -90
  331. data/examples/text/text_box_returning_excess.rb +0 -52
  332. data/examples/text/text_flow.rb +0 -68
  333. data/lib/prawn/compatibility.rb +0 -51
  334. data/lib/prawn/core/annotations.rb +0 -61
  335. data/lib/prawn/core/byte_string.rb +0 -9
  336. data/lib/prawn/core/destinations.rb +0 -90
  337. data/lib/prawn/core/document_state.rb +0 -78
  338. data/lib/prawn/core/literal_string.rb +0 -16
  339. data/lib/prawn/core/name_tree.rb +0 -165
  340. data/lib/prawn/core/object_store.rb +0 -264
  341. data/lib/prawn/core/page.rb +0 -213
  342. data/lib/prawn/core/pdf_object.rb +0 -108
  343. data/lib/prawn/core/reference.rb +0 -112
  344. data/lib/prawn/core/text/formatted/arranger.rb +0 -293
  345. data/lib/prawn/core/text/formatted/line_wrap.rb +0 -272
  346. data/lib/prawn/core/text/formatted/wrap.rb +0 -149
  347. data/lib/prawn/core/text.rb +0 -268
  348. data/lib/prawn/core.rb +0 -85
  349. data/lib/prawn/document/page_geometry.rb +0 -136
  350. data/lib/prawn/graphics/gradient.rb +0 -84
  351. data/spec/name_tree_spec.rb +0 -112
  352. data/spec/pdf_object_spec.rb +0 -170
  353. data/spec/template_spec.rb +0 -291
data/spec/table_spec.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), "spec_helper")
4
4
  require 'set'
5
5
 
6
6
  describe "Prawn::Table" do
@@ -12,7 +12,7 @@ describe "Prawn::Table" do
12
12
  end
13
13
 
14
14
  it "should return a Prawn::Table" do
15
- @table.should.be.an.instance_of Prawn::Table
15
+ @table.should be_a_kind_of Prawn::Table
16
16
  end
17
17
 
18
18
  it "should flatten the data into the @cells array in row-major order" do
@@ -29,23 +29,158 @@ describe "Prawn::Table" do
29
29
  lambda {
30
30
  data = [["foo","bar"],["baz",""]]
31
31
  @pdf.table(data)
32
- }.should.not.raise
33
- end
32
+ }.should_not raise_error
33
+ end
34
34
 
35
35
  it "should allow a table with a header but no body" do
36
- lambda { @pdf.table([["Header"]], :header => true) }.should.not.raise
36
+ lambda { @pdf.table([["Header"]], :header => true) }.should_not raise_error
37
37
  end
38
38
 
39
- # TODO: pending colspan
40
- xit "should accurately count columns from data" do
39
+ it "should accurately count columns from data" do
41
40
  # First data row may contain colspan which would hide true column count
42
- data = [["Name:",{:text => "Some very long name", :colspan => 5}]]
41
+ data = [["Name:", {:content => "Some very long name", :colspan => 5}]]
43
42
  pdf = Prawn::Document.new
44
43
  table = Prawn::Table.new data, pdf
45
44
  table.column_widths.length.should == 6
46
45
  end
47
46
  end
48
47
 
48
+ describe "You can explicitly set the column widths and use a colspan > 1" do
49
+
50
+ it "should tolerate floating point rounding errors < 0.000000001" do
51
+ data=[["a", "b ", "c ", "d", "e", "f", "g", "h", "i", "j", "k", "l"],
52
+ [{:content=>"Foobar", :colspan=>12}]
53
+ ]
54
+ #we need values with lots of decimals so that arithmetic errors will occur
55
+ #the values are not arbitrary but where found converting mm to pdf pt
56
+ column_widths=[137, 40, 40, 54.69291338582678, 54.69291338582678,
57
+ 54.69291338582678, 54.69291338582678, 54.69291338582678,
58
+ 54.69291338582678, 54.69291338582678, 54.69291338582678,
59
+ 54.69291338582678]
60
+
61
+ pdf = Prawn::Document.new({:page_size => 'A4', :page_layout => :landscape})
62
+ table = Prawn::Table.new data, pdf, :column_widths => column_widths
63
+ table.column_widths.should == column_widths
64
+ end
65
+
66
+ it "should work with two different given colspans", :issue => 628 do
67
+ data = [
68
+ [" ", " ", " "],
69
+ [{:content=>" ", :colspan=>3}],
70
+ [" ", {:content=>" ", :colspan=>2}]
71
+ ]
72
+ column_widths = [60, 240, 60]
73
+ pdf = Prawn::Document.new
74
+ #the next line raised an Prawn::Errors::CannotFit exception before issue 628 was fixed
75
+ table = Prawn::Table.new data, pdf, :column_widths => column_widths
76
+ table.column_widths.should == column_widths
77
+ end
78
+
79
+ it "should work with a colspan > 1 with given column_widths (issue #407)" do
80
+ #normal entries in line 1
81
+ data = [
82
+ [ '','',''],
83
+ [ { :content => "", :colspan => 3 } ],
84
+ [ "", "", "" ],
85
+ ]
86
+ pdf = Prawn::Document.new
87
+ table = Prawn::Table.new data, pdf, :column_widths => [100 , 200, 240]
88
+
89
+ #colspan entry in line 1
90
+ data = [
91
+ [ { :content => "", :colspan => 3 } ],
92
+ [ "", "", "" ],
93
+ ]
94
+ pdf = Prawn::Document.new
95
+ table = Prawn::Table.new data, pdf, :column_widths => [100 , 200, 240]
96
+
97
+ #mixed entries in line 1
98
+ data = [
99
+ [ { :content => "", :colspan =>2 }, "" ],
100
+ [ "", "", "" ],
101
+ ]
102
+ pdf = Prawn::Document.new
103
+ table = Prawn::Table.new data, pdf, :column_widths => [100 , 200, 240]
104
+
105
+ data = [['', '', {:content => '', :colspan => 2}, '',''],
106
+ ['',{:content => '', :colspan => 5}]
107
+ ]
108
+ pdf = Prawn::Document.new
109
+ table = Prawn::Table.new data, pdf, :column_widths => [50 , 100, 50, 50, 50, 50]
110
+
111
+ end
112
+
113
+ it "should not increase column width when rendering a subtable",
114
+ :unresolved, :issue => 612 do
115
+
116
+ pdf = Prawn::Document.new
117
+
118
+ first = {:content=>"Foooo fo foooooo",:width=>50,:align=>:center}
119
+ second = {:content=>"Foooo",:colspan=>2,:width=>70,:align=>:center}
120
+ third = {:content=>"fooooooooooo, fooooooooooooo, fooo, foooooo fooooo",:width=>50,:align=>:center}
121
+ fourth = {:content=>"Bar",:width=>20,:align=>:center}
122
+
123
+ table_content = [[
124
+ first,
125
+ [[second],[third,fourth]]
126
+ ]]
127
+
128
+ table = Prawn::Table.new table_content, pdf
129
+ table.column_widths.should == [50.0, 70.0]
130
+ end
131
+
132
+ it "illustrate issue #533" do
133
+ data = [['', '', '', '', '',''],
134
+ ['',{:content => '', :colspan => 5}]]
135
+ pdf = Prawn::Document.new
136
+ table = Prawn::Table.new data, pdf, :column_widths => [50, 200, 40, 40, 50, 50]
137
+ end
138
+
139
+ it "illustrates issue #502" do
140
+ pdf = Prawn::Document.new
141
+ first = {:content=>"Foooo fo foooooo",:width=>50,:align=>:center}
142
+ second = {:content=>"Foooo",:colspan=>2,:width=>70,:align=>:center}
143
+ third = {:content=>"fooooooooooo, fooooooooooooo, fooo, foooooo fooooo",:width=>50,:align=>:center}
144
+ fourth = {:content=>"Bar",:width=>20,:align=>:center}
145
+ table_content = [[
146
+ first,
147
+ [[second],[third,fourth]]
148
+ ]]
149
+ pdf.move_down(20)
150
+ table = Prawn::Table.new table_content, pdf
151
+ pdf.table(table_content)
152
+ end
153
+
154
+ #https://github.com/prawnpdf/prawn/issues/407#issuecomment-28556698
155
+ it "correctly computes column widths with empty cells + colspan" do
156
+ data = [['', ''],
157
+ [{:content => '', :colspan => 2}]
158
+ ]
159
+ pdf = Prawn::Document.new
160
+
161
+ table = Prawn::Table.new data, pdf, :column_widths => [50, 200]
162
+ table.column_widths.should == [50.0, 200.0]
163
+ end
164
+
165
+ it "illustrates a variant of problem in issue #407 - comment 28556698" do
166
+ pdf = Prawn::Document.new
167
+ table_data = [["a", "b", "c"], [{:content=>"d", :colspan=>3}]]
168
+ column_widths = [50, 60, 400]
169
+
170
+ # Before we fixed #407, this line incorrectly raise a CannotFit error
171
+ pdf.table(table_data, :column_widths => column_widths)
172
+ end
173
+
174
+ it "should not allow oversized subtables when parent column width is constrained" do
175
+ pdf = Prawn::Document.new
176
+ child_1 = pdf.make_table([['foo'*100]])
177
+ child_2 = pdf.make_table([['foo']])
178
+ lambda do
179
+ pdf.table([[child_1], [child_2]], column_widths: [pdf.bounds.width/2] * 2)
180
+ end.should raise_error(Prawn::Errors::CannotFit)
181
+ end
182
+ end
183
+
49
184
  describe "#initialize" do
50
185
  before(:each) do
51
186
  @pdf = Prawn::Document.new
@@ -56,7 +191,8 @@ describe "Prawn::Table" do
56
191
  initializer.expects(:kick).once
57
192
 
58
193
  @pdf.table([["a"]]){
59
- self.should.be.an.instance_of(Prawn::Table); initializer.kick }
194
+ initializer.kick
195
+ }
60
196
  end
61
197
 
62
198
  it "should call a 1-arg block with the document as the argument" do
@@ -64,7 +200,7 @@ describe "Prawn::Table" do
64
200
  initializer.expects(:kick).once
65
201
 
66
202
  @pdf.table([["a"]]){ |doc|
67
- doc.should.be.an.instance_of(Prawn::Table); initializer.kick }
203
+ doc.should be_a_kind_of(Prawn::Table); initializer.kick }
68
204
  end
69
205
 
70
206
  it "should proxy cell methods to #cells" do
@@ -80,7 +216,7 @@ describe "Prawn::Table" do
80
216
 
81
217
  it "should generate a text cell based on a String" do
82
218
  t = @pdf.table([["foo"]])
83
- t.cells[0,0].should.be.a.kind_of(Prawn::Table::Cell::Text)
219
+ t.cells[0,0].should be_a_kind_of(Prawn::Table::Cell::Text)
84
220
  end
85
221
 
86
222
  it "should pass through a text cell" do
@@ -97,9 +233,14 @@ describe "Prawn::Table" do
97
233
  end
98
234
 
99
235
  it "should select rows by number or range" do
100
- Set.new(@table.row(0).map { |c| c.content }).should ==
236
+ Set.new(@table.row(0).map { |c| c.content }).should ==
101
237
  Set.new(%w[R0C0 R0C1])
102
- Set.new(@table.rows(0..1).map { |c| c.content }).should ==
238
+ Set.new(@table.rows(0..1).map { |c| c.content }).should ==
239
+ Set.new(%w[R0C0 R0C1 R1C0 R1C1])
240
+ end
241
+
242
+ it "should select rows by array" do
243
+ Set.new(@table.rows([0, 1]).map { |c| c.content }).should ==
103
244
  Set.new(%w[R0C0 R0C1 R1C0 R1C1])
104
245
  end
105
246
 
@@ -113,9 +254,14 @@ describe "Prawn::Table" do
113
254
  end
114
255
 
115
256
  it "should select columns by number or range" do
116
- Set.new(@table.column(0).map { |c| c.content }).should ==
257
+ Set.new(@table.column(0).map { |c| c.content }).should ==
117
258
  Set.new(%w[R0C0 R1C0])
118
- Set.new(@table.columns(0..1).map { |c| c.content }).should ==
259
+ Set.new(@table.columns(0..1).map { |c| c.content }).should ==
260
+ Set.new(%w[R0C0 R0C1 R1C0 R1C1])
261
+ end
262
+
263
+ it "should select columns by array" do
264
+ Set.new(@table.columns([0, 1]).map { |c| c.content }).should ==
119
265
  Set.new(%w[R0C0 R0C1 R1C0 R1C1])
120
266
  end
121
267
 
@@ -133,13 +279,13 @@ describe "Prawn::Table" do
133
279
  end
134
280
 
135
281
  it "should accept a filter block, returning a cell proxy" do
136
- @table.cells.filter { |c| c.content =~ /R0/ }.column(1).map{ |c|
282
+ @table.cells.filter { |c| c.content =~ /R0/ }.column(1).map{ |c|
137
283
  c.content }.should == ["R0C1"]
138
284
  end
139
285
 
140
286
  it "should accept the [] method, returning a Cell or nil" do
141
287
  @table.cells[0, 0].content.should == "R0C0"
142
- @table.cells[12, 12].should.be.nil
288
+ @table.cells[12, 12].should be_nil
143
289
  end
144
290
 
145
291
  it "should proxy unknown methods to the cells" do
@@ -150,6 +296,20 @@ describe "Prawn::Table" do
150
296
  @table.cells[1, 0].height.should == 100
151
297
  end
152
298
 
299
+ it "should ignore non-setter methods" do
300
+ lambda {
301
+ @table.cells.content_width
302
+ }.should raise_error(NoMethodError)
303
+ end
304
+
305
+ it "skips cells that don't respond to the given method" do
306
+ table = @pdf.make_table([[{:content => "R0", :colspan => 2}],
307
+ %w[R1C0 R1C1]])
308
+ lambda {
309
+ table.row(0).font_style = :bold
310
+ }.should_not raise_error
311
+ end
312
+
153
313
  it "should accept the style method, proxying its calls to the cells" do
154
314
  @table.cells.style(:height => 200, :width => 200)
155
315
  @table.column(0).style(:width => 100)
@@ -194,14 +354,14 @@ describe "Prawn::Table" do
194
354
  end
195
355
 
196
356
  describe "width" do
197
- it "should raise an error if the given width is outside of range" do
357
+ it "should raise_error an error if the given width is outside of range" do
198
358
  lambda do
199
359
  @pdf.table([["foo"]], :width => 1)
200
- end.should.raise(Prawn::Errors::CannotFit)
360
+ end.should raise_error(Prawn::Errors::CannotFit)
201
361
 
202
362
  lambda do
203
363
  @pdf.table([[@long_text]], :width => @pdf.bounds.width + 100)
204
- end.should.raise(Prawn::Errors::CannotFit)
364
+ end.should raise_error(Prawn::Errors::CannotFit)
205
365
  end
206
366
 
207
367
  it "should accept the natural width for small tables" do
@@ -210,7 +370,7 @@ describe "Prawn::Table" do
210
370
  @table.width.should == @table.cells[0, 0].natural_content_width + pad
211
371
  end
212
372
 
213
- it "width should equal sum(column_widths)" do
373
+ it "width should == sum(column_widths)" do
214
374
  table = Prawn::Table.new([%w[ a b c ], %w[d e f]], @pdf) do
215
375
  column(0).width = 50
216
376
  column(1).width = 100
@@ -219,6 +379,13 @@ describe "Prawn::Table" do
219
379
  table.width.should == 300
220
380
  end
221
381
 
382
+ it "should accept Numeric for column_widths" do
383
+ table = Prawn::Table.new([%w[ a b c ], %w[d e f]], @pdf) do |t|
384
+ t.column_widths = 50
385
+ end
386
+ table.width.should == 150
387
+ end
388
+
222
389
  it "should calculate unspecified column widths as "+
223
390
  "(max(string_width) + 2*horizontal_padding)" do
224
391
  hpad, fs = 3, 12
@@ -236,13 +403,13 @@ describe "Prawn::Table" do
236
403
  "column widths within a single table" do
237
404
  hpad, fs = 10, 6
238
405
  stretchy_columns = 2
239
-
406
+
240
407
  col0_width = 50
241
408
  col1_width = @pdf.width_of("foo", :size => fs)
242
409
  col2_width = @pdf.width_of("foobar", :size => fs)
243
410
  col3_width = 150
244
411
 
245
- table = Prawn::Table.new( [%w[snake foo b apple],
412
+ table = Prawn::Table.new( [%w[snake foo b apple],
246
413
  %w[kitten d foobar banana]], @pdf,
247
414
  :cell_style => { :padding => hpad, :size => fs }) do
248
415
 
@@ -250,16 +417,38 @@ describe "Prawn::Table" do
250
417
  column(3).width = col3_width
251
418
  end
252
419
 
253
- table.width.should == col1_width + col2_width +
254
- 2*stretchy_columns*hpad +
420
+ table.width.should == col1_width + col2_width +
421
+ 2*stretchy_columns*hpad +
255
422
  col0_width + col3_width
256
423
  end
257
424
 
258
- it "should not exceed the maximum width of the margin_box" do
425
+ it "should preserve all manually requested column widths" do
426
+ col0_width = 50
427
+ col1_width = 20
428
+ col3_width = 60
429
+
430
+ table = Prawn::Table.new( [["snake", "foo", "b",
431
+ "some long, long text that will wrap"],
432
+ %w[kitten d foobar banana]], @pdf,
433
+ :width => 150) do
434
+
435
+ column(0).width = col0_width
436
+ column(1).width = col1_width
437
+ column(3).width = col3_width
438
+ end
439
+
440
+ table.draw
441
+
442
+ table.column(0).width.should == col0_width
443
+ table.column(1).width.should == col1_width
444
+ table.column(3).width.should == col3_width
445
+ end
446
+
447
+ it "should_not exceed the maximum width of the margin_box" do
259
448
  expected_width = @pdf.margin_box.width
260
449
  data = [
261
450
  ['This is a column with a lot of text that should comfortably exceed '+
262
- 'the width of a normal document margin_box width', 'Some more text',
451
+ 'the width of a normal document margin_box width', 'Some more text',
263
452
  'and then some more', 'Just a bit more to be extra sure']
264
453
  ]
265
454
  table = Prawn::Table.new(data, @pdf)
@@ -267,25 +456,25 @@ describe "Prawn::Table" do
267
456
  table.width.should == expected_width
268
457
  end
269
458
 
270
- it "should not exceed the maximum width of the margin_box even with" +
459
+ it "should_not exceed the maximum width of the margin_box even with" +
271
460
  "manual widths specified" do
272
461
  expected_width = @pdf.margin_box.width
273
462
  data = [
274
463
  ['This is a column with a lot of text that should comfortably exceed '+
275
- 'the width of a normal document margin_box width', 'Some more text',
464
+ 'the width of a normal document margin_box width', 'Some more text',
276
465
  'and then some more', 'Just a bit more to be extra sure']
277
466
  ]
278
467
  table = Prawn::Table.new(data, @pdf) { column(1).width = 100 }
279
468
 
280
469
  table.width.should == expected_width
281
470
  end
282
-
471
+
283
472
  it "scales down only the non-preset column widths when the natural width" +
284
473
  "exceeds the maximum width of the margin_box" do
285
474
  expected_width = @pdf.margin_box.width
286
475
  data = [
287
476
  ['This is a column with a lot of text that should comfortably exceed '+
288
- 'the width of a normal document margin_box width', 'Some more text',
477
+ 'the width of a normal document margin_box width', 'Some more text',
289
478
  'and then some more', 'Just a bit more to be extra sure']
290
479
  ]
291
480
  table = Prawn::Table.new(data, @pdf) { column(1).width = 100; column(3).width = 50 }
@@ -321,29 +510,29 @@ describe "Prawn::Table" do
321
510
  end
322
511
 
323
512
  it "should allow table cells to be resized in block" do
324
- lambda do
325
- @pdf.table([%w[1 2 3 4 5]]) do |t|
326
- t.width = 40
327
- t.cells.size = 8
328
- t.cells.padding = 0
329
- end
330
- end.should.not.raise(Prawn::Errors::CannotFit)
513
+ # if anything goes wrong, a CannotFit error will be raised
514
+
515
+ @pdf.table([%w[1 2 3 4 5]]) do |t|
516
+ t.width = 40
517
+ t.cells.size = 8
518
+ t.cells.padding = 0
519
+ end
331
520
  end
332
521
 
333
522
  it "should be the width of the :width parameter" do
334
523
  expected_width = 300
335
- table = Prawn::Table.new( [%w[snake foo b apple],
524
+ table = Prawn::Table.new( [%w[snake foo b apple],
336
525
  %w[kitten d foobar banana]], @pdf,
337
526
  :width => expected_width)
338
527
 
339
528
  table.width.should == expected_width
340
529
  end
341
530
 
342
- it "should not exceed the :width option" do
531
+ it "should_not exceed the :width option" do
343
532
  expected_width = 400
344
533
  data = [
345
534
  ['This is a column with a lot of text that should comfortably exceed '+
346
- 'the width of a normal document margin_box width', 'Some more text',
535
+ 'the width of a normal document margin_box width', 'Some more text',
347
536
  'and then some more', 'Just a bit more to be extra sure']
348
537
  ]
349
538
  table = Prawn::Table.new(data, @pdf, :width => expected_width)
@@ -351,11 +540,11 @@ describe "Prawn::Table" do
351
540
  table.width.should == expected_width
352
541
  end
353
542
 
354
- it "should not exceed the :width option even with manual widths specified" do
543
+ it "should_not exceed the :width option even with manual widths specified" do
355
544
  expected_width = 400
356
545
  data = [
357
546
  ['This is a column with a lot of text that should comfortably exceed '+
358
- 'the width of a normal document margin_box width', 'Some more text',
547
+ 'the width of a normal document margin_box width', 'Some more text',
359
548
  'and then some more', 'Just a bit more to be extra sure']
360
549
  ]
361
550
  table = Prawn::Table.new(data, @pdf, :width => expected_width) do
@@ -365,25 +554,26 @@ describe "Prawn::Table" do
365
554
  table.width.should == expected_width
366
555
  end
367
556
 
368
- # TODO: pending colspan
369
- xit "should calculate unspecified column widths even " +
557
+ it "should calculate unspecified column widths even " +
370
558
  "with colspan cells declared" do
371
559
  pdf = Prawn::Document.new
372
560
  hpad, fs = 3, 5
373
561
  columns = 3
374
562
 
375
- data = [ [ { :text => 'foo', :colspan => 2 }, "foobar" ],
563
+ data = [ [ { :content => 'foo', :colspan => 2 }, "foobar" ],
376
564
  [ "foo", "foo", "foo" ] ]
377
565
  table = Prawn::Table.new( data, pdf,
378
- :horizontal_padding => hpad,
379
- :font_size => fs )
566
+ :cell_style => {
567
+ :padding_left => hpad, :padding_right => hpad,
568
+ :size => fs
569
+ })
380
570
 
381
571
  col0_width = pdf.width_of("foo", :size => fs) # cell 1, 0
382
572
  col1_width = pdf.width_of("foo", :size => fs) # cell 1, 1
383
573
  col2_width = pdf.width_of("foobar", :size => fs) # cell 0, 1 (at col 2)
384
574
 
385
- table.width.should == col0_width.ceil + col1_width.ceil +
386
- col2_width.ceil + 2*columns*hpad
575
+ table.width.should == col0_width + col1_width +
576
+ col2_width + 2*columns*hpad
387
577
  end
388
578
  end
389
579
 
@@ -399,16 +589,16 @@ describe "Prawn::Table" do
399
589
  @pdf.y.should == old_y - table.height
400
590
  end
401
591
 
402
- it "should not wrap unnecessarily" do
592
+ it "should_not wrap unnecessarily" do
403
593
  # Test for FP errors and glitches
404
594
  t = @pdf.table([["Bender Bending Rodriguez"]])
405
595
  h = @pdf.height_of("one line")
406
- (t.height - 10).should.be < h*1.5
596
+ (t.height - 10).should be < h*1.5
407
597
  end
408
598
 
409
- it "should have a height of n rows" do
599
+ it "should have a height of n rows" do
410
600
  data = [["foo"],["bar"],["baaaz"]]
411
-
601
+
412
602
  vpad = 4
413
603
  origin = @pdf.y
414
604
  @pdf.table data, :cell_style => { :padding => vpad }
@@ -418,10 +608,45 @@ describe "Prawn::Table" do
418
608
  line_gap = @pdf.font.line_gap
419
609
 
420
610
  num_rows = data.length
421
- table_height.should.be.close(
422
- num_rows * font_height + 2*vpad*num_rows, 0.001 )
611
+ table_height.should be_within(0.001).of(
612
+ num_rows * font_height + 2*vpad*num_rows )
613
+ end
614
+
615
+ end
616
+
617
+ describe "position" do
618
+ it "should center tables with :position => :center" do
619
+ @pdf.expects(:bounding_box).with do |(x, y), opts|
620
+ expected = (@pdf.bounds.width - 500) / 2.0
621
+ (x - expected).abs < 0.001
622
+ end
623
+
624
+ @pdf.table([["foo"]], :column_widths => 500, :position => :center)
423
625
  end
424
626
 
627
+ it "should right-align tables with :position => :right" do
628
+ @pdf.expects(:bounding_box).with do |(x, y), opts|
629
+ expected = @pdf.bounds.width - 500
630
+ (x - expected).abs < 0.001
631
+ end
632
+
633
+ @pdf.table([["foo"]], :column_widths => 500, :position => :right)
634
+ end
635
+
636
+ it "should accept a Numeric" do
637
+ @pdf.expects(:bounding_box).with do |(x, y), opts|
638
+ expected = 123
639
+ (x - expected).abs < 0.001
640
+ end
641
+
642
+ @pdf.table([["foo"]], :column_widths => 500, :position => 123)
643
+ end
644
+
645
+ it "should raise_error an ArgumentError on unknown :position" do
646
+ lambda do
647
+ @pdf.table([["foo"]], :position => :bratwurst)
648
+ end.should raise_error(ArgumentError)
649
+ end
425
650
  end
426
651
 
427
652
  end
@@ -442,7 +667,7 @@ describe "Prawn::Table" do
442
667
  end.page_count.should == 2
443
668
  end
444
669
 
445
- it "should not start a new page before finishing out a row" do
670
+ it "should_not start a new page before finishing out a row" do
446
671
  Prawn::Document.new do
447
672
  table([[ (1..80).map{ |i| "Line #{i}" }.join("\n"), "Column 2" ]])
448
673
  end.page_count.should == 1
@@ -455,7 +680,7 @@ describe "Prawn::Table" do
455
680
  end.page_count.should == 2
456
681
  end
457
682
 
458
- it "should not start a new page to gain height when at the top of " +
683
+ it "should_not start a new page to gain height when at the top of " +
459
684
  "a bounding box, even if stretchy" do
460
685
  Prawn::Document.new do
461
686
  bounding_box([bounds.left, bounds.top - 20], :width => 400) do
@@ -482,9 +707,124 @@ describe "Prawn::Table" do
482
707
 
483
708
  output = PDF::Inspector::Page.analyze(pdf.render)
484
709
  # Ensure we only drew the header once, on the second page
485
- output.pages[0][:strings].should.be.empty
710
+ output.pages[0][:strings].should be_empty
486
711
  output.pages[1][:strings].should == ["Header", "Body"]
487
712
  end
713
+
714
+ it "should draw background before borders, but only within pages" do
715
+ seq = sequence("drawing_order")
716
+
717
+ @pdf = Prawn::Document.new
718
+
719
+ # give enough room for only the first row
720
+ @pdf.y = @pdf.bounds.absolute_bottom + 30
721
+ t = @pdf.make_table([["A", "B"],
722
+ ["C", "D"]],
723
+ :cell_style => {:background_color => 'ff0000'})
724
+
725
+ ca = t.cells[0, 0]
726
+ cb = t.cells[0, 1]
727
+ cc = t.cells[1, 0]
728
+ cd = t.cells[1, 1]
729
+
730
+ # All backgrounds should draw before any borders on page 1...
731
+ ca.expects(:draw_background).in_sequence(seq)
732
+ cb.expects(:draw_background).in_sequence(seq)
733
+ ca.expects(:draw_borders).in_sequence(seq)
734
+ cb.expects(:draw_borders).in_sequence(seq)
735
+ # ...and page 2
736
+ @pdf.expects(:start_new_page).in_sequence(seq)
737
+ cc.expects(:draw_background).in_sequence(seq)
738
+ cd.expects(:draw_background).in_sequence(seq)
739
+ cc.expects(:draw_borders).in_sequence(seq)
740
+ cd.expects(:draw_borders).in_sequence(seq)
741
+
742
+ t.draw
743
+ end
744
+
745
+ describe "before_rendering_page callback" do
746
+ before(:each) { @pdf = Prawn::Document.new }
747
+
748
+ it "is passed all cells to be rendered on that page" do
749
+ kicked = 0
750
+
751
+ @pdf.table([["foo"]] * 100) do |t|
752
+ t.before_rendering_page do |page|
753
+ page.row_count.should == ((kicked < 3) ? 30 : 10)
754
+ page.column_count.should == 1
755
+ page.row(0).first.content.should == "foo"
756
+ page.row(-1).first.content.should == "foo"
757
+ kicked += 1
758
+ end
759
+ end
760
+
761
+ kicked.should == 4
762
+ end
763
+
764
+ it "numbers cells relative to their position on page" do
765
+ @pdf.table([["foo"]] * 100) do |t|
766
+ t.before_rendering_page do |page|
767
+ page[0, 0].content.should == "foo"
768
+ end
769
+ end
770
+ end
771
+
772
+ it "changing cells in the callback affects their rendering" do
773
+ seq = sequence("render order")
774
+
775
+ t = @pdf.make_table([["foo"]] * 40) do |table|
776
+ table.before_rendering_page do |page|
777
+ page[0, 0].background_color = "ff0000"
778
+ end
779
+ end
780
+
781
+ t.cells[30, 0].stubs(:draw_background).checking do |xy|
782
+ t.cells[30, 0].background_color.should == 'ff0000'
783
+ end
784
+ t.cells[31, 0].stubs(:draw_background).checking do |xy|
785
+ t.cells[31, 0].background_color.should == nil
786
+ end
787
+
788
+ t.draw
789
+ end
790
+
791
+ it "passes headers on page 2+" do
792
+ @pdf.table([["header"]] + [["foo"]] * 100, :header => true) do |t|
793
+ t.before_rendering_page do |page|
794
+ page[0, 0].content.should == "header"
795
+ end
796
+ end
797
+ end
798
+
799
+ it "updates dummy cell header rows" do
800
+ header = [[{:content => "header", :colspan => 2}]]
801
+ data = [["foo", "bar"]] * 31
802
+ @pdf.table(header + data, :header => true) do |t|
803
+ t.before_rendering_page do |page|
804
+ cell = page[0, 0]
805
+ cell.dummy_cells.each {|dc| dc.row.should == cell.row }
806
+ end
807
+ end
808
+ end
809
+
810
+ it "allows headers to be changed" do
811
+ seq = sequence("render order")
812
+ @pdf.expects(:draw_text!).with { |t, _| t == "hdr1"}.in_sequence(seq)
813
+ @pdf.expects(:draw_text!).with { |t, _| t == "foo"}.times(29).in_sequence(seq)
814
+ # Verify that the changed cell doesn't mutate subsequent pages
815
+ @pdf.expects(:draw_text!).with { |t, _| t == "header"}.in_sequence(seq)
816
+ @pdf.expects(:draw_text!).with { |t, _| t == "foo"}.times(11).in_sequence(seq)
817
+
818
+ set_first_page_headers = false
819
+ @pdf.table([["header"]] + [["foo"]] * 40, :header => true) do |t|
820
+ t.before_rendering_page do |page|
821
+ # only change first page header
822
+ page[0, 0].content = "hdr1" unless set_first_page_headers
823
+ set_first_page_headers = true
824
+ end
825
+ end
826
+ end
827
+ end
488
828
  end
489
829
 
490
830
  describe "#style" do
@@ -505,11 +845,17 @@ describe "Prawn::Table" do
505
845
  it "should default to {} for the hash argument" do
506
846
  stylable = stub()
507
847
  stylable.expects(:style).with({}).once
508
-
848
+
509
849
  Prawn::Document.new do
510
850
  table([["x"]]) { style(stylable) }
511
851
  end
512
852
  end
853
+
854
+ it "ignores unknown values on a cell-by-cell basis" do
855
+ Prawn::Document.new do
856
+ table([["x", [["y"]]]], :cell_style => {:overflow => :shrink_to_fit})
857
+ end
858
+ end
513
859
  end
514
860
 
515
861
  describe "row_colors" do
@@ -523,14 +869,48 @@ describe "Prawn::Table" do
523
869
  it "should ignore headers" do
524
870
  data = [["header"], ["foo"], ["bar"], ["baz"]]
525
871
  pdf = Prawn::Document.new
526
- t = pdf.table(data, :header => true,
872
+ t = pdf.table(data, :header => true,
527
873
  :row_colors => ['cccccc', 'ffffff']) do
528
874
  row(0).background_color = '333333'
529
875
  end
530
876
 
531
- t.cells.map{|x| x.background_color}.should ==
877
+ t.cells.map{|x| x.background_color}.should ==
532
878
  %w[333333 cccccc ffffff cccccc]
533
879
  end
880
+
881
+ it "stripes rows consistently from page to page, skipping header rows" do
882
+ data = [["header"]] + [["foo"]] * 70
883
+ pdf = Prawn::Document.new
884
+ t = pdf.make_table(data, :header => true,
885
+ :row_colors => ['cccccc', 'ffffff']) do
886
+ cells.padding = 0
887
+ cells.size = 9
888
+ row(0).size = 11
889
+ end
890
+
891
+ # page 1: header + 67 cells (odd number -- verifies that the next
892
+ # page disrupts the even/odd coloring, since both the last data cell
893
+ # on this page and the first one on the next are colored cccccc)
894
+ Prawn::Table::Cell.expects(:draw_cells).with do |cells|
895
+ cells.map { |c, (x, y)| c.background_color } ==
896
+ [nil] + (%w[cccccc ffffff] * 33) + %w[cccccc]
897
+ end
898
+ # page 2: header and 3 data cells
899
+ Prawn::Table::Cell.expects(:draw_cells).with do |cells|
900
+ cells.map { |c, (x, y)| c.background_color } ==
901
+ [nil] + %w[cccccc ffffff cccccc]
902
+ end
903
+ t.draw
904
+ end
905
+
906
+ it "should_not override an explicit background_color" do
907
+ data = [["foo"], ["bar"], ["baz"]]
908
+ pdf = Prawn::Document.new
909
+ table = pdf.table(data, :row_colors => ['cccccc', 'ffffff']) { |t|
910
+ t.cells[0, 0].background_color = 'dddddd'
911
+ }
912
+ table.cells.map{|x| x.background_color}.should == %w[dddddd ffffff cccccc]
913
+ end
534
914
  end
535
915
 
536
916
  describe "inking" do
@@ -540,7 +920,7 @@ describe "Prawn::Table" do
540
920
 
541
921
  it "should set the x-position of each cell based on widths" do
542
922
  @table = @pdf.table([["foo", "bar", "baz"]])
543
-
923
+
544
924
  x = 0
545
925
  (0..2).each do |col|
546
926
  cell = @table.cells[0, col]
@@ -555,7 +935,7 @@ describe "Prawn::Table" do
555
935
 
556
936
  (0..2).each do |row|
557
937
  cell = @table.cells[row, 0]
558
- cell.y.should.be.close(y, 0.01)
938
+ cell.y.should be_within(0.01).of(y)
559
939
  y -= cell.height
560
940
  end
561
941
  end
@@ -568,19 +948,40 @@ describe "Prawn::Table" do
568
948
  output.strings.should == data.flatten
569
949
  end
570
950
 
571
- it "should not cause an error if rendering the very first row causes a " +
951
+ it "should_not cause an error if rendering the very first row causes a " +
572
952
  "page break" do
573
- Prawn::Document.new do
953
+ Prawn::Document.new do |pdf|
574
954
  arr = Array(1..5).collect{|i| ["cell #{i}"] }
575
955
 
576
- move_down( y - (bounds.absolute_bottom + 3) )
956
+ pdf.move_down( pdf.y - (pdf.bounds.absolute_bottom + 3) )
577
957
 
578
958
  lambda {
579
- table(arr)
580
- }.should.not.raise
959
+ pdf.table(arr)
960
+ }.should_not raise_error
581
961
  end
582
962
  end
583
963
 
964
+ it "should draw all backgrounds before any borders" do
965
+ # lest backgrounds overlap borders:
966
+ # https://github.com/sandal/prawn/pull/226
967
+
968
+ seq = sequence("drawing_order")
969
+
970
+ t = @pdf.make_table([["A", "B"]],
971
+ :cell_style => {:background_color => 'ff0000'})
972
+ ca = t.cells[0, 0]
973
+ cb = t.cells[0, 1]
974
+
975
+ # XXX Not a perfectly general test, because it would still be acceptable
976
+ # if we drew B then A
977
+ ca.expects(:draw_background).in_sequence(seq)
978
+ cb.expects(:draw_background).in_sequence(seq)
979
+ ca.expects(:draw_borders).in_sequence(seq)
980
+ cb.expects(:draw_borders).in_sequence(seq)
981
+
982
+ t.draw
983
+ end
984
+
584
985
  it "should allow multiple inkings of the same table" do
585
986
  pdf = Prawn::Document.new
586
987
  t = Prawn::Table.new([["foo"]], pdf)
@@ -595,33 +996,142 @@ describe "Prawn::Table" do
595
996
  pdf.move_cursor_to(400)
596
997
  t.draw
597
998
  end
999
+
1000
+ describe "in stretchy bounding boxes" do
1001
+ it "should draw all cells on a row at the same y-position" do
1002
+ pdf = Prawn::Document.new
1003
+
1004
+ text_y = pdf.y.to_i - 5 # text starts 5pt below current y pos (padding)
1005
+
1006
+ pdf.bounding_box([0, pdf.cursor], :width => pdf.bounds.width) do
1007
+ pdf.expects(:draw_text!).checking { |text, options|
1008
+ pdf.bounds.absolute_top.should == text_y
1009
+ }.times(3)
1010
+
1011
+ pdf.table([%w[a b c]])
1012
+ end
1013
+ end
1014
+ end
598
1015
  end
599
1016
 
600
1017
  describe "headers" do
601
- it "should add headers to output when specified" do
602
- data = [["a", "b"], ["foo","bar"],["baz","bang"]]
603
- @pdf = Prawn::Document.new
604
- @pdf.table(data, :header => true)
605
- output = PDF::Inspector::Text.analyze(@pdf.render)
606
- output.strings.should == data.flatten
607
- end
1018
+ context "single row header" do
1019
+ it "should add headers to output when specified" do
1020
+ data = [["a", "b"], ["foo","bar"],["baz","bang"]]
1021
+ @pdf = Prawn::Document.new
1022
+ @pdf.table(data, :header => true)
1023
+ output = PDF::Inspector::Text.analyze(@pdf.render)
1024
+ output.strings.should == data.flatten
1025
+ end
608
1026
 
609
- it "should repeat headers across pages" do
610
- data = [["foo","bar"]] * 30
611
- headers = ["baz","foobar"]
612
- @pdf = Prawn::Document.new
613
- @pdf.table([headers] + data, :header => true)
614
- output = PDF::Inspector::Text.analyze(@pdf.render)
615
- output.strings.should == headers + data.flatten[0..-3] + headers +
616
- data.flatten[-2..-1]
1027
+ it "should repeat headers across pages" do
1028
+ data = [["foo","bar"]] * 30
1029
+ headers = ["baz","foobar"]
1030
+ @pdf = Prawn::Document.new
1031
+ @pdf.table([headers] + data, :header => true)
1032
+ output = PDF::Inspector::Text.analyze(@pdf.render)
1033
+ output.strings.should == headers + data.flatten[0..-3] + headers +
1034
+ data.flatten[-2..-1]
1035
+ end
1036
+
1037
+ it "draws headers at the correct position" do
1038
+ data = [["header"]] + [["foo"]] * 40
1039
+
1040
+ Prawn::Table::Cell.expects(:draw_cells).times(2).checking do |cells|
1041
+ cells.each do |cell, pt|
1042
+ if cell.content == "header"
1043
+ # Assert that header text is drawn at the same location on each page
1044
+ if @header_location
1045
+ pt.should == @header_location
1046
+ else
1047
+ @header_location = pt
1048
+ end
1049
+ end
1050
+ end
1051
+ end
1052
+ @pdf = Prawn::Document.new
1053
+ @pdf.table(data, :header => true)
1054
+ end
1055
+
1056
+ it "draws headers at the correct position with column box" do
1057
+ data = [["header"]] + [["foo"]] * 40
1058
+
1059
+ Prawn::Table::Cell.expects(:draw_cells).times(2).checking do |cells|
1060
+ cells.each do |cell, pt|
1061
+ if cell.content == "header"
1062
+ pt[0].should == @pdf.bounds.left
1063
+ end
1064
+ end
1065
+ end
1066
+ @pdf = Prawn::Document.new
1067
+ @pdf.column_box [0, @pdf.cursor], :width => @pdf.bounds.width, :columns => 2 do
1068
+ @pdf.table(data, :header => true)
1069
+ end
1070
+ end
1071
+
1072
+ it "should_not draw header twice when starting new page" do
1073
+ @pdf = Prawn::Document.new
1074
+ @pdf.y = 0
1075
+ @pdf.table([["Header"], ["Body"]], :header => true)
1076
+ output = PDF::Inspector::Text.analyze(@pdf.render)
1077
+ output.strings.should == ["Header", "Body"]
1078
+ end
617
1079
  end
618
1080
 
619
- it "should not draw header twice when starting new page" do
620
- @pdf = Prawn::Document.new
621
- @pdf.y = 0
622
- @pdf.table([["Header"], ["Body"]], :header => true)
623
- output = PDF::Inspector::Text.analyze(@pdf.render)
624
- output.strings.should == ["Header", "Body"]
1081
+ context "multiple row header" do
1082
+ it "should add headers to output when specified" do
1083
+ data = [["a", "b"], ["c", "d"], ["foo","bar"],["baz","bang"]]
1084
+ @pdf = Prawn::Document.new
1085
+ @pdf.table(data, :header => 2)
1086
+ output = PDF::Inspector::Text.analyze(@pdf.render)
1087
+ output.strings.should == data.flatten
1088
+ end
1089
+
1090
+ it "should repeat headers across pages" do
1091
+ data = [["foo","bar"]] * 30
1092
+ headers = ["baz","foobar"] + ["bas", "foobaz"]
1093
+ @pdf = Prawn::Document.new
1094
+ @pdf.table([headers] + data, :header => 2)
1095
+ output = PDF::Inspector::Text.analyze(@pdf.render)
1096
+ output.strings.should == headers + data.flatten[0..-3] + headers +
1097
+ data.flatten[-4..-1]
1098
+ end
1099
+
1100
+ it "draws headers at the correct position" do
1101
+ data = [["header"]] + [["header2"]] + [["foo"]] * 40
1102
+
1103
+ Prawn::Table::Cell.expects(:draw_cells).times(2).checking do |cells|
1104
+ cells.each do |cell, pt|
1105
+ if cell.content == "header"
1106
+ # Assert that header text is drawn at the same location on each page
1107
+ if @header_location
1108
+ pt.should == @header_location
1109
+ else
1110
+ @header_location = pt
1111
+ end
1112
+ end
1113
+
1114
+ if cell.content == "header2"
1115
+ # Assert that header text is drawn at the same location on each page
1116
+ if @header2_location
1117
+ pt.should == @header2_location
1118
+ else
1119
+ @header2_location = pt
1120
+ end
1121
+ end
1122
+ end
1123
+ end
1124
+ @pdf = Prawn::Document.new
1125
+ @pdf.table(data, :header => 2)
1126
+ end
1127
+
1128
+ it "should_not draw header twice when starting new page" do
1129
+ @pdf = Prawn::Document.new
1130
+ @pdf.y = 0
1131
+ @pdf.table([["Header"], ["Header2"], ["Body"]], :header => 2)
1132
+ output = PDF::Inspector::Text.analyze(@pdf.render)
1133
+ output.strings.should == ["Header", "Header2", "Body"]
1134
+ end
625
1135
  end
626
1136
  end
627
1137
 
@@ -634,8 +1144,8 @@ describe "Prawn::Table" do
634
1144
 
635
1145
  it "can be created from an Array" do
636
1146
  cell = Prawn::Table::Cell.make(@pdf, [["foo"]])
637
- cell.should.be.an.instance_of(Prawn::Table::Cell::Subtable)
638
- cell.subtable.should.be.an.instance_of(Prawn::Table)
1147
+ cell.should be_a_kind_of(Prawn::Table::Cell::Subtable)
1148
+ cell.subtable.should be_a_kind_of(Prawn::Table)
639
1149
  end
640
1150
 
641
1151
  it "defaults its padding to zero" do
@@ -645,7 +1155,7 @@ describe "Prawn::Table" do
645
1155
  it "has a subtable accessor" do
646
1156
  @table.cells[0, 0].subtable.should == @subtable
647
1157
  end
648
-
1158
+
649
1159
  it "determines its dimensions from the subtable" do
650
1160
  @table.cells[0, 0].width.should == @subtable.width
651
1161
  @table.cells[0, 0].height.should == @subtable.height
@@ -654,35 +1164,271 @@ describe "Prawn::Table" do
654
1164
  end
655
1165
 
656
1166
  describe "An invalid table" do
657
-
1167
+
658
1168
  before(:each) do
659
1169
  @pdf = Prawn::Document.new
660
1170
  @bad_data = ["Single Nested Array"]
661
1171
  end
662
-
663
- it "should raise error when invalid table data is given" do
664
- assert_raises(Prawn::Errors::InvalidTableData) do
1172
+
1173
+ it "should raise_error error when invalid table data is given" do
1174
+ lambda {
665
1175
  @pdf.table(@bad_data)
666
- end
1176
+ }.should raise_error(Prawn::Errors::InvalidTableData)
667
1177
  end
668
1178
 
669
- it "should raise an EmptyTableError with empty table data" do
1179
+ it "should raise_error an EmptyTableError with empty table data" do
670
1180
  lambda {
671
1181
  data = []
672
1182
  @pdf = Prawn::Document.new
673
1183
  @pdf.table(data)
674
- }.should.raise( Prawn::Errors::EmptyTable )
675
- end
1184
+ }.should raise_error( Prawn::Errors::EmptyTable )
1185
+ end
676
1186
 
677
- it "should raise an EmptyTableError with nil table data" do
1187
+ it "should raise_error an EmptyTableError with nil table data" do
678
1188
  lambda {
679
1189
  data = nil
680
1190
  @pdf = Prawn::Document.new
681
1191
  @pdf.table(data)
682
- }.should.raise( Prawn::Errors::EmptyTable )
683
- end
1192
+ }.should raise_error( Prawn::Errors::EmptyTable )
1193
+ end
684
1194
 
685
1195
  end
686
1196
 
687
1197
  end
688
1198
 
1199
+ describe "colspan / rowspan" do
1200
+ before(:each) { create_pdf }
1201
+
1202
+ it "doesn't raise an error" do
1203
+ lambda {
1204
+ @pdf.table([[{:content => "foo", :colspan => 2, :rowspan => 2}]])
1205
+ }.should_not raise_error
1206
+ end
1207
+
1208
+ it "colspan is properly counted" do
1209
+ t = @pdf.make_table([[{:content => "foo", :colspan => 2}]])
1210
+ t.column_length.should == 2
1211
+ end
1212
+
1213
+ it "rowspan is properly counted" do
1214
+ t = @pdf.make_table([[{:content => "foo", :rowspan => 2}]])
1215
+ t.row_length.should == 2
1216
+ end
1217
+
1218
+ it "raises if colspan or rowspan are called after layout" do
1219
+ lambda {
1220
+ @pdf.table([["foo"]]) { cells[0, 0].colspan = 2 }
1221
+ }.should raise_error(Prawn::Errors::InvalidTableSpan)
1222
+
1223
+ lambda {
1224
+ @pdf.table([["foo"]]) { cells[0, 0].rowspan = 2 }
1225
+ }.should raise_error(Prawn::Errors::InvalidTableSpan)
1226
+ end
1227
+
1228
+ it "raises when spans overlap" do
1229
+ lambda {
1230
+ @pdf.table([["foo", {:content => "bar", :rowspan => 2}],
1231
+ [{:content => "baz", :colspan => 2}]])
1232
+ }.should raise_error(Prawn::Errors::InvalidTableSpan)
1233
+ end
1234
+
1235
+ it "table and cell width account for colspan" do
1236
+ t = @pdf.table([["a", {:content => "b", :colspan => 2}]],
1237
+ :column_widths => [100, 100, 100])
1238
+ spanned = t.cells[0, 1]
1239
+ spanned.colspan.should == 2
1240
+ t.width.should == 300
1241
+ t.cells.min_width.should == 300
1242
+ t.cells.max_width.should == 300
1243
+ spanned.width.should == 200
1244
+ end
1245
+
1246
+ it "table and cell height account for rowspan" do
1247
+ t = @pdf.table([["a"], [{:content => "b", :rowspan => 2}]]) do
1248
+ row(0..2).height = 100
1249
+ end
1250
+ spanned = t.cells[1, 0]
1251
+ spanned.rowspan.should == 2
1252
+ t.height.should == 300
1253
+ spanned.height.should == 200
1254
+ end
1255
+
1256
+ it "provides the full content_width as drawing space" do
1257
+ w = @pdf.make_table([["foo"]]).cells[0, 0].content_width
1258
+
1259
+ t = @pdf.make_table([[{:content => "foo", :colspan => 2}]])
1260
+ t.cells[0, 0].spanned_content_width.should == w
1261
+ end
1262
+
1263
+ it "dummy cells are not drawn" do
1264
+ # make a fake master cell for the dummy cell to slave to
1265
+ t = @pdf.make_table([[{:content => "foo", :colspan => 2}]])
1266
+
1267
+ # drawing just a dummy cell should_not ink
1268
+ @pdf.expects(:stroke_line).never
1269
+ @pdf.expects(:draw_text!).never
1270
+ Prawn::Table::Cell.draw_cells([t.cells[0, 1]])
1271
+ end
1272
+
1273
+ it "dummy cells do not add any height or width" do
1274
+ t1 = @pdf.table([["foo"]])
1275
+
1276
+ t2 = @pdf.table([[{:content => "foo", :colspan => 2}]])
1277
+ t2.width.should == t1.width
1278
+
1279
+ t3 = @pdf.table([[{:content => "foo", :rowspan => 2}]])
1280
+ t3.height.should == t1.height
1281
+ end
1282
+
1283
+ it "dummy cells ignored by #style" do
1284
+ t = @pdf.table([[{:content => "blah", :colspan => 2}]],
1285
+ :cell_style => { :size => 9 })
1286
+ t.cells[0, 0].size.should == 9
1287
+ end
1288
+
1289
+ context "inheriting master cell styles from dummy cell" do
1290
+ # Relatively full coverage for all these attributes that should be
1291
+ # inherited.
1292
+ [["border_X_width", 20],
1293
+ ["border_X_color", "123456"],
1294
+ ["padding_X", 20]].each do |attribute, val|
1295
+ attribute_right = attribute.sub("X", "right")
1296
+ attribute_left = attribute.sub("X", "left")
1297
+ attribute_bottom = attribute.sub("X", "bottom")
1298
+ attribute_top = attribute.sub("X", "top")
1299
+
1300
+ specify "#{attribute_right} of right column is inherited" do
1301
+ t = @pdf.table([[{:content => "blah", :colspan => 2}]]) do |table|
1302
+ table.column(1).send("#{attribute_right}=", val)
1303
+ end
1304
+
1305
+ t.cells[0, 0].send(attribute_right).should == val
1306
+ end
1307
+
1308
+ specify "#{attribute_bottom} of bottom row is inherited" do
1309
+ t = @pdf.table([[{:content => "blah", :rowspan => 2}]]) do |table|
1310
+ table.row(1).send("#{attribute_bottom}=", val)
1311
+ end
1312
+
1313
+ t.cells[0, 0].send(attribute_bottom).should == val
1314
+ end
1315
+
1316
+ specify "#{attribute_left} of right column is not inherited" do
1317
+ t = @pdf.table([[{:content => "blah", :colspan => 2}]]) do |table|
1318
+ table.column(1).send("#{attribute_left}=", val)
1319
+ end
1320
+
1321
+ t.cells[0, 0].send(attribute_left).should_not == val
1322
+ end
1323
+
1324
+ specify "#{attribute_right} of interior column is not inherited" do
1325
+ t = @pdf.table([[{:content => "blah", :colspan => 3}]]) do |table|
1326
+ table.column(1).send("#{attribute_right}=", val)
1327
+ end
1328
+
1329
+ t.cells[0, 0].send(attribute_right).should_not == val
1330
+ end
1331
+
1332
+ specify "#{attribute_bottom} of interior row is not inherited" do
1333
+ t = @pdf.table([[{:content => "blah", :rowspan => 3}]]) do |table|
1334
+ table.row(1).send("#{attribute_bottom}=", val)
1335
+ end
1336
+
1337
+ t.cells[0, 0].send(attribute_bottom).should_not == val
1338
+ end
1339
+
1340
+ specify "#{attribute_top} of bottom row is not inherited" do
1341
+ t = @pdf.table([[{:content => "blah", :rowspan => 2}]]) do |table|
1342
+ table.row(1).send("#{attribute_top}=", val)
1343
+ end
1344
+
1345
+ t.cells[0, 0].send(attribute_top).should_not == val
1346
+ end
1347
+ end
1348
+ end
1349
+
1350
+ it "splits natural width between cols in the group" do
1351
+ t = @pdf.table([[{:content => "foo", :colspan => 2}]])
1352
+ widths = t.column_widths
1353
+ widths[0].should == widths[1]
1354
+ end
1355
+
1356
+ it "splits natural width between cols when width is increased" do
1357
+ t = @pdf.table([[{:content => "foo", :colspan => 2}]],
1358
+ :width => @pdf.bounds.width)
1359
+ widths = t.column_widths
1360
+ widths[0].should == widths[1]
1361
+ end
1362
+
1363
+ it "splits min-width between cols in the group" do
1364
+ # Since column_widths, when reducing column widths, reduces proportional to
1365
+ # the remaining width after each column's min width, we must ensure that the
1366
+ # min-width is split proportionally in order to ensure the width is still
1367
+ # split evenly when the width is reduced. (See "splits natural width between
1368
+ # cols when width is reduced".)
1369
+ t = @pdf.table([[{:content => "foo", :colspan => 2}]],
1370
+ :width => 20)
1371
+ t.column(0).min_width.should == t.column(1).min_width
1372
+ end
1373
+
1374
+ it "splits natural width between cols when width is reduced" do
1375
+ t = @pdf.table([[{:content => "foo", :colspan => 2}]],
1376
+ :width => 20)
1377
+ widths = t.column_widths
1378
+ widths[0].should == widths[1]
1379
+ end
1380
+
1381
+ it "honors a large, explicitly set table width" do
1382
+ t = @pdf.table([[{:content => "AAAAAAAAAA", :colspan => 3}],
1383
+ ["A", "B", "C"]],
1384
+ :width => 400)
1385
+
1386
+ t.column_widths.inject(0) { |sum, w| sum + w }.
1387
+ should be_within(0.01).of(400)
1388
+ end
1389
+
1390
+ it "honors a small, explicitly set table width" do
1391
+ t = @pdf.table([[{:content => "Lorem ipsum dolor sit amet " * 20,
1392
+ :colspan => 3}],
1393
+ ["A", "B", "C"]],
1394
+ :width => 200)
1395
+ t.column_widths.inject(0) { |sum, w| sum + w }.
1396
+ should be_within(0.01).of(200)
1397
+ end
1398
+
1399
+ it "splits natural_content_height between rows in the group" do
1400
+ t = @pdf.table([[{:content => "foo", :rowspan => 2}]])
1401
+ heights = t.row_heights
1402
+ heights[0].should == heights[1]
1403
+ end
1404
+
1405
+ it "skips column numbers that have been col-spanned" do
1406
+ t = @pdf.table([["a", "b", {:content => "c", :colspan => 3}, "d"]])
1407
+ t.cells[0, 0].content.should == "a"
1408
+ t.cells[0, 1].content.should == "b"
1409
+ t.cells[0, 2].content.should == "c"
1410
+ t.cells[0, 3].should be_a_kind_of(Prawn::Table::Cell::SpanDummy)
1411
+ t.cells[0, 4].should be_a_kind_of(Prawn::Table::Cell::SpanDummy)
1412
+ t.cells[0, 5].content.should == "d"
1413
+ end
1414
+
1415
+ it "skips row/col positions that have been row-spanned" do
1416
+ t = @pdf.table([["a", {:content => "b", :colspan => 2, :rowspan => 2}, "c"],
1417
+ ["d", "e"],
1418
+ ["f", "g", "h", "i"]])
1419
+ t.cells[0, 0].content.should == "a"
1420
+ t.cells[0, 1].content.should == "b"
1421
+ t.cells[0, 2].should be_a_kind_of(Prawn::Table::Cell::SpanDummy)
1422
+ t.cells[0, 3].content.should == "c"
1423
+
1424
+ t.cells[1, 0].content.should == "d"
1425
+ t.cells[1, 1].should be_a_kind_of(Prawn::Table::Cell::SpanDummy)
1426
+ t.cells[1, 2].should be_a_kind_of(Prawn::Table::Cell::SpanDummy)
1427
+ t.cells[1, 3].content.should == "e"
1428
+
1429
+ t.cells[2, 0].content.should == "f"
1430
+ t.cells[2, 1].content.should == "g"
1431
+ t.cells[2, 2].content.should == "h"
1432
+ t.cells[2, 3].content.should == "i"
1433
+ end
1434
+ end