prawn 1.1.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +1 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +9 -40
  7. data/lib/prawn/document/bounding_box.rb +54 -40
  8. data/lib/prawn/document/column_box.rb +8 -10
  9. data/lib/prawn/document/internals.rb +39 -146
  10. data/lib/prawn/document/span.rb +23 -17
  11. data/lib/prawn/document.rb +217 -182
  12. data/lib/prawn/encoding.rb +69 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +124 -104
  15. data/lib/prawn/font_metric_cache.rb +23 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +5 -12
  18. data/lib/prawn/fonts/otf.rb +11 -0
  19. data/lib/prawn/fonts/ttc.rb +36 -0
  20. data/lib/prawn/{font → fonts}/ttf.rb +140 -88
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +5 -5
  23. data/lib/prawn/graphics/color.rb +46 -44
  24. data/lib/prawn/graphics/dash.rb +27 -11
  25. data/lib/prawn/graphics/join_style.rb +11 -6
  26. data/lib/prawn/graphics/patterns.rb +220 -78
  27. data/lib/prawn/graphics/transformation.rb +20 -12
  28. data/lib/prawn/graphics/transparency.rb +20 -18
  29. data/lib/prawn/graphics.rb +153 -115
  30. data/lib/prawn/grid.rb +93 -50
  31. data/lib/prawn/image_handler.rb +4 -4
  32. data/lib/prawn/images/image.rb +3 -2
  33. data/lib/prawn/images/jpg.rb +31 -24
  34. data/lib/prawn/images/png.rb +101 -68
  35. data/lib/prawn/images.rb +64 -56
  36. data/lib/prawn/measurement_extensions.rb +10 -9
  37. data/lib/prawn/measurements.rb +20 -23
  38. data/lib/prawn/outline.rb +96 -75
  39. data/lib/prawn/repeater.rb +16 -16
  40. data/lib/prawn/security/arcfour.rb +2 -2
  41. data/lib/prawn/security.rb +100 -85
  42. data/lib/prawn/soft_mask.rb +37 -38
  43. data/lib/prawn/stamp.rb +28 -13
  44. data/lib/prawn/text/box.rb +24 -29
  45. data/lib/prawn/text/formatted/arranger.rb +108 -63
  46. data/lib/prawn/text/formatted/box.rb +187 -124
  47. data/lib/prawn/text/formatted/fragment.rb +24 -20
  48. data/lib/prawn/text/formatted/line_wrap.rb +133 -73
  49. data/lib/prawn/text/formatted/parser.rb +147 -127
  50. data/lib/prawn/text/formatted/wrap.rb +48 -35
  51. data/lib/prawn/text/formatted.rb +5 -5
  52. data/lib/prawn/text.rb +103 -68
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +10 -22
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +39 -54
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +34 -25
  60. data/manual/basic_concepts/creation.rb +10 -11
  61. data/manual/basic_concepts/cursor.rb +4 -5
  62. data/manual/basic_concepts/measurement.rb +8 -9
  63. data/manual/basic_concepts/origin.rb +5 -6
  64. data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
  65. data/manual/basic_concepts/view.rb +48 -0
  66. data/manual/bounding_box/bounding_box.rb +30 -28
  67. data/manual/bounding_box/bounds.rb +12 -13
  68. data/manual/bounding_box/canvas.rb +7 -8
  69. data/manual/bounding_box/creation.rb +6 -7
  70. data/manual/bounding_box/indentation.rb +14 -15
  71. data/manual/bounding_box/nesting.rb +25 -18
  72. data/manual/bounding_box/russian_boxes.rb +18 -18
  73. data/manual/bounding_box/stretchy.rb +12 -14
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -32
  76. data/manual/document_and_page_options/background.rb +15 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +24 -22
  78. data/manual/document_and_page_options/metadata.rb +20 -18
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -13
  81. data/manual/document_and_page_options/print_scaling.rb +18 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +52 -0
  84. data/manual/graphics/circle_and_ellipse.rb +4 -5
  85. data/manual/graphics/color.rb +7 -9
  86. data/manual/graphics/common_lines.rb +7 -8
  87. data/manual/graphics/fill_and_stroke.rb +5 -6
  88. data/manual/graphics/fill_rules.rb +12 -11
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +46 -40
  91. data/manual/graphics/helper.rb +19 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +8 -9
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -9
  97. data/manual/graphics/scale.rb +14 -13
  98. data/manual/graphics/soft_masks.rb +4 -6
  99. data/manual/graphics/stroke_cap.rb +7 -8
  100. data/manual/graphics/stroke_dash.rb +15 -16
  101. data/manual/graphics/stroke_join.rb +6 -7
  102. data/manual/graphics/translate.rb +10 -10
  103. data/manual/graphics/transparency.rb +7 -9
  104. data/manual/how_to_read_this_manual.rb +8 -9
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +10 -11
  108. data/manual/images/images.rb +28 -27
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +16 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +10 -11
  114. data/manual/layout/content.rb +9 -10
  115. data/manual/layout/layout.rb +17 -18
  116. data/manual/layout/simple_grid.rb +6 -7
  117. data/manual/outline/add_subsection_to.rb +20 -21
  118. data/manual/outline/insert_section_after.rb +15 -16
  119. data/manual/outline/outline.rb +22 -21
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +27 -23
  124. data/manual/repeatable_content/repeater.rb +15 -16
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +8 -11
  127. data/manual/security/permissions.rb +20 -15
  128. data/manual/security/security.rb +18 -18
  129. data/manual/table.rb +16 -0
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -12
  132. data/manual/text/column_box.rb +9 -11
  133. data/manual/text/fallback_fonts.rb +25 -21
  134. data/manual/text/font.rb +11 -12
  135. data/manual/text/font_size.rb +13 -14
  136. data/manual/text/font_style.rb +10 -8
  137. data/manual/text/formatted_callbacks.rb +33 -23
  138. data/manual/text/formatted_text.rb +36 -25
  139. data/manual/text/free_flowing_text.rb +22 -23
  140. data/manual/text/inline.rb +18 -19
  141. data/manual/text/kerning_and_character_spacing.rb +14 -15
  142. data/manual/text/leading.rb +7 -8
  143. data/manual/text/line_wrapping.rb +37 -18
  144. data/manual/text/paragraph_indentation.rb +15 -10
  145. data/manual/text/positioned_text.rb +16 -17
  146. data/manual/text/registering_families.rb +27 -24
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +30 -19
  149. data/manual/text/rotation.rb +33 -24
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +56 -54
  152. data/manual/text/text_box_excess.rb +20 -17
  153. data/manual/text/text_box_extensions.rb +18 -15
  154. data/manual/text/text_box_overflow.rb +24 -17
  155. data/manual/text/utf8.rb +12 -13
  156. data/manual/text/win_ansi_charset.rb +28 -25
  157. data/prawn.gemspec +45 -50
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  160. data/spec/prawn/document/column_box_spec.rb +75 -0
  161. data/spec/prawn/document/security_spec.rb +176 -0
  162. data/spec/prawn/document_annotations_spec.rb +76 -0
  163. data/spec/prawn/document_destinations_spec.rb +15 -0
  164. data/spec/prawn/document_grid_spec.rb +99 -0
  165. data/spec/prawn/document_reference_spec.rb +27 -0
  166. data/spec/prawn/document_span_spec.rb +44 -0
  167. data/spec/prawn/document_spec.rb +805 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +544 -0
  170. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  171. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  172. data/spec/prawn/graphics_spec.rb +872 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/prawn/image_handler_spec.rb +53 -0
  175. data/spec/prawn/images/jpg_spec.rb +20 -0
  176. data/spec/prawn/images/png_spec.rb +283 -0
  177. data/spec/prawn/images_spec.rb +229 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +512 -0
  180. data/spec/prawn/repeater_spec.rb +166 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +173 -0
  183. data/spec/prawn/text/box_spec.rb +1110 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +150 -0
  190. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  191. data/spec/prawn/text_spacing_spec.rb +95 -0
  192. data/spec/prawn/text_spec.rb +603 -0
  193. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  194. data/spec/prawn/transformation_stack_spec.rb +66 -0
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +19 -25
  198. data.tar.gz.sig +0 -0
  199. metadata +113 -276
  200. metadata.gz.sig +0 -0
  201. data/data/encodings/win_ansi.txt +0 -29
  202. data/data/images/16bit.alpha +0 -0
  203. data/data/images/16bit.color +0 -0
  204. data/data/images/16bit.png +0 -0
  205. data/data/images/arrow.png +0 -0
  206. data/data/images/arrow2.png +0 -0
  207. data/data/images/dice.alpha +0 -0
  208. data/data/images/dice.color +0 -0
  209. data/data/images/dice.png +0 -0
  210. data/data/images/dice_interlaced.png +0 -0
  211. data/data/images/fractal.jpg +0 -0
  212. data/data/images/indexed_color.dat +0 -0
  213. data/data/images/indexed_color.png +0 -0
  214. data/data/images/letterhead.jpg +0 -0
  215. data/data/images/license.md +0 -8
  216. data/data/images/page_white_text.alpha +0 -0
  217. data/data/images/page_white_text.color +0 -0
  218. data/data/images/page_white_text.png +0 -0
  219. data/data/images/pigs.jpg +0 -0
  220. data/data/images/prawn.png +0 -0
  221. data/data/images/ruport.png +0 -0
  222. data/data/images/ruport_data.dat +0 -0
  223. data/data/images/ruport_transparent.png +0 -0
  224. data/data/images/ruport_type0.png +0 -0
  225. data/data/images/stef.jpg +0 -0
  226. data/data/images/tru256.bmp +0 -0
  227. data/data/images/web-links.dat +0 -1
  228. data/data/images/web-links.png +0 -0
  229. data/data/pdfs/complex_template.pdf +0 -0
  230. data/data/pdfs/contains_ttf_font.pdf +0 -0
  231. data/data/pdfs/encrypted.pdf +0 -0
  232. data/data/pdfs/form.pdf +1 -819
  233. data/data/pdfs/hexagon.pdf +0 -61
  234. data/data/pdfs/indirect_reference.pdf +0 -86
  235. data/data/pdfs/multipage_template.pdf +0 -127
  236. data/data/pdfs/nested_pages.pdf +0 -118
  237. data/data/pdfs/page_without_mediabox.pdf +0 -193
  238. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  239. data/data/pdfs/two_hexagons.pdf +0 -90
  240. data/data/pdfs/version_1_6.pdf +0 -61
  241. data/data/shift_jis_text.txt +0 -1
  242. data/lib/prawn/document/graphics_state.rb +0 -73
  243. data/lib/prawn/font/afm.rb +0 -247
  244. data/lib/prawn/table/cell/image.rb +0 -69
  245. data/lib/prawn/table/cell/in_table.rb +0 -33
  246. data/lib/prawn/table/cell/span_dummy.rb +0 -93
  247. data/lib/prawn/table/cell/subtable.rb +0 -66
  248. data/lib/prawn/table/cell/text.rb +0 -154
  249. data/lib/prawn/table/cell.rb +0 -772
  250. data/lib/prawn/table/cells.rb +0 -255
  251. data/lib/prawn/table/column_width_calculator.rb +0 -182
  252. data/lib/prawn/table.rb +0 -644
  253. data/manual/table/basic_block.rb +0 -53
  254. data/manual/table/before_rendering_page.rb +0 -26
  255. data/manual/table/cell_border_lines.rb +0 -24
  256. data/manual/table/cell_borders_and_bg.rb +0 -31
  257. data/manual/table/cell_dimensions.rb +0 -30
  258. data/manual/table/cell_text.rb +0 -38
  259. data/manual/table/column_widths.rb +0 -30
  260. data/manual/table/content_and_subtables.rb +0 -39
  261. data/manual/table/creation.rb +0 -27
  262. data/manual/table/filtering.rb +0 -36
  263. data/manual/table/flow_and_header.rb +0 -17
  264. data/manual/table/image_cells.rb +0 -33
  265. data/manual/table/position.rb +0 -29
  266. data/manual/table/row_colors.rb +0 -20
  267. data/manual/table/span.rb +0 -30
  268. data/manual/table/style.rb +0 -22
  269. data/manual/table/table.rb +0 -52
  270. data/manual/table/width.rb +0 -27
  271. data/spec/acceptance/png.rb +0 -25
  272. data/spec/annotations_spec.rb +0 -74
  273. data/spec/bounding_box_spec.rb +0 -510
  274. data/spec/cell_spec.rb +0 -629
  275. data/spec/column_box_spec.rb +0 -65
  276. data/spec/destinations_spec.rb +0 -15
  277. data/spec/document_spec.rb +0 -730
  278. data/spec/extensions/mocha.rb +0 -46
  279. data/spec/font_metric_cache_spec.rb +0 -52
  280. data/spec/font_spec.rb +0 -449
  281. data/spec/formatted_text_arranger_spec.rb +0 -421
  282. data/spec/formatted_text_box_spec.rb +0 -639
  283. data/spec/formatted_text_fragment_spec.rb +0 -298
  284. data/spec/graphics_spec.rb +0 -669
  285. data/spec/grid_spec.rb +0 -96
  286. data/spec/image_handler_spec.rb +0 -54
  287. data/spec/images_spec.rb +0 -153
  288. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  289. data/spec/jpg_spec.rb +0 -25
  290. data/spec/line_wrap_spec.rb +0 -344
  291. data/spec/measurement_units_spec.rb +0 -25
  292. data/spec/outline_spec.rb +0 -430
  293. data/spec/png_spec.rb +0 -237
  294. data/spec/reference_spec.rb +0 -25
  295. data/spec/repeater_spec.rb +0 -160
  296. data/spec/security_spec.rb +0 -158
  297. data/spec/soft_mask_spec.rb +0 -79
  298. data/spec/span_spec.rb +0 -44
  299. data/spec/stamp_spec.rb +0 -160
  300. data/spec/stroke_styles_spec.rb +0 -211
  301. data/spec/table/span_dummy_spec.rb +0 -17
  302. data/spec/table_spec.rb +0 -1527
  303. data/spec/text_at_spec.rb +0 -115
  304. data/spec/text_box_spec.rb +0 -1034
  305. data/spec/text_rendering_mode_spec.rb +0 -45
  306. data/spec/text_spacing_spec.rb +0 -93
  307. data/spec/text_spec.rb +0 -437
  308. data/spec/text_with_inline_formatting_spec.rb +0 -35
  309. data/spec/transparency_spec.rb +0 -91
