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
@@ -7,13 +7,13 @@
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
9
  require "stringio"
10
- require "prawn/document/page_geometry"
11
- require "prawn/document/bounding_box"
12
- require "prawn/document/column_box"
13
- require "prawn/document/internals"
14
- require "prawn/document/span"
15
- require "prawn/document/snapshot"
16
- require "prawn/document/graphics_state"
10
+
11
+ require_relative "document/bounding_box"
12
+ require_relative "document/column_box"
13
+ require_relative "document/internals"
14
+ require_relative "document/span"
15
+ require_relative "document/snapshot"
16
+ require_relative "document/graphics_state"
17
17
 
18
18
  module Prawn
19
19
 
@@ -52,8 +52,8 @@ module Prawn
52
52
  #
53
53
  class Document
54
54
  include Prawn::Document::Internals
55
- include Prawn::Core::Annotations
56
- include Prawn::Core::Destinations
55
+ include PDF::Core::Annotations
56
+ include PDF::Core::Destinations
57
57
  include Prawn::Document::Snapshot
58
58
  include Prawn::Document::GraphicsState
59
59
  include Prawn::Document::Security
@@ -61,6 +61,17 @@ module Prawn
61
61
  include Prawn::Graphics
62
62
  include Prawn::Images
63
63
  include Prawn::Stamp
64
+ include Prawn::SoftMask
65
+
66
+ # @group Extension API
67
+
68
+ # NOTE: We probably need to rethink the options validation system, but this
69
+ # constant temporarily allows for extensions to modify the list.
70
+
71
+ VALID_OPTIONS = [:page_size, :page_layout, :margin, :left_margin,
72
+ :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
73
+ :compress, :skip_encoding, :background, :info,
74
+ :optimize_objects, :text_formatter, :print_scaling]
64
75
 
65
76
  # Any module added to this array will be included into instances of
66
77
  # Prawn::Document at the per-object level. These will also be inherited by
@@ -82,14 +93,28 @@ module Prawn
82
93
  # party!
83
94
  # end
84
95
  #
96
+ #
85
97
  def self.extensions
86
98
  @extensions ||= []
87
99
  end
88
100
 
89
- def self.inherited(base) #:nodoc:
101
+ # @private
102
+ def self.inherited(base)
90
103
  extensions.each { |e| base.extensions << e }
91
104
  end
92
105
 
106
+ # @group Stable Attributes
107
+
108
+ attr_accessor :margin_box
109
+ attr_reader :margins, :y
110
+ attr_accessor :page_number
111
+
112
+ # @group Extension Attributes
113
+
114
+ attr_accessor :text_formatter
115
+
116
+ # @group Stable API
117
+
93
118
  # Creates and renders a PDF document.
94
119
  #
95
120
  # When using the implicit block form, Prawn will evaluate the block
@@ -136,8 +161,9 @@ module Prawn
136
161
  # <tt>:compress</tt>:: Compresses content streams before rendering them [false]
137
162
  # <tt>:optimize_objects</tt>:: Reduce number of PDF objects in output, at expense of render time [false]
138
163
  # <tt>:background</tt>:: An image path to be used as background on all pages [nil]
164
+ # <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
139
165
  # <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
140
- # <tt>:template</tt>:: The path to an existing PDF file to use as a template [nil]
166
+ # <tt>:text_formatter</tt>: The text formatter to use for <tt>:inline_format</tt>ted text [Prawn::Text::Formatted::Parser]
141
167
  #
142
168
  # Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
143
169
  # of 100 points on every side except for the left, where it will be 50.
@@ -166,116 +192,100 @@ module Prawn
166
192
  # pdf = Prawn::Document.new(:page_size => [200, 300])
167
193
  #
168
194
  # # New document, with background
169
- # pdf = Prawn::Document.new(:background => "#{Prawn::BASEDIR}/data/images/pigs.jpg")
195
+ # pdf = Prawn::Document.new(:background => "#{Prawn::DATADIR}/images/pigs.jpg")
170
196
  #
171
197
  def initialize(options={},&block)
