prawn 0.13.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 (348) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +10 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -16
  6. data/Rakefile +17 -39
  7. data/lib/prawn/document/bounding_box.rb +85 -42
  8. data/lib/prawn/document/column_box.rb +21 -11
  9. data/lib/prawn/document/internals.rb +40 -147
  10. data/lib/prawn/document/span.rb +25 -17
  11. data/lib/prawn/document.rb +286 -245
  12. data/lib/prawn/encoding.rb +68 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +204 -155
  15. data/lib/prawn/font_metric_cache.rb +25 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +7 -13
  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 +142 -80
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +6 -5
  23. data/lib/prawn/graphics/color.rb +47 -44
  24. data/lib/prawn/graphics/dash.rb +30 -13
  25. data/lib/prawn/graphics/join_style.rb +13 -6
  26. data/lib/prawn/graphics/patterns.rb +221 -90
  27. data/lib/prawn/graphics/transformation.rb +21 -12
  28. data/lib/prawn/graphics/transparency.rb +21 -17
  29. data/lib/prawn/graphics.rb +155 -128
  30. data/lib/prawn/{layout/grid.rb → grid.rb} +110 -47
  31. data/lib/prawn/image_handler.rb +16 -2
  32. data/lib/prawn/images/image.rb +4 -2
  33. data/lib/prawn/images/jpg.rb +39 -30
  34. data/lib/prawn/images/png.rb +132 -169
  35. data/lib/prawn/images.rb +70 -62
  36. data/lib/prawn/measurement_extensions.rb +15 -10
  37. data/lib/prawn/measurements.rb +22 -23
  38. data/lib/prawn/outline.rb +301 -13
  39. data/lib/prawn/repeater.rb +19 -17
  40. data/lib/prawn/security/arcfour.rb +54 -0
  41. data/lib/prawn/security.rb +108 -86
  42. data/lib/prawn/soft_mask.rb +40 -41
  43. data/lib/prawn/stamp.rb +29 -12
  44. data/lib/prawn/text/box.rb +27 -29
  45. data/lib/prawn/text/formatted/arranger.rb +110 -67
  46. data/lib/prawn/text/formatted/box.rb +233 -165
  47. data/lib/prawn/text/formatted/fragment.rb +27 -27
  48. data/lib/prawn/text/formatted/line_wrap.rb +137 -97
  49. data/lib/prawn/text/formatted/parser.rb +149 -127
  50. data/lib/prawn/text/formatted/wrap.rb +57 -37
  51. data/lib/prawn/text/formatted.rb +6 -4
  52. data/lib/prawn/text.rb +105 -73
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +11 -21
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +42 -68
  58. data/{data/images/fractal.jpg → manual/absolute_position.pdf} +0 -0
  59. data/manual/basic_concepts/adding_pages.rb +9 -10
  60. data/manual/basic_concepts/basic_concepts.rb +33 -24
  61. data/manual/basic_concepts/creation.rb +10 -11
  62. data/manual/basic_concepts/cursor.rb +9 -10
  63. data/manual/basic_concepts/measurement.rb +10 -11
  64. data/manual/basic_concepts/origin.rb +8 -9
  65. data/manual/basic_concepts/other_cursor_helpers.rb +17 -18
  66. data/manual/basic_concepts/view.rb +48 -0
  67. data/manual/bounding_box/bounding_box.rb +31 -29
  68. data/manual/bounding_box/bounds.rb +17 -18
  69. data/manual/bounding_box/canvas.rb +8 -9
  70. data/manual/bounding_box/creation.rb +8 -9
  71. data/manual/bounding_box/indentation.rb +22 -23
  72. data/manual/bounding_box/nesting.rb +32 -25
  73. data/manual/bounding_box/russian_boxes.rb +19 -19
  74. data/manual/bounding_box/stretchy.rb +18 -20
  75. data/manual/contents.rb +35 -0
  76. data/manual/cover.rb +43 -0
  77. data/manual/document_and_page_options/background.rb +16 -14
  78. data/manual/document_and_page_options/document_and_page_options.rb +26 -23
  79. data/manual/document_and_page_options/metadata.rb +21 -19
  80. data/manual/document_and_page_options/page_margins.rb +20 -22
  81. data/manual/document_and_page_options/page_size.rb +15 -15
  82. data/manual/document_and_page_options/print_scaling.rb +23 -0
  83. data/manual/example_helper.rb +5 -408
  84. data/manual/graphics/blend_mode.rb +52 -0
  85. data/manual/graphics/circle_and_ellipse.rb +8 -9
  86. data/manual/graphics/color.rb +11 -13
  87. data/manual/graphics/common_lines.rb +13 -12
  88. data/manual/graphics/fill_and_stroke.rb +10 -11
  89. data/manual/graphics/fill_rules.rb +13 -12
  90. data/manual/graphics/gradients.rb +28 -22
  91. data/manual/graphics/graphics.rb +52 -46
  92. data/manual/graphics/helper.rb +20 -10
  93. data/manual/graphics/line_width.rb +13 -12
  94. data/manual/graphics/lines_and_curves.rb +13 -14
  95. data/manual/graphics/polygon.rb +10 -12
  96. data/manual/graphics/rectangle.rb +7 -8
  97. data/manual/graphics/rotate.rb +9 -12
  98. data/manual/graphics/scale.rb +19 -18
  99. data/manual/graphics/soft_masks.rb +5 -7
  100. data/manual/graphics/stroke_cap.rb +10 -11
  101. data/manual/graphics/stroke_dash.rb +16 -17
  102. data/manual/graphics/stroke_join.rb +10 -11
  103. data/manual/graphics/translate.rb +13 -13
  104. data/manual/graphics/transparency.rb +11 -13
  105. data/manual/{manual/how_to_read_this_manual.rb → how_to_read_this_manual.rb} +23 -25
  106. data/manual/images/absolute_position.rb +9 -10
  107. data/manual/images/fit.rb +9 -10
  108. data/manual/images/horizontal.rb +13 -14
  109. data/manual/images/images.rb +31 -30
  110. data/manual/images/plain_image.rb +6 -7
  111. data/manual/images/scale.rb +12 -13
  112. data/manual/images/vertical.rb +19 -17
  113. data/manual/images/width_and_height.rb +13 -14
  114. data/manual/layout/boxes.rb +14 -15
  115. data/manual/layout/content.rb +12 -13
  116. data/manual/layout/layout.rb +19 -20
  117. data/manual/layout/simple_grid.rb +8 -9
  118. data/manual/outline/add_subsection_to.rb +26 -27
  119. data/manual/outline/insert_section_after.rb +19 -20
  120. data/manual/outline/outline.rb +23 -22
  121. data/manual/outline/sections_and_pages.rb +24 -25
  122. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  123. data/manual/repeatable_content/page_numbering.rb +20 -19
  124. data/manual/repeatable_content/repeatable_content.rb +26 -22
  125. data/manual/repeatable_content/repeater.rb +18 -19
  126. data/manual/repeatable_content/stamp.rb +18 -19
  127. data/manual/security/encryption.rb +8 -11
  128. data/manual/security/permissions.rb +20 -15
  129. data/manual/security/security.rb +20 -20
  130. data/manual/table.rb +16 -0
  131. data/manual/text/alignment.rb +17 -18
  132. data/manual/text/color.rb +13 -13
  133. data/manual/text/column_box.rb +10 -12
  134. data/manual/text/fallback_fonts.rb +29 -25
  135. data/manual/text/font.rb +17 -18
  136. data/manual/text/font_size.rb +21 -22
  137. data/manual/text/font_style.rb +12 -10
  138. data/manual/text/formatted_callbacks.rb +36 -26
  139. data/manual/text/formatted_text.rb +41 -34
  140. data/manual/text/free_flowing_text.rb +28 -29
  141. data/manual/text/inline.rb +23 -26
  142. data/manual/text/kerning_and_character_spacing.rb +20 -21
  143. data/manual/text/leading.rb +10 -11
  144. data/manual/text/line_wrapping.rb +40 -21
  145. data/manual/text/paragraph_indentation.rb +17 -12
  146. data/manual/text/positioned_text.rb +19 -20
  147. data/manual/text/registering_families.rb +33 -30
  148. data/manual/text/rendering_and_color.rb +11 -12
  149. data/manual/text/right_to_left_text.rb +31 -20
  150. data/manual/text/rotation.rb +36 -27
  151. data/manual/text/single_usage.rb +13 -14
  152. data/manual/text/text.rb +62 -62
  153. data/manual/text/text_box_excess.rb +22 -19
  154. data/manual/text/text_box_extensions.rb +21 -18
  155. data/manual/text/text_box_overflow.rb +28 -21
  156. data/manual/text/utf8.rb +16 -17
  157. data/manual/text/win_ansi_charset.rb +29 -26
  158. data/prawn.gemspec +45 -43
  159. data/spec/extensions/encoding_helpers.rb +4 -3
  160. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  161. data/spec/prawn/document/column_box_spec.rb +75 -0
  162. data/spec/prawn/document/security_spec.rb +176 -0
  163. data/spec/prawn/document_annotations_spec.rb +76 -0
  164. data/spec/prawn/document_destinations_spec.rb +15 -0
  165. data/spec/prawn/document_grid_spec.rb +99 -0
  166. data/spec/prawn/document_reference_spec.rb +27 -0
  167. data/spec/prawn/document_span_spec.rb +44 -0
  168. data/spec/prawn/document_spec.rb +805 -0
  169. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  170. data/spec/prawn/font_spec.rb +544 -0
  171. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  172. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  173. data/spec/prawn/graphics_spec.rb +872 -0
  174. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  175. data/spec/prawn/image_handler_spec.rb +53 -0
  176. data/spec/prawn/images/jpg_spec.rb +20 -0
  177. data/spec/prawn/images/png_spec.rb +283 -0
  178. data/spec/prawn/images_spec.rb +229 -0
  179. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  180. data/spec/prawn/outline_spec.rb +512 -0
  181. data/spec/prawn/repeater_spec.rb +166 -0
  182. data/spec/prawn/soft_mask_spec.rb +74 -0
  183. data/spec/prawn/stamp_spec.rb +173 -0
  184. data/spec/prawn/text/box_spec.rb +1110 -0
  185. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  186. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  187. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  188. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  189. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  190. data/spec/prawn/text_draw_text_spec.rb +150 -0
  191. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  192. data/spec/prawn/text_spacing_spec.rb +95 -0
  193. data/spec/prawn/text_spec.rb +603 -0
  194. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  195. data/spec/prawn/transformation_stack_spec.rb +66 -0
  196. data/spec/prawn/view_spec.rb +63 -0
  197. data/spec/prawn_manual_spec.rb +35 -0
  198. data/spec/spec_helper.rb +22 -21
  199. data.tar.gz.sig +0 -0
  200. metadata +168 -307
  201. metadata.gz.sig +0 -0
  202. data/README.md +0 -109
  203. data/data/encodings/win_ansi.txt +0 -29
  204. data/data/images/16bit.alpha +0 -0
  205. data/data/images/16bit.dat +0 -0
  206. data/data/images/16bit.png +0 -0
  207. data/data/images/arrow.png +0 -0
  208. data/data/images/arrow2.png +0 -0
  209. data/data/images/barcode_issue.png +0 -0
  210. data/data/images/dice.alpha +0 -0
  211. data/data/images/dice.dat +0 -0
  212. data/data/images/dice.png +0 -0
  213. data/data/images/dice_interlaced.png +0 -0
  214. data/data/images/indexed_color.dat +0 -0
  215. data/data/images/indexed_color.png +0 -0
  216. data/data/images/letterhead.jpg +0 -0
  217. data/data/images/page_white_text.alpha +0 -0
  218. data/data/images/page_white_text.dat +0 -0
  219. data/data/images/page_white_text.png +0 -0
  220. data/data/images/pigs.jpg +0 -0
  221. data/data/images/prawn.png +0 -0
  222. data/data/images/ruport.png +0 -0
  223. data/data/images/ruport_data.dat +0 -0
  224. data/data/images/ruport_transparent.png +0 -0
  225. data/data/images/ruport_type0.png +0 -0
  226. data/data/images/stef.jpg +0 -0
  227. data/data/images/tru256.bmp +0 -0
  228. data/data/images/web-links.dat +0 -1
  229. data/data/images/web-links.png +0 -0
  230. data/data/pdfs/complex_template.pdf +0 -0
  231. data/data/pdfs/contains_ttf_font.pdf +0 -0
  232. data/data/pdfs/encrypted.pdf +0 -0
  233. data/data/pdfs/form.pdf +1 -819
  234. data/data/pdfs/hexagon.pdf +0 -61
  235. data/data/pdfs/indirect_reference.pdf +0 -86
  236. data/data/pdfs/multipage_template.pdf +0 -127
  237. data/data/pdfs/nested_pages.pdf +0 -118
  238. data/data/pdfs/page_without_mediabox.pdf +0 -193
  239. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  240. data/data/pdfs/two_hexagons.pdf +0 -90
  241. data/data/pdfs/version_1_6.pdf +0 -61
  242. data/data/shift_jis_text.txt +0 -1
  243. data/lib/pdf/core/annotations.rb +0 -60
  244. data/lib/pdf/core/byte_string.rb +0 -9
  245. data/lib/pdf/core/destinations.rb +0 -90
  246. data/lib/pdf/core/document_state.rb +0 -78
  247. data/lib/pdf/core/filter_list.rb +0 -51
  248. data/lib/pdf/core/filters.rb +0 -36
  249. data/lib/pdf/core/graphics_state.rb +0 -68
  250. data/lib/pdf/core/literal_string.rb +0 -16
  251. data/lib/pdf/core/name_tree.rb +0 -177
  252. data/lib/pdf/core/object_store.rb +0 -320
  253. data/lib/pdf/core/outline.rb +0 -315
  254. data/lib/pdf/core/page.rb +0 -212
  255. data/lib/pdf/core/page_geometry.rb +0 -126
  256. data/lib/pdf/core/pdf_object.rb +0 -124
  257. data/lib/pdf/core/reference.rb +0 -103
  258. data/lib/pdf/core/stream.rb +0 -98
  259. data/lib/pdf/core/text.rb +0 -275
  260. data/lib/pdf/core.rb +0 -35
  261. data/lib/prawn/compatibility.rb +0 -91
  262. data/lib/prawn/document/graphics_state.rb +0 -73
  263. data/lib/prawn/document/snapshot.rb +0 -89
  264. data/lib/prawn/font/afm.rb +0 -203
  265. data/lib/prawn/layout.rb +0 -20
  266. data/lib/prawn/table/cell/image.rb +0 -70
  267. data/lib/prawn/table/cell/in_table.rb +0 -27
  268. data/lib/prawn/table/cell/span_dummy.rb +0 -92
  269. data/lib/prawn/table/cell/subtable.rb +0 -65
  270. data/lib/prawn/table/cell/text.rb +0 -153
  271. data/lib/prawn/table/cell.rb +0 -770
  272. data/lib/prawn/table/cells.rb +0 -295
  273. data/lib/prawn/table.rb +0 -643
  274. data/manual/example_file.rb +0 -116
  275. data/manual/example_package.rb +0 -53
  276. data/manual/example_section.rb +0 -46
  277. data/manual/manual/cover.rb +0 -35
  278. data/manual/manual/foreword.rb +0 -85
  279. data/manual/manual/manual.rb +0 -35
  280. data/manual/syntax_highlight.rb +0 -52
  281. data/manual/table/basic_block.rb +0 -53
  282. data/manual/table/before_rendering_page.rb +0 -26
  283. data/manual/table/cell_border_lines.rb +0 -24
  284. data/manual/table/cell_borders_and_bg.rb +0 -31
  285. data/manual/table/cell_dimensions.rb +0 -30
  286. data/manual/table/cell_text.rb +0 -38
  287. data/manual/table/column_widths.rb +0 -30
  288. data/manual/table/content_and_subtables.rb +0 -39
  289. data/manual/table/creation.rb +0 -27
  290. data/manual/table/filtering.rb +0 -36
  291. data/manual/table/flow_and_header.rb +0 -17
  292. data/manual/table/image_cells.rb +0 -33
  293. data/manual/table/position.rb +0 -29
  294. data/manual/table/row_colors.rb +0 -20
  295. data/manual/table/span.rb +0 -30
  296. data/manual/table/style.rb +0 -22
  297. data/manual/table/table.rb +0 -52
  298. data/manual/table/width.rb +0 -27
  299. data/manual/templates/full_template.rb +0 -25
  300. data/manual/templates/page_template.rb +0 -48
  301. data/manual/templates/templates.rb +0 -27
  302. data/manual/text/group.rb +0 -29
  303. data/spec/acceptance/png.rb +0 -23
  304. data/spec/annotations_spec.rb +0 -74
  305. data/spec/bounding_box_spec.rb +0 -493
  306. data/spec/cell_spec.rb +0 -628
  307. data/spec/column_box_spec.rb +0 -33
  308. data/spec/destinations_spec.rb +0 -15
  309. data/spec/document_spec.rb +0 -761
  310. data/spec/extensions/mocha.rb +0 -44
  311. data/spec/filters_spec.rb +0 -34
  312. data/spec/font_metric_cache_spec.rb +0 -52
  313. data/spec/font_spec.rb +0 -464
  314. data/spec/formatted_text_arranger_spec.rb +0 -421
  315. data/spec/formatted_text_box_spec.rb +0 -650
  316. data/spec/formatted_text_fragment_spec.rb +0 -298
  317. data/spec/graphics_spec.rb +0 -651
  318. data/spec/grid_spec.rb +0 -85
  319. data/spec/image_handler_spec.rb +0 -42
  320. data/spec/images_spec.rb +0 -157
  321. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  322. data/spec/jpg_spec.rb +0 -25
  323. data/spec/line_wrap_spec.rb +0 -333
  324. data/spec/measurement_units_spec.rb +0 -23
  325. data/spec/name_tree_spec.rb +0 -112
  326. data/spec/object_store_spec.rb +0 -170
  327. data/spec/outline_spec.rb +0 -448
  328. data/spec/pdf_object_spec.rb +0 -172
  329. data/spec/png_spec.rb +0 -240
  330. data/spec/reference_spec.rb +0 -82
  331. data/spec/repeater_spec.rb +0 -158
  332. data/spec/security_spec.rb +0 -158
  333. data/spec/snapshot_spec.rb +0 -186
  334. data/spec/soft_mask_spec.rb +0 -117
  335. data/spec/span_spec.rb +0 -44
  336. data/spec/stamp_spec.rb +0 -158
  337. data/spec/stream_spec.rb +0 -58
  338. data/spec/stroke_styles_spec.rb +0 -211
  339. data/spec/table/span_dummy_spec.rb +0 -17
  340. data/spec/table_spec.rb +0 -1355
  341. data/spec/template_spec.rb +0 -351
  342. data/spec/text_at_spec.rb +0 -130
  343. data/spec/text_box_spec.rb +0 -1030
  344. data/spec/text_rendering_mode_spec.rb +0 -45
  345. data/spec/text_spacing_spec.rb +0 -93
  346. data/spec/text_spec.rb +0 -425
  347. data/spec/text_with_inline_formatting_spec.rb +0 -35
  348. data/spec/transparency_spec.rb +0 -89