@@ -1,255 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # cells.rb: Methods for accessing rows, columns, and cells of a Prawn::Table.
4
- #
5
- # Copyright December 2009, Brad Ediger. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
-
9
- module Prawn
10
- class Table
11
- # Selects the given rows (0-based) for styling. Returns a Cells object --
12
- # see the documentation on Cells for things you can do with cells.
13
- #
14
- def rows(row_spec)
15
- cells.rows(row_spec)
16
- end
17
- alias_method :row, :rows
18
-
19
- # Selects the given columns (0-based) for styling. Returns a Cells object
20
- # -- see the documentation on Cells for things you can do with cells.
21
- #
22
- def columns(col_spec)
23
- cells.columns(col_spec)
24
- end
25
- alias_method :column, :columns
26
-
27
- # Represents a selection of cells to be styled. Operations on a CellProxy
28
- # can be chained, and cell properties can be set one-for-all on the proxy.
29
- #
30
- # To set vertical borders only:
31
- #
32
- # table.cells.borders = [:left, :right]
33
- #
34
- # To highlight a rectangular area of the table:
35
- #
36
- # table.rows(1..3).columns(2..4).background_color = 'ff0000'
37
- #
38
- class Cells < Array
39
-
40
- # @group Experimental API
41
-
42
- # Limits selection to the given row or rows. +row_spec+ can be anything
43
- # that responds to the === operator selecting a set of 0-based row
44
- # numbers; most commonly a number or a range.
45
- #
46
- # table.row(0) # selects first row
47
- # table.rows(3..4) # selects rows four and five
48
- #
49
- def rows(row_spec)
50
- index_cells unless defined?(@indexed) && @indexed
51
- row_spec = transform_spec(row_spec, @first_row, @row_count)
52
- Cells.new(@rows[row_spec] ||= select { |c|
53
- row_spec.respond_to?(:include?) ?
54
- row_spec.include?(c.row) : row_spec === c.row })
55
- end
56
- alias_method :row, :rows
57
-
58
- # Returns the number of rows in the list.
59
- #
60
- def row_count
61
- index_cells unless defined?(@indexed) && @indexed
62
- @row_count
63
- end
64
-
65
- # Limits selection to the given column or columns. +col_spec+ can be
66
- # anything that responds to the === operator selecting a set of 0-based
67
- # column numbers; most commonly a number or a range.
68
- #
69
- # table.column(0) # selects first column
70
- # table.columns(3..4) # selects columns four and five
71
- #
72
- def columns(col_spec)
73
- index_cells unless defined?(@indexed) && @indexed
74
- col_spec = transform_spec(col_spec, @first_column, @column_count)
75
- Cells.new(@columns[col_spec] ||= select { |c|
76
- col_spec.respond_to?(:include?) ?
77
- col_spec.include?(c.column) : col_spec === c.column })
78
- end
79
- alias_method :column, :columns
80
-
81
- # Returns the number of columns in the list.
82
- #
83
- def column_count
84
- index_cells unless defined?(@indexed) && @indexed
85
- @column_count
86
- end
87
-
88
- # Allows you to filter the given cells by arbitrary properties.
89
- #
90
- # table.column(4).filter { |cell| cell.content =~ /Yes/ }.
91
- # background_color = '00ff00'
92
- #
93
- def filter(&block)
94
- Cells.new(select(&block))
95
- end
96
-
97
- # Retrieves a cell based on its 0-based row and column. Returns an
98
- # individual Cell, not a Cells collection.
99
- #
100
- # table.cells[0, 0].content # => "First cell content"
101
- #
102
- def [](row, col)
103
- return nil if empty?
104
- index_cells unless defined?(@indexed) && @indexed
105
- row_array, col_array = @rows[@first_row + row] || [], @columns[@first_column + col] || []
106
- if row_array.length < col_array.length
107
- row_array.find { |c| c.column == @first_column + col }
108
- else
109
- col_array.find { |c| c.row == @first_row + row }
110
- end
111
- end
112
-
113
- # Puts a cell in the collection at the given position. Internal use only.
114
- #
115
- def []=(row, col, cell) # :nodoc:
116
- cell.extend(Cell::InTable)
117
- cell.row = row
118
- cell.column = col
119
-
120
- if defined?(@indexed) && @indexed
121
- (@rows[row] ||= []) << cell
122
- (@columns[col] ||= []) << cell
123
- @first_row = row if !@first_row || row < @first_row
124
- @first_column = col if !@first_column || col < @first_column
125
- @row_count = @rows.size
126
- @column_count = @columns.size
127
- end
128
-
129
- self << cell
130
- end
131
-
132
- # Supports setting multiple properties at once.
133
- #
134
- # table.cells.style(:padding => 0, :border_width => 2)
135
- #
136
- # is the same as:
137
- #
138
- # table.cells.padding = 0
139
- # table.cells.border_width = 2
140
- #
141
- # You can also pass a block, which will be called for each cell in turn.
142
- # This allows you to set more complicated properties:
143
- #
144
- # table.cells.style { |cell| cell.border_width += 12 }
145
- #
146
- def style(options={}, &block)
147
- each do |cell|
148
- next if cell.is_a?(Cell::SpanDummy)
149
- cell.style(options, &block)
150
- end
151
- end
152
-
153
- # Returns the total width of all columns in the selected set.
154
- #
155
- def width
156
- widths = {}
157
- each do |cell|
158
- per_cell_width = cell.width_ignoring_span.to_f / cell.colspan
159
- cell.colspan.times do |n|
160
- widths[cell.column+n] = [widths[cell.column+n], per_cell_width].
161
- compact.max
162
- end
163
- end
164
- widths.values.inject(0, &:+)
165
- end
166
-
167
- # Returns minimum width required to contain cells in the set.
168
- #
169
- def min_width
170
- aggregate_cell_values(:column, :avg_spanned_min_width, :max)
171
- end
172
-
173
- # Returns maximum width that can contain cells in the set.
174
- #
175
- def max_width
176
- aggregate_cell_values(:column, :max_width_ignoring_span, :max)
177
- end
178
-
179
- # Returns the total height of all rows in the selected set.
180
- #
181
- def height
182
- aggregate_cell_values(:row, :height_ignoring_span, :max)
183
- end
184
-
185
- # Supports setting arbitrary properties on a group of cells.
186
- #
187
- # table.cells.row(3..6).background_color = 'cc0000'
188
- #
189
- def method_missing(id, *args, &block)
190
- if id.to_s =~ /=\z/
191
- each { |c| c.send(id, *args, &block) if c.respond_to?(id) }
192
- else
193
- super
194
- end
195
- end
196
-
197
- protected
198
-
199
- # Defers indexing until rows() or columns() is actually called on the
200
- # Cells object. Without this, we would needlessly index the leaf nodes of
201
- # the object graph, the ones that are only there to be iterated over.
202
- #
203
- # Make sure to call this before using @rows or @columns.
204
- #
205
- def index_cells
206
- @rows = {}
207
- @columns = {}
208
-
209
- each do |cell|
210
- @rows[cell.row] ||= []
211
- @rows[cell.row] << cell
212
-
213
- @columns[cell.column] ||= []
214
- @columns[cell.column] << cell
215
- end
216
-
217
- @first_row = @rows.keys.min
218
- @first_column = @columns.keys.min
219
-
220
- @row_count = @rows.size
221
- @column_count = @columns.size
222
-
223
- @indexed = true
224
- end
225
-
226
- # Sum up a min/max value over rows or columns in the cells selected.
227
- # Takes the min/max (per +aggregate+) of the result of sending +meth+ to
228
- # each cell, grouped by +row_or_column+.
229
- #
230
- def aggregate_cell_values(row_or_column, meth, aggregate)
231
- ColumnWidthCalculator.new(self).aggregate_cell_values(row_or_column, meth, aggregate)
232
- end
233
-
234
- # Transforms +spec+, a column / row specification, into an object that
235
- # can be compared against a row or column number using ===. Normalizes
236
- # negative indices to be positive, given a total size of +total+. The
237
- # first row/column is indicated by +first+; this value is considered row
238
- # or column 0.
239
- #
240
- def transform_spec(spec, first, total)
241
- case spec
242
- when Range
243
- transform_spec(spec.begin, first, total) ..
244
- transform_spec(spec.end, first, total)
245
- when Integer
246
- spec < 0 ? (first + total + spec) : first + spec
247
- when Enumerable
248
- spec.map { |x| first + x }
249
- else # pass through
250
- raise "Don't understand spec #{spec.inspect}"
251
- end
252
- end
253
- end
254
- end
255
- end
@@ -1,182 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Prawn
4
- class Table
5
- # @private
6
- class ColumnWidthCalculator
7
- def initialize(cells)
8
- @cells = cells
9
-
10
- @widths_by_column = Hash.new(0)
11
- @rows_with_a_span_dummy = Hash.new(false)
12
-
13
- #calculate for each row if it includes a Cell:SpanDummy
14
- @cells.each do |cell|
15
- @rows_with_a_span_dummy[cell.row] = true if cell.is_a?(Cell::SpanDummy)
16
- end
17
- end
18
-
19
- # does this row include a Cell:SpanDummy?
20
- #
21
- # @param row - the row that should be checked for Cell:SpanDummy elements
22
- #
23
- def has_a_span_dummy?(row)
24
- @rows_with_a_span_dummy[row]
25
- end
26
-
27
- # helper method
28
- # column widths are stored in the values array
29
- # a cell may span cells whose value is only partly given
30
- # this function handles this special case
31
- #
32
- # @param values - The columns widths calculated up until now
33
- # @param cell - The current cell
34
- # @param index - The current column
35
- # @param meth - Meth (min/max); used to calculate values to be filled
36
- #
37
- def fill_values_if_needed(values, cell, index, meth)
38
- #have all spanned indices been filled with a value?
39
- #e.g. values[0], values[1] and values[2] don't return nil given a index of 0 and a colspan of 3
40
- number_of_nil_values = 0
41
- cell.colspan.times do |i|
42
- number_of_nil_values += 1 if values[index+i].nil?
43
- end
44
-
45
- #nothing to do? because
46
- #a) all values are filled
47
- return values if number_of_nil_values == 0
48
- #b) no values are filled
49
- return values if number_of_nil_values == cell.colspan
50
- #c) I am not sure why this line is needed FIXXME
51
- #some test cases manage to this line even though there is no dummy cell in the row
52
- #I'm not sure if this is a sign for a further underlying bug.
53
- return values unless has_a_span_dummy?(cell.row)
54
- #fill up the values array
55
-
56
- #calculate the new sum
57
- new_sum = cell.send(meth) * cell.colspan
58
- #substract any calculated values
59
- cell.colspan.times do |i|
60
- new_sum -= values[index+i] unless values[index+i].nil?
61
- end
62
-
63
- #calculate value for the remaining - not yet filled - cells.
64
- new_value = new_sum.to_f / number_of_nil_values
65
- #fill the not yet filled cells
66
- cell.colspan.times do |i|
67
- values[index+i] = new_value if values[index+i].nil?
68
- end
69
- return values
70
- end
71
-
72
- def natural_widths
73
- #calculate natural column width for all rows that do not include a span dummy
74
- @cells.each do |cell|
75
- unless has_a_span_dummy?(cell.row)
76
- @widths_by_column[cell.column] =
77
- [@widths_by_column[cell.column], cell.width.to_f].max
78
- end
79
- end
80
-
81
- #integrate natural column widths for all rows that do include a span dummy
82
- @cells.each do |cell|
83
- next unless has_a_span_dummy?(cell.row)
84
- #the width of a SpanDummy cell will be calculated by the "mother" cell
85
- next if cell.is_a?(Cell::SpanDummy)
86
-
87
- if cell.colspan == 1
88
- @widths_by_column[cell.column] =
89
- [@widths_by_column[cell.column], cell.width.to_f].max
90
- else
91
- #calculate the current with of all cells that will be spanned by the current cell
92
- current_width_of_spanned_cells =
93
- @widths_by_column.to_a[cell.column..(cell.column + cell.colspan - 1)]
94
- .collect{|key, value| value}.inject(0, :+)
95
-
96
- #update the Hash only if the new with is at least equal to the old one
97
- #due to arithmetic errors we need to ignore a small difference in the new and the old sum
98
- #the same had to be done in the column_widht_calculator#natural_width
99
- update_hash = ((cell.width.to_f - current_width_of_spanned_cells) >
100
- Prawn::FLOAT_PRECISION)
101
-
102
- if update_hash
103
- # Split the width of colspanned cells evenly by columns
104
- width_per_column = cell.width.to_f / cell.colspan
105
- # Update the Hash
106
- cell.colspan.times do |i|
107
- @widths_by_column[cell.column + i] = width_per_column
108
- end
109
- end
110
- end
111
- end
112
-
113
- @widths_by_column.sort_by { |col, _| col }.map { |_, w| w }
114
- end
115
-
116
- # get column widths (either min or max depending on meth)
117
- # used in cells.rb
118
- #
119
- # @param row_or_column - you may call this on either rows or columns
120
- # @param meth - min/max
121
- # @param aggregate - functions from cell.rb to be used to aggregate e.g. avg_spanned_min_width
122
- #
123
- def aggregate_cell_values(row_or_column, meth, aggregate)
124
- values = {}
125
-
126
- #calculate values for all cells that do not span accross multiple cells
127
- #this ensures that we don't have a problem if the first line includes
128
- #a cell that spans across multiple cells
129
- @cells.each do |cell|
130
- #don't take spanned cells
131
- if cell.colspan == 1 and cell.class != Prawn::Table::Cell::SpanDummy
132
- index = cell.send(row_or_column)
133
- values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
134
- end
135
- end
136
-
137
- # if there are only colspanned or rowspanned cells in a table
138
- spanned_width_needs_fixing = true
139
-
140
- @cells.each do |cell|
141
- index = cell.send(row_or_column)
142
- if cell.colspan > 1
143
- #special treatment if some but not all spanned indices in the values array have been calculated
144
- #only applies to rows
145
- values = fill_values_if_needed(values, cell, index, meth) if row_or_column == :column
146
- #calculate current (old) return value before we do anything
147
- old_sum = 0
148
- cell.colspan.times { |i|
149
- old_sum += values[index+i] unless values[index+i].nil?
150
- }
151
-
152
- #calculate future return value
153
- new_sum = cell.send(meth) * cell.colspan
154
-
155
- #due to float rounding errors we need to ignore a small difference in the new
156
- #and the old sum the same had to be done in
157
- #the column_width_calculator#natural_width
158
- spanned_width_needs_fixing = ((new_sum - old_sum) > Prawn::FLOAT_PRECISION)
159
-
160
- if spanned_width_needs_fixing
161
- #not entirely sure why we need this line, but with it the tests pass
162
- values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
163
- #overwrite the old values with the new ones, but only if all entries existed
164
- entries_exist = true
165
- cell.colspan.times { |i| entries_exist = false if values[index+i].nil? }
166
- cell.colspan.times { |i|
167
- values[index+i] = cell.send(meth) if entries_exist
168
- }
169
- end
170
- else
171
- if spanned_width_needs_fixing && cell.class == Prawn::Table::Cell::SpanDummy
172
- values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
173
- end
174
- end
175
- end
176
-
177
- return values.values.inject(0, &:+)
178
- end
179
- end
180
-
181
- end
182
- end