172
- Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
173
- :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
174
- :compress, :skip_encoding, :background, :info,
175
- :optimize_objects, :template], options
176
-
177
- # need to fix, as the refactoring breaks this
178
- # raise NotImplementedError if options[:skip_page_creation]
179
-
180
- self.class.extensions.reverse_each { |e| extend e }
181
- @internal_state = Prawn::Core::DocumentState.new(options)
182
- @internal_state.populate_pages_from_store(self)
183
- min_version(state.store.min_version) if state.store.min_version
184
-
185
- @background = options[:background]
186
- @font_size = 12
187
-
188
- @bounding_box = nil
189
- @margin_box = nil
190
-
191
- @page_number = 0
192
-
193
- options[:size] = options.delete(:page_size)
194
- options[:layout] = options.delete(:page_layout)
195
-
196
- if options[:template]
197
- fresh_content_streams(options)
198
- go_to_page(1)
199
- else
200
- if options[:skip_page_creation] || options[:template]
201
- start_new_page(options.merge(:orphan => true))
202
- else
203
- start_new_page(options)
204
- end
205
- end
206
-
207
- @bounding_box = @margin_box
208
-
209
- if block
210
- block.arity < 1 ? instance_eval(&block) : block[self]
211
- end
212
- end
213
-
214
- attr_accessor :margin_box
215
- attr_reader :margins, :y
216
- attr_writer :font_size
217
- attr_accessor :page_number
218
-
219
- def state
220
- @internal_state
221
- end
222
-
223
- def page
224
- state.page
225
- end
226
-
227
- # Creates and advances to a new page in the document.
228
- #
229
- # Page size, margins, and layout can also be set when generating a
230
- # new page. These values will become the new defaults for page creation
231
- #
232
- # pdf.start_new_page #=> Starts new page keeping current values
233
- # pdf.start_new_page(:size => "LEGAL", :layout => :landscape)
234
- # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
235
- # pdf.start_new_page(:margin => 100)
236
- #
237
- # A template for a page can be specified by pointing to the path of and existing pdf.
238
- # One can also specify which page of the template which defaults otherwise to 1.
239
- #
240
- # pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
241
- #
242
- def start_new_page(options = {})
243
- if last_page = state.page
244
- last_page_size = last_page.size
245
- last_page_layout = last_page.layout
246
- last_page_margins = last_page.margins
247
- end
248
-
249
- page_options = {:size => options[:size] || last_page_size,
250
- :layout => options[:layout] || last_page_layout,
251
- :margins => last_page_margins}
252
- if last_page
253
- new_graphic_state = last_page.graphic_state.dup
254
- #erase the color space so that it gets reset on new page for fussy pdf-readers
255
- new_graphic_state.color_space = {}
256
- page_options.merge!(:graphic_state => new_graphic_state)
257
- end
258
- merge_template_options(page_options, options) if options[:template]
259
-
260
- state.page = Prawn::Core::Page.new(self, page_options)
261
-
262
- apply_margin_options(options)
263
- state.page.new_content_stream if options[:template]
264
- use_graphic_settings(options[:template])
265
-
266
- unless options[:orphan]
267
- state.insert_page(state.page, @page_number)
268
- @page_number += 1
269
-
270
- canvas { image(@background, :at => bounds.top_left) } if @background
271
- @y = @bounding_box.absolute_top
272
-
273
- float do
274
- state.on_page_create_action(self)
275
- end
276
- end
198
+ options = options.dup
199
+
200
+ Prawn.verify_options VALID_OPTIONS, options
201
+
202
+ # need to fix, as the refactoring breaks this
203
+ # raise NotImplementedError if options[:skip_page_creation]
204
+
205
+ self.class.extensions.reverse_each { |e| extend e }
206
+ @internal_state = PDF::Core::DocumentState.new(options)
207
+ @internal_state.populate_pages_from_store(self)
208
+ min_version(state.store.min_version) if state.store.min_version
209
+
210
+ min_version(1.6) if options[:print_scaling] == :none
211
+
212
+ @background = options[:background]
213
+ @background_scale = options[:background_scale] || 1
214
+ @font_size = 12
215
+
216
+ @bounding_box = nil
217
+ @margin_box = nil
218
+
219
+ @page_number = 0
220
+
221
+ @text_formatter = options.delete(:text_formatter) || Text::Formatted::Parser
222
+
223
+ options[:size] = options.delete(:page_size)
224
+ options[:layout] = options.delete(:page_layout)
225
+
226
+ initialize_first_page(options)
227
+
228
+ @bounding_box = @margin_box
229
+
230
+ if block
231
+ block.arity < 1 ? instance_eval(&block) : block[self]
232
+ end
233
+ end
234
+
235
+ # @group Stable API
236
+
237
+ # Creates and advances to a new page in the document.
238
+ #
239
+ # Page size, margins, and layout can also be set when generating a
240
+ # new page. These values will become the new defaults for page creation
241
+ #
242
+ # pdf.start_new_page #=> Starts new page keeping current values
243
+ # pdf.start_new_page(:size => "LEGAL", :layout => :landscape)
244
+ # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
245
+ # pdf.start_new_page(:margin => 100)
246
+ #
247
+ def start_new_page(options = {})
248
+ if last_page = state.page
249
+ last_page_size = last_page.size
250
+ last_page_layout = last_page.layout
251
+ last_page_margins = last_page.margins
252
+ end
253
+
254
+ page_options = {:size => options[:size] || last_page_size,
255
+ :layout => options[:layout] || last_page_layout,
256
+ :margins => last_page_margins}
257
+ if last_page
258
+ new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
259
+ #erase the color space so that it gets reset on new page for fussy pdf-readers
260
+ new_graphic_state.color_space = {} if new_graphic_state
261
+ page_options.merge!(:graphic_state => new_graphic_state)
262
+ end
263
+
264
+ state.page = PDF::Core::Page.new(self, page_options)
265
+
266
+ apply_margin_options(options)
267
+ generate_margin_box
268
+
269
+ # Reset the bounding box if the new page has different size or layout
270
+ if last_page && (last_page.size != state.page.size ||
271
+ last_page.layout != state.page.layout)
272
+ @bounding_box = @margin_box
273
+ end
274
+
275
+ use_graphic_settings
277
276
 