@@ -1,770 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # cell.rb: Table cell drawing.
4
- #
5
- # Copyright December 2009, Gregory Brown and Brad Ediger. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
-
9
- require 'date'
10
- module Prawn
11
- class Document
12
-
13
- # Instantiates and draws a cell on the document.
14
- #
15
- # cell(:content => "Hello world!", :at => [12, 34])
16
- #
17
- # See Prawn::Table::Cell.make for full options.
18
- #
19
- def cell(options={})
20
- cell = Table::Cell.make(self, options.delete(:content), options)
21
- cell.draw
22
- cell
23
- end
24
-
25
- # Set up, but do not draw, a cell. Useful for creating cells with
26
- # formatting options to be inserted into a Table. Call +draw+ on the
27
- # resulting Cell to ink it.
28
- #
29
- # See the documentation on Prawn::Cell for details on the arguments.
30
- #
31
- def make_cell(content, options={})
32
- Prawn::Table::Cell.make(self, content, options)
33
- end
34
-
35
- end
36
-
37
- class Table
38
-
39
- # A Cell is a rectangular area of the page into which content is drawn. It
40
- # has a framework for sizing itself and adding padding and simple styling.
41
- # There are several standard Cell subclasses that handle things like text,
42
- # Tables, and (in the future) stamps, images, and arbitrary content.
43
- #
44
- # Cells are a basic building block for table support (see Prawn::Table).
45
- #
46
- # Please subclass me if you want new content types! I'm designed to be very
47
- # extensible. See the different standard Cell subclasses in
48
- # lib/prawn/table/cell/*.rb for a template.
49
- #
50
- class Cell
51
-
52
- # Amount of dead space (in PDF points) inside the borders but outside the
53
- # content. Padding defaults to 5pt.
54
- #
55
- attr_reader :padding
56
-
57
- # If provided, the minimum width that this cell in its column will permit.
58
- #
59
- def min_width_ignoring_span
60
- set_width_constraints
61
- @min_width
62
- end
63
-
64
- # Minimum width of the entire span group this cell controls.
65
- #
66
- def min_width
67
- return min_width_ignoring_span if @colspan == 1
68
-
69
- # Sum up the largest min-width from each column, including myself.
70
- min_widths = Hash.new(0)
71
- dummy_cells.each do |cell|
72
- min_widths[cell.column] =
73
- [min_widths[cell.column], cell.min_width].max
74
- end
75
- min_widths[column] = [min_widths[column], min_width_ignoring_span].max
76
- min_widths.values.inject(0, &:+)
77
- end
78
-
79
- # Min-width of the span divided by the number of columns.
80
- #
81
- def avg_spanned_min_width
82
- min_width.to_f / colspan
83
- end
84
-
85
- # If provided, the maximum width that this cell can be drawn in, within
86
- # its column.
87
- #
88
- def max_width_ignoring_span
89
- set_width_constraints
90
- @max_width
91
- end
92
-
93
- # Maximum width of the entire span group this cell controls.
94
- #
95
- def max_width
96
- return max_width_ignoring_span if @colspan == 1
97
-
98
- # Sum the smallest max-width from each column in the group, including
99
- # myself.
100
- max_widths = Hash.new(0)
101
- dummy_cells.each do |cell|
102
- max_widths[cell.column] =
103
- [max_widths[cell.column], cell.max_width].min
104
- end
105
- max_widths[column] = [max_widths[column], max_width_ignoring_span].min
106
- max_widths.values.inject(0, &:+)
107
- end
108
-
109
- # Manually specify the cell's height.
110
- #
111
- attr_writer :height
112
-
113
- # Specifies which borders to enable. Must be an array of zero or more of:
114
- # <tt>[:left, :right, :top, :bottom]</tt>.
115
- #
116
- attr_accessor :borders
117
-
118
- # Width, in PDF points, of the cell's borders: [top, right, bottom, left].
119
- #
120
- attr_reader :border_widths
121
-
122
- # HTML RGB-format ("ccffff") border colors: [top, right, bottom, left].
123
- #
124
- attr_reader :border_colors
125
-
126
- # Line style
127
- #
128
- attr_reader :border_lines
129
-
130
- # Specifies the content for the cell. Must be a "cellable" object. See the
131
- # "Data" section of the Prawn::Table documentation for details on cellable
132
- # objects.
133
- #
134
- attr_accessor :content
135
-
136
- # The background color, if any, for this cell. Specified in HTML RGB
137
- # format, e.g., "ccffff". The background is drawn under the whole cell,
138
- # including any padding.
139
- #
140
- attr_accessor :background_color
141
-
142
- # Number of columns this cell spans. Defaults to 1.
143
- #
144
- attr_reader :colspan
145
-
146
- # Number of rows this cell spans. Defaults to 1.
147
- #
148
- attr_reader :rowspan
149
-
150
- # Array of SpanDummy cells (if any) that represent the other cells in
151
- # this span group. They know their own width / height, but do not draw
152
- # anything.
153
- #
154
- attr_reader :dummy_cells # :nodoc:
155
-
156
- # Instantiates a Cell based on the given options. The particular class of
157
- # cell returned depends on the :content argument. See the Prawn::Table
158
- # documentation under "Data" for allowable content types.
159
- #
160
- def self.make(pdf, content, options={})
161
- at = options.delete(:at) || [0, pdf.cursor]
162
- content = content.to_s if content.nil? || content.kind_of?(Numeric) ||
163
- content.kind_of?(Date)
164
-
165
- if content.is_a?(Hash)
166
- if content[:image]
167
- return Cell::Image.new(pdf, at, content)
168
- end
169
- options.update(content)
170
- content = options[:content]
171
- else
172
- options[:content] = content
173
- end
174
-
175
- options[:content] = content = "" if content.nil?
176
-
177
- case content
178
- when Prawn::Table::Cell
179
- content
180
- when String
181
- Cell::Text.new(pdf, at, options)
182
- when Prawn::Table
183
- Cell::Subtable.new(pdf, at, options)
184
- when Array
185
- subtable = Prawn::Table.new(options[:content], pdf, {})
186
- Cell::Subtable.new(pdf, at, options.merge(:content => subtable))
187
- else
188
- raise Errors::UnrecognizedTableContent
189
- end
190
- end
191
-
192
- # A small amount added to the bounding box width to cover over floating-
193
- # point errors when round-tripping from content_width to width and back.
194
- # This does not change cell positioning; it only slightly expands each
195
- # cell's bounding box width so that rounding error does not prevent a cell
196
- # from rendering.
197
- #
198
- FPTolerance = 1
199
-
200
- # Sets up a cell on the document +pdf+, at the given x/y location +point+,
201
- # with the given +options+. Cell, like Table, follows the "options set
202
- # accessors" paradigm (see "Options" under the Table documentation), so
203
- # any cell accessor <tt>cell.foo = :bar</tt> can be set by providing the
204
- # option <tt>:foo => :bar</tt> here.
205
- #
206
- def initialize(pdf, point, options={})
207
- @pdf = pdf
208
- @point = point
209
-
210
- # Set defaults; these can be changed by options
211
- @padding = [5, 5, 5, 5]
212
- @borders = [:top, :bottom, :left, :right]
213
- @border_widths = [1] * 4
214
- @border_colors = ['000000'] * 4
215
- @border_lines = [:solid] * 4
216
- @colspan = 1
217
- @rowspan = 1
218
- @dummy_cells = []
219
-
220
- options.each { |k, v| send("#{k}=", v) }
221
-
222
- @initializer_run = true
223
- end
224
-
225
- # Supports setting multiple properties at once.
226
- #
227
- # cell.style(:padding => 0, :border_width => 2)
228
- #
229
- # is the same as:
230
- #
231
- # cell.padding = 0
232
- # cell.border_width = 2
233
- #
234
- def style(options={}, &block)
235
- options.each do |k, v|
236
- send("#{k}=", v) if respond_to?("#{k}=")
237
- end
238
-
239
- # The block form supports running a single block for multiple cells, as
240
- # in Cells#style.
241
- block.call(self) if block
242
- end
243
-
244
- # Returns the width of the cell in its first column alone, ignoring any
245
- # colspans.
246
- #
247
- def width_ignoring_span
248
- # We can't ||= here because the FP error accumulates on the round-trip
249
- # from #content_width.
250
- defined?(@width) && @width || (content_width + padding_left + padding_right)
251
- end
252
-
253
- # Returns the cell's width in points, inclusive of padding. If the cell is
254
- # the master cell of a colspan, returns the width of the entire span
255
- # group.
256
- #
257
- def width
258
- return width_ignoring_span if @colspan == 1 && @rowspan == 1
259
-
260
- # We're in a span group; get the maximum width per column (including
261
- # the master cell) and sum each column.
262
- column_widths = Hash.new(0)
263
- dummy_cells.each do |cell|
264
- column_widths[cell.column] =
265
- [column_widths[cell.column], cell.width].max
266
- end
267
- column_widths[column] = [column_widths[column], width_ignoring_span].max
268
- column_widths.values.inject(0, &:+)
269
- end
270
-
271
- # Manually sets the cell's width, inclusive of padding.
272
- #
273
- def width=(w)
274
- @width = @min_width = @max_width = w
275
- end
276
-
277
- # Returns the width of the bare content in the cell, excluding padding.
278
- #
279
- def content_width
280
- if defined?(@width) && @width # manually set
281
- return @width - padding_left - padding_right
282
- end
283
-
284
- natural_content_width
285
- end
286
-
287
- # Width of the entire span group.
288
- #
289
- def spanned_content_width
290
- width - padding_left - padding_right
291
- end
292
-
293
- # Returns the width this cell would naturally take on, absent other
294
- # constraints. Must be implemented in subclasses.
295
- #
296
- def natural_content_width
297
- raise NotImplementedError,
298
- "subclasses must implement natural_content_width"
299
- end
300
-
301
- # Returns the cell's height in points, inclusive of padding, in its first
302
- # row only.
303
- #
304
- def height_ignoring_span
305
- # We can't ||= here because the FP error accumulates on the round-trip
306
- # from #content_height.
307
- defined?(@height) && @height || (content_height + padding_top + padding_bottom)
308
- end
309
-
310
- # Returns the cell's height in points, inclusive of padding. If the cell
311
- # is the master cell of a rowspan, returns the width of the entire span
312
- # group.
313
- #
314
- def height
315
- return height_ignoring_span if @colspan == 1 && @rowspan == 1
316
-
317
- # We're in a span group; get the maximum height per row (including the
318
- # master cell) and sum each row.
319
- row_heights = Hash.new(0)
320
- dummy_cells.each do |cell|
321
- row_heights[cell.row] = [row_heights[cell.row], cell.height].max
322
- end
323
- row_heights[row] = [row_heights[row], height_ignoring_span].max
324
- row_heights.values.inject(0, &:+)
325
- end
326
-
327
- # Returns the height of the bare content in the cell, excluding padding.
328
- #
329
- def content_height
330
- if defined?(@height) && @height # manually set
331
- return @height - padding_top - padding_bottom
332
- end
333
-
334
- natural_content_height
335
- end
336
-
337
- # Height of the entire span group.
338
- #
339
- def spanned_content_height
340
- height - padding_top - padding_bottom
341
- end
342
-
343
- # Returns the height this cell would naturally take on, absent
344
- # constraints. Must be implemented in subclasses.
345
- #
346
- def natural_content_height
347
- raise NotImplementedError,
348
- "subclasses must implement natural_content_height"
349
- end
350
-
351
- # Indicates the number of columns that this cell is to span. Defaults to
352
- # 1.
353
- #
354
- # This must be provided as part of the table data, like so:
355
- #
356
- # pdf.table([["foo", {:content => "bar", :colspan => 2}]])
357
- #
358
- # Setting colspan from the initializer block is invalid because layout
359
- # has already run. For example, this will NOT work:
360
- #
361
- # pdf.table([["foo", "bar"]]) { cells[0, 1].colspan = 2 }
362
- #
363
- def colspan=(span)
364
- if defined?(@initializer_run) && @initializer_run
365
- raise Prawn::Errors::InvalidTableSpan,
366
- "colspan must be provided in the table's structure, never in the " +
367
- "initialization block. See Prawn's documentation for details."
368
- end
369
-
370
- @colspan = span
371
- end
372
-
373
- # Indicates the number of rows that this cell is to span. Defaults to 1.
374
- #
375
- # This must be provided as part of the table data, like so:
376
- #
377
- # pdf.table([["foo", {:content => "bar", :rowspan => 2}], ["baz"]])
378
- #
379
- # Setting rowspan from the initializer block is invalid because layout
380
- # has already run. For example, this will NOT work:
381
- #
382
- # pdf.table([["foo", "bar"], ["baz"]]) { cells[0, 1].rowspan = 2 }
383
- #
384
- def rowspan=(span)
385
- if defined?(@initializer_run) && @initializer_run
386
- raise Prawn::Errors::InvalidTableSpan,
387
- "rowspan must be provided in the table's structure, never in the " +
388
- "initialization block. See Prawn's documentation for details."
389
- end
390
-
391
- @rowspan = span
392
- end
393
-
394
- # Draws the cell onto the document. Pass in a point [x,y] to override the
395
- # location at which the cell is drawn.
396
- #
397
- # If drawing a group of cells at known positions, look into
398
- # Cell.draw_cells, which ensures that the backgrounds, borders, and
399
- # content are all drawn in correct order so as not to overlap.
400
- #
401
- def draw(pt=[x, y])
402
- Prawn::Table::Cell.draw_cells([[self, pt]])
403
- end
404
-
405
- # Given an array of pairs [cell, pt], draws each cell at its
406
- # corresponding pt, making sure all backgrounds are behind all borders
407
- # and content.
408
- #
409
- def self.draw_cells(cells)
410
- cells.each do |cell, pt|
411
- cell.set_width_constraints
412
- cell.draw_background(pt)
413
- end
414
-
415
- cells.each do |cell, pt|
416
- cell.draw_borders(pt)
417
- cell.draw_bounded_content(pt)
418
- end
419
- end
420
-
421
- # Draws the cell's content at the point provided.
422
- #
423
- def draw_bounded_content(pt)
424
- @pdf.float do
425
- @pdf.bounding_box([pt[0] + padding_left, pt[1] - padding_top],
426
- :width => spanned_content_width + FPTolerance,
427
- :height => spanned_content_height + FPTolerance) do
428
- draw_content
429
- end
430
- end
431
- end
432
-
433
- # x-position of the cell within the parent bounds.
434
- #
435
- def x
436
- @point[0]
437
- end
438
-
439
- # Set the x-position of the cell within the parent bounds.
440
- #
441
- def x=(val)
442
- @point[0] = val
443
- end
444
-
445
- # y-position of the cell within the parent bounds.
446
- #
447
- def y
448
- @point[1]
449
- end
450
-
451
- # Set the y-position of the cell within the parent bounds.
452
- #
453
- def y=(val)
454
- @point[1] = val
455
- end
456
-
457
- # Sets padding on this cell. The argument can be one of:
458
- #
459
- # * an integer (sets all padding)
460
- # * a two-element array [vertical, horizontal]
461
- # * a three-element array [top, horizontal, bottom]
462
- # * a four-element array [top, right, bottom, left]
463
- #
464
- def padding=(pad)
465
- @padding = case
466
- when pad.nil?
467
- [0, 0, 0, 0]
468
- when Numeric === pad # all padding
469
- [pad, pad, pad, pad]
470
- when pad.length == 2 # vert, horiz
471
- [pad[0], pad[1], pad[0], pad[1]]
472
- when pad.length == 3 # top, horiz, bottom
473
- [pad[0], pad[1], pad[2], pad[1]]
474
- when pad.length == 4 # top, right, bottom, left
475
- [pad[0], pad[1], pad[2], pad[3]]
476
- else
477
- raise ArgumentError, ":padding must be a number or an array [v,h] " +
478
- "or [t,r,b,l]"
479
- end
480
- end
481
-
482
- def padding_top
483
- @padding[0]
484
- end
485
-
486
- def padding_top=(val)
487
- @padding[0] = val
488
- end
489
-
490
- def padding_right
491
- @padding[1]
492
- end
493
-
494
- def padding_right=(val)
495
- @padding[1] = val
496
- end
497
-
498
- def padding_bottom
499
- @padding[2]
500
- end
501
-
502
- def padding_bottom=(val)
503
- @padding[2] = val
504
- end
505
-
506
- def padding_left
507
- @padding[3]
508
- end
509
-
510
- def padding_left=(val)
511
- @padding[3] = val
512
- end
513
-
514
- # Sets border colors on this cell. The argument can be one of:
515
- #
516
- # * an integer (sets all colors)
517
- # * a two-element array [vertical, horizontal]
518
- # * a three-element array [top, horizontal, bottom]
519
- # * a four-element array [top, right, bottom, left]
520
- #
521
- def border_color=(color)
522
- @border_colors = case
523
- when color.nil?
524
- ["000000"] * 4
525
- when String === color # all colors
526
- [color, color, color, color]
527
- when color.length == 2 # vert, horiz
528
- [color[0], color[1], color[0], color[1]]
529
- when color.length == 3 # top, horiz, bottom
530
- [color[0], color[1], color[2], color[1]]
531
- when color.length == 4 # top, right, bottom, left
532
- [color[0], color[1], color[2], color[3]]
533
- else
534
- raise ArgumentError, ":border_color must be a string " +
535
- "or an array [v,h] or [t,r,b,l]"
536
- end
537
- end
538
- alias_method :border_colors=, :border_color=
539
-
540
- def border_top_color
541
- @border_colors[0]
542
- end
543
-
544
- def border_top_color=(val)
545
- @border_colors[0] = val
546
- end
547
-
548
- def border_right_color
549
- @border_colors[1]
550
- end
551
-
552
- def border_right_color=(val)
553
- @border_colors[1] = val
554
- end
555
-
556
- def border_bottom_color
557
- @border_colors[2]
558
- end
559
-
560
- def border_bottom_color=(val)
561
- @border_colors[2] = val
562
- end
563
-
564
- def border_left_color
565
- @border_colors[3]
566
- end
567
-
568
- def border_left_color=(val)
569
- @border_colors[3] = val
570
- end
571
-
572
- # Sets border widths on this cell. The argument can be one of:
573
- #
574
- # * an integer (sets all widths)
575
- # * a two-element array [vertical, horizontal]
576
- # * a three-element array [top, horizontal, bottom]
577
- # * a four-element array [top, right, bottom, left]
578
- #
579
- def border_width=(width)
580
- @border_widths = case
581
- when width.nil?
582
- ["000000"] * 4
583
- when Numeric === width # all widths
584
- [width, width, width, width]
585
- when width.length == 2 # vert, horiz
586
- [width[0], width[1], width[0], width[1]]
587
- when width.length == 3 # top, horiz, bottom
588
- [width[0], width[1], width[2], width[1]]
589
- when width.length == 4 # top, right, bottom, left
590
- [width[0], width[1], width[2], width[3]]
591
- else
592
- raise ArgumentError, ":border_width must be a string " +
593
- "or an array [v,h] or [t,r,b,l]"
594
- end
595
- end
596
- alias_method :border_widths=, :border_width=
597
-
598
- def border_top_width
599
- @borders.include?(:top) ? @border_widths[0] : 0
600
- end
601
-
602
- def border_top_width=(val)
603
- @border_widths[0] = val
604
- end
605
-
606
- def border_right_width
607
- @borders.include?(:right) ? @border_widths[1] : 0
608
- end
609
-
610
- def border_right_width=(val)
611
- @border_widths[1] = val
612
- end
613
-
614
- def border_bottom_width
615
- @borders.include?(:bottom) ? @border_widths[2] : 0
616
- end
617
-
618
- def border_bottom_width=(val)
619
- @border_widths[2] = val
620
- end
621
-
622
- def border_left_width
623
- @borders.include?(:left) ? @border_widths[3] : 0
624
- end
625
-
626
- def border_left_width=(val)
627
- @border_widths[3] = val
628
- end
629
-
630
- # Sets the cell's minimum and maximum width. Deferred until requested
631
- # because padding and size can change.
632
- #
633
- def set_width_constraints
634
- @min_width ||= padding_left + padding_right
635
- @max_width ||= @pdf.bounds.width
636
- end
637
-
638
- # Sets border line style on this cell. The argument can be one of:
639
- #
640
- # Possible values are: :solid, :dashed, :dotted
641
- #
642
- # * one value (sets all lines)
643
- # * a two-element array [vertical, horizontal]
644
- # * a three-element array [top, horizontal, bottom]
645
- # * a four-element array [top, right, bottom, left]
646
- #
647
- def border_line=(line)
648
- @border_lines = case
649
- when line.nil?
650
- [:solid] * 4
651
- when line.length == 1 # all lines
652
- [line[0]] * 4
653
- when line.length == 2
654
- [line[0], line[1], line[0], line[1]]
655
- when line.length == 3
656
- [line[0], line[1], line[2], line[1]]
657
- when line.length == 4
658
- [line[0], line[1], line[2], line[3]]
659
- else
660
- raise ArgumentError, "border_line must be one of :solid, :dashed, "
661
- ":dotted or an array [v,h] or [t,r,b,l]"
662
- end
663
- end
664
- alias_method :border_lines=, :border_line=
665
-
666
- def border_top_line
667
- @borders.include?(:top) ? @border_lines[0] : 0
668
- end
669
-
670
- def border_top_line=(val)
671
- @border_lines[0] = val
672
- end
673
-
674
- def border_right_line
675
- @borders.include?(:right) ? @border_lines[1] : 0
676
- end
677
-
678
- def border_right_line=(val)
679
- @border_lines[1] = val
680
- end
681
-
682
- def border_bottom_line
683
- @borders.include?(:bottom) ? @border_lines[2] : 0
684
- end
685
-
686
- def border_bottom_line=(val)
687
- @border_lines[2] = val
688
- end
689
-
690
- def border_left_line
691
- @borders.include?(:left) ? @border_lines[3] : 0
692
- end
693
-
694
- def border_left_line=(val)
695
- @border_lines[3] = val
696
- end
697
-
698
- # Draws the cell's background color.
699
- #
700
- def draw_background(pt)
701
- if defined?(@background_color) && @background_color
702
- @pdf.mask(:fill_color) do
703
- @pdf.fill_color @background_color
704
- @pdf.fill_rectangle pt, width, height
705
- end
706
- end
707
- end
708
-
709
- # Draws borders around the cell. Borders are centered on the bounds of
710
- # the cell outside of any padding, so the caller is responsible for
711
- # setting appropriate padding to ensure the border does not overlap with
712
- # cell content.
713
- #
714
- def draw_borders(pt)
715
- x, y = pt
716
-
717
- @pdf.mask(:line_width, :stroke_color) do
718
- @borders.each do |border|
719
- idx = {:top => 0, :right => 1, :bottom => 2, :left => 3}[border]
720
- border_color = @border_colors[idx]
721
- border_width = @border_widths[idx]
722
- border_line = @border_lines[idx]
723
-
724
- next if border_width <= 0
725
-
726
- # Left and right borders are drawn one-half border beyond the center
727
- # of the corner, so that the corners end up square.
728
- from, to = case border
729
- when :top
730
- [[x, y], [x+width, y]]
731
- when :bottom
732
- [[x, y-height], [x+width, y-height]]
733
- when :left
734
- [[x, y + (border_top_width / 2.0)],
735
- [x, y - height - (border_bottom_width / 2.0)]]
736
- when :right
737
- [[x+width, y + (border_top_width / 2.0)],
738
- [x+width, y - height - (border_bottom_width / 2.0)]]
739
- end
740
-
741
- case border_line
742
- when :dashed
743
- @pdf.dash border_width * 4
744
- when :dotted
745
- @pdf.dash border_width, :space => border_width * 2
746
- when :solid
747
- # normal line style
748
- else
749
- raise ArgumentError, "border_line must be :solid, :dotted or" +
750
- " :dashed"
751
- end
752
-
753
- @pdf.line_width = border_width
754
- @pdf.stroke_color = border_color
755
- @pdf.stroke_line(from, to)
756
- @pdf.undash
757
- end
758
- end
759
- end
760
-
761
- # Draws cell content within the cell's bounding box. Must be implemented
762
- # in subclasses.
763
- #
764
- def draw_content
765
- raise NotImplementedError, "subclasses must implement draw_content"
766
- end
767
-
768
- end
769
- end
770
- end