278
- end
277
+ unless options[:orphan]
278
+ state.insert_page(state.page, @page_number)
279
+ @page_number += 1
280
+
281
+ canvas { image(@background, :scale => @background_scale, :at => bounds.top_left) } if @background
282
+ @y = @bounding_box.absolute_top
283
+
284
+ float do
285
+ state.on_page_create_action(self)
286
+ end
287
+ end
288
+ end
279
289
 
280
290
  # Returns the number of pages in the document
281
291
  #
@@ -318,7 +328,9 @@ module Prawn
318
328
  self.y = new_y + bounds.absolute_bottom
319
329
  end
320
330
 
321
- # Executes a block and then restores the original y position
331
+ # Executes a block and then restores the original y position. If new pages
332
+ # were created during this block, it will teleport back to the original
333
+ # page when done.
322
334
  #
323
335
  # pdf.text "A"
324
336
  #
@@ -330,22 +342,33 @@ module Prawn
330
342
  # pdf.text "B"
331
343
  #
332
344
  def float
333
- mask(:y) { yield }
345
+ original_page = page_number
346
+ original_y = y
347
+ yield
348
+ go_to_page(original_page) unless page_number == original_page
349
+ self.y = original_y
334
350
  end
335
351
 
336
- # Renders the PDF document to string
352
+ # Renders the PDF document to string.
353
+ # Pass an open file descriptor to render to file.
337
354
  #
338
- def render
339
- output = StringIO.new
355
+ def render(output = StringIO.new)
356
+ if output.instance_of?(StringIO)
357
+ output.set_encoding(::Encoding::ASCII_8BIT)
358
+ end
340
359
  finalize_all_page_contents
341
360
 
342
361
  render_header(output)
343
362
  render_body(output)
344
363
  render_xref(output)
345
364
  render_trailer(output)
346
- str = output.string
347
- str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
348
- str
365
+ if output.instance_of?(StringIO)
366
+ str = output.string
367
+ str.force_encoding(::Encoding::ASCII_8BIT)
368
+ return str
369
+ else
370
+ return nil
371
+ end
349
372
  end
350
373
 
351
374
  # Renders the PDF document to file.
@@ -353,8 +376,7 @@ module Prawn
353
376
  # pdf.render_file "foo.pdf"
354
377
  #
355
378
  def render_file(filename)
356
- Kernel.const_defined?("Encoding") ? mode = "wb:ASCII-8BIT" : mode = "wb"
357
- File.open(filename,mode) { |f| f << render }
379
+ File.open(filename, "wb") { |f| render(f) }
358
380
  end
359
381
 
360
382
  # The bounds method returns the current bounding box you are currently in,
@@ -388,6 +410,13 @@ module Prawn
388
410
  @bounding_box
389
411
  end
390
412
 
413
+ # Returns the innermost non-stretchy bounding box.
414
+ #
415
+ # @private
416
+ def reference_bounds
417
+ @bounding_box.reference_bounds
418
+ end
419
+
391
420
  # Sets Document#bounds to the BoundingBox provided. See above for a brief
392
421
  # description of what a bounding box is. This function is useful if you
393
422
  # really need to change the bounding box manually, but usually, just entering
@@ -469,47 +498,6 @@ module Prawn
469
498
  bounds.indent(left, right, &block)
470
499
  end
471
500
 
472
-
473
- def mask(*fields) # :nodoc:
474
- # Stores the current state of the named attributes, executes the block, and
475
- # then restores the original values after the block has executed.
476
- # -- I will remove the nodoc if/when this feature is a little less hacky
477
- stored = {}
478
- fields.each { |f| stored[f] = send(f) }
479
- yield
480
- fields.each { |f| send("#{f}=", stored[f]) }
481
- end
482
-
483
- # Attempts to group the given block vertically within the current context.
484
- # First attempts to render it in the current position on the current page.
485
- # If that attempt overflows, it is tried anew after starting a new context
486
- # (page or column). Returns a logically true value if the content fits in
487
- # one page/column, false if a new page or column was needed.
488
- #
489
- # Raises CannotGroup if the provided content is too large to fit alone in
490
- # the current page or column.
491
- #
492
- def group(second_attempt=false)
493
- old_bounding_box = @bounding_box
494
- @bounding_box = SimpleDelegator.new(@bounding_box)
495
-
496
- def @bounding_box.move_past_bottom
497
- raise RollbackTransaction
498
- end
499
-
500
- success = transaction { yield }
501
-
502
- @bounding_box = old_bounding_box
503
-
504
- unless success
505
- raise Prawn::Errors::CannotGroup if second_attempt
506
- old_bounding_box.move_past_bottom
507
- group(second_attempt=true) { yield }
508
- end
509
-
510
- success
511
- end
512
-
513
501
  # Places a text box on specified pages for page numbering. This should be called
514
502
  # towards the end of document creation, after all your content is already in
515
503
  # place. In your template string, <page> refers to the current page, and
@@ -518,15 +506,15 @@ module Prawn
518
506
  # through existing pages after they are created.
519
507
  #
520
508
  # Parameters are:
521
- #
522
- # <tt>string</tt>:: Template string for page number wording.
509
+ #
510
+ # <tt>string</tt>:: Template string for page number wording.
523
511
  # Should include '<page>' and, optionally, '<total>'.
524
512
  # <tt>options</tt>:: A hash for page numbering and text box options.
525
- # <tt>:page_filter</tt>:: A filter to specify which pages to place page numbers on.
513
+ # <tt>:page_filter</tt>:: A filter to specify which pages to place page numbers on.
526
514
  # Refer to the method 'page_match?'
527
515
  # <tt>:start_count_at</tt>:: The starting count to increment pages from.
528
516
  # <tt>:total_pages</tt>:: If provided, will replace <total> with the value given.
529
- # Useful to override the total number of pages when using
517
+ # Useful to override the total number of pages when using
530
518
  # the start_count_at option.
531
519
  # <tt>:color</tt>:: Text fill color.
532
520
  #
@@ -537,7 +525,7 @@ module Prawn
537
525
  # five.
538
526
  #
539
527
  # Prawn::Document.generate("page_with_numbering.pdf") do
540
- # number_pages "<page> in a total of <total>",
528
+ # number_pages "<page> in a total of <total>",
541
529
  # {:start_count_at => 5,
542
530
  # :page_filter => lambda{ |pg| pg != 1 },
543
531
  # :at => [bounds.right - 50, 0],
@@ -548,12 +536,16 @@ module Prawn
548
536
  def number_pages(string, options={})
549
537
  opts = options.dup
550
538
  start_count_at = opts.delete(:start_count_at).to_i
551
- page_filter = opts.delete(:page_filter)
539
+ page_filter = if opts.has_key?(:page_filter)
540
+ opts.delete(:page_filter)
541
+ else
542
+ :all
543
+ end
552
544
  total_pages = opts.delete(:total_pages)
553
545
  txtcolor = opts.delete(:color)
554
546
  # An explicit height so that we can draw page numbers in the margins
555
- opts[:height] = 50
556
-
547
+ opts[:height] = 50 unless opts.has_key?(:height)
548
+
557
549
  start_count = false
558
550
  pseudopage = 0
559
551
  (1..page_count).each do |p|
@@ -564,7 +556,7 @@ module Prawn
564
556
  else
565
557
  start_count_at.to_i
566
558
  end
567
- end
559
+ end
568
560
  if page_match?(page_filter, p)
569
561
  go_to_page(p)
570
562
  # have to use fill_color here otherwise text reverts back to default fill color
@@ -573,13 +565,53 @@ module Prawn
573
565
  str = string.gsub("<page>","#{pseudopage}").gsub("<total>","#{total_pages}")
574
566
  text_box str, opts
575
567
  start_count = true # increment page count as soon as first match found
576
- end
568
+ end
577
569
  pseudopage += 1 if start_count
578
570
  end
579
571
  end
580
572
 
573
+ # Returns true if content streams will be compressed before rendering,
574
+ # false otherwise
575
+ #
576
+ def compression_enabled?
577
+ !!state.compress
578
+ end
579
+
580
+ # @group Experimental API
581
+
582
+ # Attempts to group the given block vertically within the current context.
583
+ # First attempts to render it in the current position on the current page.
584
+ # If that attempt overflows, it is tried anew after starting a new context
585
+ # (page or column). Returns a logically true value if the content fits in
586
+ # one page/column, false if a new page or column was needed.
587
+ #
588
+ # Raises CannotGroup if the provided content is too large to fit alone in
589
+ # the current page or column.
590
+ #
591
+ def group(second_attempt=false)
592
+ old_bounding_box = @bounding_box
593
+ @bounding_box = SimpleDelegator.new(@bounding_box)
594
+
595
+ # @private
596
+ def @bounding_box.move_past_bottom
597
+ raise RollbackTransaction
598
+ end
599
+
600
+ success = transaction { yield }
601
+
602
+ @bounding_box = old_bounding_box
603
+
604
+ unless success
605
+ raise Prawn::Errors::CannotGroup if second_attempt
606
+ old_bounding_box.move_past_bottom
607
+ group(second_attempt=true) { yield }
608
+ end
609
+
610
+ success
611
+ end
612
+
581
613
  # Provides a way to execute a block of code repeatedly based on a
582
- # page_filter.
614
+ # page_filter.
583
615
  #
584
616
  # Available page filters are:
585
617
  # :all repeats on every page
@@ -587,7 +619,7 @@ module Prawn
587
619
  # :even repeats on even pages
588
620
  # some_array repeats on every page listed in the array
589
621
  # some_range repeats on every page included in the range
590
- # some_lambda yields page number and repeats for true return values
622
+ # some_lambda yields page number and repeats for true return values
591
623
  def page_match?(page_filter, page_number)
592
624
  case page_filter
593
625
  when :all
@@ -601,25 +633,47 @@ module Prawn
601
633
  when Proc
602
634
  page_filter.call(page_number)
603
635
  end
604
- end
636
+ end
605
637
 
638
+ # @private
639
+
640
+ def mask(*fields)
641
+ # Stores the current state of the named attributes, executes the block, and
642
+ # then restores the original values after the block has executed.
643
+ # -- I will remove the nodoc if/when this feature is a little less hacky
644
+ stored = {}
645
+ fields.each { |f| stored[f] = send(f) }
646
+ yield
647
+ fields.each { |f| send("#{f}=", stored[f]) }
648
+ end
606
649
 
607
- # Returns true if content streams will be compressed before rendering,
608
- # false otherwise
609
- #
610
- def compression_enabled?
611
- !!state.compress
650
+ # @group Extension API
651
+
652
+ def initialize_first_page(options)
653
+ if options[:skip_page_creation]
654
+ start_new_page(options.merge(:orphan => true))
655
+ else
656
+ start_new_page(options)
657
+ end
612
658
  end
613
659
 
614
- private
660
+ ## Internals. Don't depend on them!
615
661
 
616
- def merge_template_options(page_options, options)
617
- object_id = state.store.import_page(options[:template], options[:template_page] || 1)
618
- page_options.merge!(:object_id => object_id )
662
+ # @private
663
+ def state
664
+ @internal_state
619
665
  end
620
666
 
667
+ # @private
668
+ def page
669
+ state.page
670
+ end
671
+
672
+ private
673
+
674
+
621
675
  # setting override_settings to true ensures that a new graphic state does not end up using
622
- # previous settings especially from imported template streams
676
+ # previous settings.
623
677
  def use_graphic_settings(override_settings = false)
624
678
  set_fill_color if current_fill_color != "000000" || override_settings
625
679
  set_stroke_color if current_stroke_color != "000000" || override_settings
@@ -642,7 +696,7 @@ module Prawn
642
696
  )
643
697
 
644
698
  # This check maintains indentation settings across page breaks
645
- if (old_margin_box)
699
+ if old_margin_box
646
700
  @margin_box.add_left_padding(old_margin_box.total_left_padding)
647
701
  @margin_box.add_right_padding(old_margin_box.total_right_padding)
648
702
  end
@@ -671,8 +725,10 @@ module Prawn
671
725
  state.page.margins[side] = margin
672
726
  end
673
727
  end
728
+ end
674
729
 
675
- generate_margin_box
730
+ def font_metric_cache #:nodoc:
731
+ @font_metric_cache ||= FontMetricCache.new( self )
676
732
  end
677
733
  end
678
734
  end
@@ -5,7 +5,7 @@
5
5
  # This is free software. Please see the LICENSE and COPYING files for details.
6
6
  #
7
7
  module Prawn
8
- module Encoding
8
+ module Encoding # @private
9
9
  # Map between unicode and WinAnsiEnoding
10
10
  #
11
11
  class WinAnsi #:nodoc:
@@ -18,7 +18,7 @@ module Prawn
18
18
  .notdef .notdef .notdef .notdef
19
19
  .notdef .notdef .notdef .notdef
20
20
  .notdef .notdef .notdef .notdef
21
-
21
+
22
22
  space exclam quotedbl numbersign
23
23
  dollar percent ampersand quotesingle
24
24
  parenleft parenright asterisk plus
@@ -54,7 +54,7 @@ module Prawn
54
54
  quotedblright bullet endash emdash
55
55
  tilde trademark scaron guilsinglright
56
56
  oe .notdef zcaron ydieresis
57
-
57
+
58
58
  space exclamdown cent sterling
59
59
  currency yen brokenbar section
60
60
  dieresis copyright ordfeminine guillemotleft
@@ -81,10 +81,10 @@ module Prawn
81
81
  ocircumflex otilde odieresis divide
82
82
  oslash ugrave uacute ucircumflex
83
83
  udieresis yacute thorn ydieresis
84
- ]
85
-
84
+ ]
85
+
86
86
  def initialize
87
- @mapping_file = "#{Prawn::BASEDIR}/data/encodings/win_ansi.txt"
87
+ @mapping_file = "#{Prawn::DATADIR}/encodings/win_ansi.txt"
88
88
  load_mapping if self.class.mapping.empty?
89
89
  end
90
90
 
@@ -100,7 +100,7 @@ module Prawn
100
100
  # Replace anything else with an underscore
101
101
  self.class.mapping[codepoint] || 95
102
102
  end
103
-
103
+
104
104
  def self.mapping
105
105
  @mapping ||= {}
106
106
  end
@@ -108,10 +108,9 @@ module Prawn
108
108
  private
109
109
 
110
110
  def load_mapping
111
- RUBY_VERSION >= "1.9" ? mode = "r:BINARY" : mode = "r"
112
- File.open(@mapping_file, mode) do |f|
111
+ File.open(@mapping_file, "r:BINARY") do |f|
113
112
  f.each do |l|
114
- m, single_byte, unicode = *l.match(/([0-9A-Za-z]+);([0-9A-F]{4})/)
113
+ _, single_byte, unicode = *l.match(/([0-9A-Za-z]+);([0-9A-F]{4})/)
115
114
  self.class.mapping["0x#{unicode}".hex] = "0x#{single_byte}".hex if single_byte
116
115
  end
117
116
  end