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,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # document.rb : Implements PDF document generation for Prawn
4
4
  #
@@ -6,23 +6,21 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
- require "stringio"
9
+ require 'stringio'
10
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/graphics_state"
11
+ require_relative 'document/bounding_box'
12
+ require_relative 'document/column_box'
13
+ require_relative 'document/internals'
14
+ require_relative 'document/span'
16
15
 
17
16
  module Prawn
18
-
19
17
  # The Prawn::Document class is how you start creating a PDF document.
20
18
  #
21
19
  # There are three basic ways you can instantiate PDF Documents in Prawn, they
22
- # are through assignment, implicit block or explicit block. Below is an exmple
23
- # of each type, each example does exactly the same thing, makes a PDF document
24
- # with all the defaults and puts in the default font "Hello There" and then
25
- # saves it to the current directory as "example.pdf"
20
+ # are through assignment, implicit block or explicit block. Below is an
21
+ # example of each type, each example does exactly the same thing, makes a PDF
22
+ # document with all the defaults and puts in the default font "Hello There"
23
+ # and then saves it to the current directory as "example.pdf"
26
24
  #
27
25
  # For example, assignment can be like this:
28
26
  #
@@ -44,8 +42,8 @@ module Prawn
44
42
  # pdf.text words
45
43
  # end
46
44
  #
47
- # Usually, the block forms are used when you are simply creating a PDF document
48
- # that you want to immediately save or render out.
45
+ # Usually, the block forms are used when you are simply creating a PDF
46
+ # document that you want to immediately save or render out.
49
47
  #
50
48
  # See the new and generate methods for further details on the above.
51
49
  #
@@ -53,23 +51,25 @@ module Prawn
53
51
  include Prawn::Document::Internals
54
52
  include PDF::Core::Annotations
55
53
  include PDF::Core::Destinations
56
- include Prawn::Document::GraphicsState
57
54
  include Prawn::Document::Security
58
55
  include Prawn::Text
59
56
  include Prawn::Graphics
60
57
  include Prawn::Images
61
58
  include Prawn::Stamp
62
59
  include Prawn::SoftMask
60
+ include Prawn::TransformationStack
63
61
 
64
62
  # @group Extension API
65
63
 
66
64
  # NOTE: We probably need to rethink the options validation system, but this
67
65
  # constant temporarily allows for extensions to modify the list.
68
66
 
69
- VALID_OPTIONS = [:page_size, :page_layout, :margin, :left_margin,
70
- :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
71
- :compress, :skip_encoding, :background, :info,
72
- :text_formatter, :print_scaling]
67
+ VALID_OPTIONS = %i[
68
+ page_size page_layout margin left_margin
69
+ right_margin top_margin bottom_margin skip_page_creation
70
+ compress background info
71
+ text_formatter print_scaling
72
+ ].freeze
73
73
 
74
74
  # Any module added to this array will be included into instances of
75
75
  # Prawn::Document at the per-object level. These will also be inherited by
@@ -98,13 +98,14 @@ module Prawn
98
98
 
99
99
  # @private
100
100
  def self.inherited(base)
101
+ super
101
102
  extensions.each { |e| base.extensions << e }
102
103
  end
103
104
 
104
105
  # @group Stable Attributes
105
106
 
106
107
  attr_accessor :margin_box
107
- attr_reader :margins, :y
108
+ attr_reader :margins, :y
108
109
  attr_accessor :page_number
109
110
 
110
111
  # @group Extension Attributes
@@ -140,8 +141,8 @@ module Prawn
140
141
  # pdf.draw_text content, :at => [200,720], :size => 32
141
142
  # end
142
143
  #
143
- def self.generate(filename,options={},&block)
144
- pdf = new(options,&block)
144
+ def self.generate(filename, options = {}, &block)
145
+ pdf = new(options, &block)
145
146
  pdf.render_file(filename)
146
147
  end
147
148
 
@@ -155,15 +156,22 @@ module Prawn
155
156
  # <tt>:right_margin</tt>:: Sets the right margin in points [0.5 inch]
156
157
  # <tt>:top_margin</tt>:: Sets the top margin in points [0.5 inch]
157
158
  # <tt>:bottom_margin</tt>:: Sets the bottom margin in points [0.5 inch]
158
- # <tt>:skip_page_creation</tt>:: Creates a document without starting the first page [false]
159
- # <tt>:compress</tt>:: Compresses content streams before rendering them [false]
160
- # <tt>:background</tt>:: An image path to be used as background on all pages [nil]
159
+ # <tt>:skip_page_creation</tt>:: Creates a document without starting the
160
+ # first page [false]
161
+ # <tt>:compress</tt>:: Compresses content streams before rendering them
162
+ # [false]
163
+ # <tt>:background</tt>:: An image path to be used as background on all pages
164
+ # [nil]
161
165
  # <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
162
- # <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
163
- # <tt>:text_formatter</tt>: The text formatter to use for <tt>:inline_format</tt>ted text [Prawn::Text::Formatted::Parser]
166
+ # <tt>:info</tt>:: Generic hash allowing for custom metadata properties
167
+ # [nil]
168
+ # <tt>:text_formatter</tt>: The text formatter to use for
169
+ # <tt>:inline_format</tt>ted text
170
+ # [Prawn::Text::Formatted::Parser]
164
171
  #
165
- # Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
166
- # of 100 points on every side except for the left, where it will be 50.
172
+ # Setting e.g. the :margin to 100 points and the :left_margin to 50 will
173
+ # result in margins of 100 points on every side except for the left, where
174
+ # it will be 50.
167
175
  #
168
176
  # The :margin can also be an array much like CSS shorthand:
169
177
  #
@@ -174,8 +182,8 @@ module Prawn
174
182
  # # Top is 10, right is 20, bottom is 30, left is 40.
175
183
  # :margin => [10, 20, 30, 40]
176
184
  #
177
- # Additionally, :page_size can be specified as a simple two value array giving
178
- # the width and height of the document you need in PDF Points.
185
+ # Additionally, :page_size can be specified as a simple two value array
186
+ # giving the width and height of the document you need in PDF Points.
179
187
  #
180
188
  # Usage:
181
189
  #
@@ -183,15 +191,17 @@ module Prawn
183
191
  # pdf = Prawn::Document.new
184
192
  #
185
193
  # # New document, A4 paper, landscaped
186
- # pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
194
+ # pdf = Prawn::Document.new(page_size: "A4", page_layout: :landscape)
187
195
  #
188
196
  # # New document, Custom size
189
- # pdf = Prawn::Document.new(:page_size => [200, 300])
197
+ # pdf = Prawn::Document.new(page_size: [200, 300])
190
198
  #
191
199
  # # New document, with background
192
- # pdf = Prawn::Document.new(:background => "#{Prawn::DATADIR}/images/pigs.jpg")
200
+ # pdf = Prawn::Document.new(
201
+ # background: "#{Prawn::DATADIR}/images/pigs.jpg"
202
+ # )
193
203
  #
194
- def initialize(options={},&block)
204
+ def initialize(options = {}, &block)
195
205
  options = options.dup
196
206
 
197
207
  Prawn.verify_options VALID_OPTIONS, options
@@ -200,22 +210,23 @@ module Prawn
200
210
  # raise NotImplementedError if options[:skip_page_creation]
201
211
 
202
212
  self.class.extensions.reverse_each { |e| extend e }
203
- @internal_state = PDF::Core::DocumentState.new(options)
204
- @internal_state.populate_pages_from_store(self)
205
- min_version(state.store.min_version) if state.store.min_version
213
+ self.state = PDF::Core::DocumentState.new(options)
214
+ state.populate_pages_from_store(self)
215
+ renderer.min_version(state.store.min_version) if state.store.min_version
206
216
 
207
- min_version(1.6) if options[:print_scaling] == :none
217
+ renderer.min_version(1.6) if options[:print_scaling] == :none
208
218
 
209
219
  @background = options[:background]
210
220
  @background_scale = options[:background_scale] || 1
211
- @font_size = 12
221
+ @font_size = 12
212
222
 
213
- @bounding_box = nil
214
- @margin_box = nil
223
+ @bounding_box = nil
224
+ @margin_box = nil
215
225
 
216
226
  @page_number = 0
217
227
 
218
- @text_formatter = options.delete(:text_formatter) || Text::Formatted::Parser
228
+ @text_formatter = options.delete(:text_formatter) ||
229
+ Text::Formatted::Parser
219
230
 
220
231
  options[:size] = options.delete(:page_size)
221
232
  options[:layout] = options.delete(:page_layout)
@@ -242,20 +253,28 @@ module Prawn
242
253
  # pdf.start_new_page(:margin => 100)
243
254
  #
244
255
  def start_new_page(options = {})
245
- if last_page = state.page
246
- last_page_size = last_page.size
247
- last_page_layout = last_page.layout
248
- last_page_margins = last_page.margins
256
+ last_page = state.page
257
+ if last_page
258
+ last_page_size = last_page.size
259
+ last_page_layout = last_page.layout
260
+ last_page_margins = last_page.margins.dup
249
261
  end
250
262
 
251
- page_options = {:size => options[:size] || last_page_size,
252
- :layout => options[:layout] || last_page_layout,
253
- :margins => last_page_margins}
263
+ page_options = {
264
+ size: options[:size] || last_page_size,
265
+ layout: options[:layout] || last_page_layout,
266
+ margins: last_page_margins
267
+ }
254
268
  if last_page
255
- new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
256
- #erase the color space so that it gets reset on new page for fussy pdf-readers
257
- new_graphic_state.color_space = {} if new_graphic_state
258
- page_options.merge!(:graphic_state => new_graphic_state)
269
+ if last_page.graphic_state
270
+ new_graphic_state = last_page.graphic_state.dup
271
+ end
272
+
273
+ # erase the color space so that it gets reset on new page for fussy
274
+ # pdf-readers
275
+ new_graphic_state&.color_space = {}
276
+
277
+ page_options[:graphic_state] = new_graphic_state
259
278
  end
260
279
 
261
280
  state.page = PDF::Core::Page.new(self, page_options)
@@ -275,7 +294,11 @@ module Prawn
275
294
  state.insert_page(state.page, @page_number)
276
295
  @page_number += 1
277
296
 
278
- canvas { image(@background, :scale => @background_scale, :at => bounds.top_left) } if @background
297
+ if @background
298
+ canvas do
299
+ image(@background, scale: @background_scale, at: bounds.top_left)
300
+ end
301
+ end
279
302
  @y = @bounding_box.absolute_top
280
303
 
281
304
  float do
@@ -284,6 +307,26 @@ module Prawn
284
307
  end
285
308
  end
286
309
 
310
+ # Remove page of the document by index
311
+ #
312
+ # pdf = Prawn::Document.new
313
+ # pdf.page_count #=> 1
314
+ # 3.times { pdf.start_new_page }
315
+ # pdf.page_count #=> 4
316
+ # pdf.delete_page(-1)
317
+ # pdf.page_count #=> 3
318
+ #
319
+ def delete_page(index)
320
+ return false if index.abs > (state.pages.count - 1)
321
+
322
+ state.pages.delete_at(index)
323
+
324
+ state.store.pages.data[:Kids].delete_at(index)
325
+ state.store.pages.data[:Count] -= 1
326
+ @page_number -= 1
327
+ true
328
+ end
329
+
287
330
  # Returns the number of pages in the document
288
331
  #
289
332
  # pdf = Prawn::Document.new
@@ -300,9 +343,9 @@ module Prawn
300
343
  #
301
344
  # See Prawn::Document#number_pages for a sample usage of this capability.
302
345
  #
303
- def go_to_page(k)
304
- @page_number = k
305
- state.page = state.pages[k-1]
346
+ def go_to_page(page_number)
347
+ @page_number = page_number
348
+ state.page = state.pages[page_number - 1]
306
349
  generate_margin_box
307
350
  @y = @bounding_box.absolute_top
308
351
  end
@@ -349,23 +392,13 @@ module Prawn
349
392
  # Renders the PDF document to string.
350
393
  # Pass an open file descriptor to render to file.
351
394
  #
352
- def render(output = StringIO.new)
353
- if output.instance_of?(StringIO)
354
- output.set_encoding(::Encoding::ASCII_8BIT)
355
- end
356
- finalize_all_page_contents
357
-
358
- render_header(output)
359
- render_body(output)
360
- render_xref(output)
361
- render_trailer(output)
362
- if output.instance_of?(StringIO)
363
- str = output.string
364
- str.force_encoding(::Encoding::ASCII_8BIT)
365
- return str
366
- else
367
- return nil
395
+ def render(*arguments, &block)
396
+ (1..page_count).each do |i|
397
+ go_to_page i
398
+ repeaters.each { |r| r.run(i) }
368
399
  end
400
+
401
+ renderer.render(*arguments, &block)
369
402
  end
370
403
 
371
404
  # Renders the PDF document to file.
@@ -373,7 +406,7 @@ module Prawn
373
406
  # pdf.render_file "foo.pdf"
374
407
  #
375
408
  def render_file(filename)
376
- File.open(filename, "wb") { |f| render(f) }
409
+ File.open(filename, 'wb') { |f| render(f) }
377
410
  end
378
411
 
379
412
  # The bounds method returns the current bounding box you are currently in,
@@ -382,14 +415,15 @@ module Prawn
382
415
  # block, the box defined by that call will be returned instead of the
383
416
  # document margin box.
384
417
  #
385
- # Another important point about bounding boxes is that all x and y measurements
386
- # within a bounding box code block are relative to the bottom left corner of the
387
- # bounding box.
418
+ # Another important point about bounding boxes is that all x and
419
+ # y measurements within a bounding box code block are relative to the bottom
420
+ # left corner of the bounding box.
388
421
  #
389
422
  # For example:
390
423
  #
391
424
  # Prawn::Document.new do
392
- # # In the default "margin box" of a Prawn document of 0.5in along each edge
425
+ # # In the default "margin box" of a Prawn document of 0.5in along each
426
+ # # edge
393
427
  #
394
428
  # # Draw a border around the page (the manual way)
395
429
  # stroke do
@@ -416,8 +450,8 @@ module Prawn
416
450
 
417
451
  # Sets Document#bounds to the BoundingBox provided. See above for a brief
418
452
  # description of what a bounding box is. This function is useful if you
419
- # really need to change the bounding box manually, but usually, just entering
420
- # and exiting bounding box code blocks is good enough.
453
+ # really need to change the bounding box manually, but usually, just
454
+ # entering and exiting bounding box code blocks is good enough.
421
455
  #
422
456
  def bounds=(bounding_box)
423
457
  @bounding_box = bounding_box
@@ -426,15 +460,15 @@ module Prawn
426
460
  # Moves up the document by n points relative to the current position inside
427
461
  # the current bounding box.
428
462
  #
429
- def move_up(n)
430
- self.y += n
463
+ def move_up(amount)
464
+ self.y += amount
431
465
  end
432
466
 
433
- # Moves down the document by n points relative to the current position inside
434
- # the current bounding box.
467
+ # Moves down the document by n points relative to the current position
468
+ # inside the current bounding box.
435
469
  #
436
- def move_down(n)
437
- self.y -= n
470
+ def move_down(amount)
471
+ self.y -= amount
438
472
  end
439
473
 
440
474
  # Moves down the document and then executes a block.
@@ -478,7 +512,6 @@ module Prawn
478
512
  move_down(y)
479
513
  end
480
514
 
481
-
482
515
  # Indents the specified number of PDF points for the duration of the block
483
516
  #
484
517
  # pdf.text "some text"
@@ -495,85 +528,88 @@ module Prawn
495
528
  bounds.indent(left, right, &block)
496
529
  end
497
530
 
498
- # Places a text box on specified pages for page numbering. This should be called
499
- # towards the end of document creation, after all your content is already in
500
- # place. In your template string, <page> refers to the current page, and
501
- # <total> refers to the total amount of pages in the document. Page numbering should
502
- # occur at the end of your Prawn::Document.generate block because the method iterates
503
- # through existing pages after they are created.
531
+ # Places a text box on specified pages for page numbering. This should be
532
+ # called towards the end of document creation, after all your content is
533
+ # already in place. In your template string, <page> refers to the current
534
+ # page, and <total> refers to the total amount of pages in the document.
535
+ # Page numbering should occur at the end of your Prawn::Document.generate
536
+ # block because the method iterates through existing pages after they are
537
+ # created.
504
538
  #
505
539
  # Parameters are:
506
540
  #
507
541
  # <tt>string</tt>:: Template string for page number wording.
508
542
  # Should include '<page>' and, optionally, '<total>'.
509
543
  # <tt>options</tt>:: A hash for page numbering and text box options.
510
- # <tt>:page_filter</tt>:: A filter to specify which pages to place page numbers on.
511
- # Refer to the method 'page_match?'
544
+ # <tt>:page_filter</tt>:: A filter to specify which pages to place page
545
+ # numbers on. Refer to the method 'page_match?'
512
546
  # <tt>:start_count_at</tt>:: The starting count to increment pages from.
513
- # <tt>:total_pages</tt>:: If provided, will replace <total> with the value given.
514
- # Useful to override the total number of pages when using
515
- # the start_count_at option.
547
+ # <tt>:total_pages</tt>:: If provided, will replace <total> with the
548
+ # value given. Useful to override the total
549
+ # number of pages when using the start_count_at
550
+ # option.
516
551
  # <tt>:color</tt>:: Text fill color.
517
552
  #
518
- # Please refer to Prawn::Text::text_box for additional options concerning text
519
- # formatting and placement.
520
- #
521
- # Example: Print page numbers on every page except for the first. Start counting from
522
- # five.
553
+ # Please refer to Prawn::Text::text_box for additional options
554
+ # concerning text formatting and placement.
523
555
  #
524
- # Prawn::Document.generate("page_with_numbering.pdf") do
525
- # number_pages "<page> in a total of <total>",
526
- # {:start_count_at => 5,
527
- # :page_filter => lambda{ |pg| pg != 1 },
528
- # :at => [bounds.right - 50, 0],
529
- # :align => :right,
530
- # :size => 14}
531
- # end
556
+ # Example:
557
+ # Print page numbers on every page except for the first. Start counting
558
+ # from five.
559
+ #
560
+ # Prawn::Document.generate("page_with_numbering.pdf") do
561
+ # number_pages "<page> in a total of <total>", {
562
+ # start_count_at: 5,
563
+ # page_filter: lambda { |pg| pg != 1 },
564
+ # at: [bounds.right - 50, 0],
565
+ # align: :right,
566
+ # size: 14
567
+ # }
568
+ # end
532
569
  #
533
- def number_pages(string, options={})
570
+ def number_pages(string, options = {})
534
571
  opts = options.dup
535
572
  start_count_at = opts.delete(:start_count_at).to_i
536
- page_filter = if opts.has_key?(:page_filter)
537
- opts.delete(:page_filter)
538
- else
539
- :all
540
- end
573
+
574
+ page_filter =
575
+ if opts.key?(:page_filter)
576
+ opts.delete(:page_filter)
577
+ else
578
+ :all
579
+ end
580
+
541
581
  total_pages = opts.delete(:total_pages)
542
582
  txtcolor = opts.delete(:color)
543
583
  # An explicit height so that we can draw page numbers in the margins
544
- opts[:height] = 50 unless opts.has_key?(:height)
584
+ opts[:height] = 50 unless opts.key?(:height)
545
585
 
546
586
  start_count = false
547
587
  pseudopage = 0
548
588
  (1..page_count).each do |p|
549
589
  unless start_count
550
- pseudopage = case start_count_at
551
- when 0
552
- 1
553
- else
554
- start_count_at.to_i
555
- end
590
+ pseudopage =
591
+ case start_count_at
592
+ when 0
593
+ 1
594
+ else
595
+ start_count_at.to_i
596
+ end
556
597
  end
557
598
  if page_match?(page_filter, p)
558
599
  go_to_page(p)
559
- # have to use fill_color here otherwise text reverts back to default fill color
600
+ # have to use fill_color here otherwise text reverts back to default
601
+ # fill color
560
602
  fill_color txtcolor unless txtcolor.nil?
561
603
  total_pages = total_pages.nil? ? page_count : total_pages
562
- str = string.gsub("<page>","#{pseudopage}").gsub("<total>","#{total_pages}")
604
+ str = string.gsub('<page>', pseudopage.to_s)
605
+ .gsub('<total>', total_pages.to_s)
563
606
  text_box str, opts
564
- start_count = true # increment page count as soon as first match found
607
+ start_count = true # increment page count as soon as first match found
565
608
  end
566
609
  pseudopage += 1 if start_count
567
610
  end
568
611
  end
569
612
 
570
- # Returns true if content streams will be compressed before rendering,
571
- # false otherwise
572
- #
573
- def compression_enabled?
574
- !!state.compress
575
- end
576
-
577
613
  # @group Experimental API
578
614
 
579
615
  # Attempts to group the given block vertically within the current context.
@@ -586,21 +622,21 @@ module Prawn
586
622
  # the current page or column.
587
623
  #
588
624
  # @private
589
- def group(*a, &b)
625
+ def group(*_arguments)
590
626
  raise NotImplementedError,
591
- "Document#group has been disabled because its implementation "+
592
- "lead to corrupted documents whenever a page boundary was "+
593
- "crossed. We will try to work on reimplementing it in a "+
594
- "future release"
627
+ 'Document#group has been disabled because its implementation ' \
628
+ 'lead to corrupted documents whenever a page boundary was ' \
629
+ 'crossed. We will try to work on reimplementing it in a ' \
630
+ 'future release'
595
631
  end
596
632
 
597
633
  # @private
598
634
  def transaction
599
635
  raise NotImplementedError,
600
- "Document#transaction has been disabled because its implementation "+
601
- "lead to corrupted documents whenever a page boundary was "+
602
- "crossed. We will try to work on reimplementing it in a "+
603
- "future release"
636
+ 'Document#transaction has been disabled because its implementation ' \
637
+ 'lead to corrupted documents whenever a page boundary was ' \
638
+ 'crossed. We will try to work on reimplementing it in a ' \
639
+ 'future release'
604
640
  end
605
641
 
606
642
  # Provides a way to execute a block of code repeatedly based on a
@@ -618,9 +654,9 @@ module Prawn
618
654
  when :all
619
655
  true
620
656
  when :odd
621
- page_number % 2 == 1
657
+ page_number.odd?
622
658
  when :even
623
- page_number % 2 == 0
659
+ page_number.even?
624
660
  when Range, Array
625
661
  page_filter.include?(page_number)
626
662
  when Proc
@@ -631,20 +667,20 @@ module Prawn
631
667
  # @private
632
668
 
633
669
  def mask(*fields)
634
- # Stores the current state of the named attributes, executes the block, and
635
- # then restores the original values after the block has executed.
636
- # -- I will remove the nodoc if/when this feature is a little less hacky
670
+ # Stores the current state of the named attributes, executes the block,
671
+ # and then restores the original values after the block has executed.
672
+ # -- I will remove the nodoc if/when this feature is a little less hacky
637
673
  stored = {}
638
- fields.each { |f| stored[f] = send(f) }
674
+ fields.each { |f| stored[f] = public_send(f) }
639
675
  yield
640
- fields.each { |f| send("#{f}=", stored[f]) }
676
+ fields.each { |f| public_send("#{f}=", stored[f]) }
641
677
  end
642
678
 
643
679
  # @group Extension API
644
680
 
645
681
  def initialize_first_page(options)
646
682
  if options[:skip_page_creation]
647
- start_new_page(options.merge(:orphan => true))
683
+ start_new_page(options.merge(orphan: true))
648
684
  else
649
685
  start_new_page(options)
650
686
  end
@@ -653,9 +689,7 @@ module Prawn
653
689
  ## Internals. Don't depend on them!
654
690
 
655
691
  # @private
656
- def state
657
- @internal_state
658
- end
692
+ attr_accessor :state
659
693
 
660
694
  # @private
661
695
  def page
@@ -664,12 +698,11 @@ module Prawn
664
698
 
665
699
  private
666
700
 
667
-
668
- # setting override_settings to true ensures that a new graphic state does not end up using
669
- # previous settings.
701
+ # setting override_settings to true ensures that a new graphic state does
702
+ # not end up using previous settings.
670
703
  def use_graphic_settings(override_settings = false)
671
- set_fill_color if current_fill_color != "000000" || override_settings
672
- set_stroke_color if current_stroke_color != "000000" || override_settings
704
+ set_fill_color if current_fill_color != '000000' || override_settings
705
+ set_stroke_color if current_stroke_color != '000000' || override_settings
673
706
  write_line_width if line_width != 1 || override_settings
674
707
  write_stroke_cap_style if cap_style != :butt || override_settings
675
708
  write_stroke_join_style if join_style != :miter || override_settings
@@ -678,14 +711,16 @@ module Prawn
678
711
 
679
712
  def generate_margin_box
680
713
  old_margin_box = @margin_box
681
- page = state.page
714
+ page = state.page
682
715
 
683
716
  @margin_box = BoundingBox.new(
684
717
  self,
685
- nil, # margin box has no parent
686
- [ page.margins[:left], page.dimensions[-1] - page.margins[:top] ] ,
687
- :width => page.dimensions[-2] - (page.margins[:left] + page.margins[:right]),
688
- :height => page.dimensions[-1] - (page.margins[:top] + page.margins[:bottom])
718
+ nil, # margin box has no parent
719
+ [page.margins[:left], page.dimensions[-1] - page.margins[:top]],
720
+ width: page.dimensions[-2] -
721
+ (page.margins[:left] + page.margins[:right]),
722
+ height: page.dimensions[-1] -
723
+ (page.margins[:top] + page.margins[:bottom])
689
724
  )
690
725
 
691
726
  # This check maintains indentation settings across page breaks
@@ -696,30 +731,30 @@ module Prawn
696
731
 
697
732
  # we must update bounding box if not flowing from the previous page
698
733
  #
699
- @bounding_box = @margin_box unless @bounding_box && @bounding_box.parent
734
+ @bounding_box = @margin_box unless @bounding_box&.parent
700
735
  end
701
736
 
702
737
  def apply_margin_options(options)
703
- if options[:margin]
704
- # Treat :margin as CSS shorthand with 1-4 values.
705
- margin = Array(options[:margin])
706
- positions = { 4 => [0,1,2,3], 3 => [0,1,2,1],
707
- 2 => [0,1,0,1], 1 => [0,0,0,0] }[margin.length]
708
-
709
- [:top, :right, :bottom, :left].zip(positions).each do |p,i|
710
- options[:"#{p}_margin"] ||= margin[i]
711
- end
712
- end
713
-
714
- [:left,:right,:top,:bottom].each do |side|
715
- if margin = options[:"#{side}_margin"]
716
- state.page.margins[side] = margin
717
- end
738
+ sides = %i[top right bottom left]
739
+ margin = Array(options[:margin])
740
+
741
+ # Treat :margin as CSS shorthand with 1-4 values.
742
+ positions = {
743
+ 4 => [0, 1, 2, 3],
744
+ 3 => [0, 1, 2, 1],
745
+ 2 => [0, 1, 0, 1],
746
+ 1 => [0, 0, 0, 0],
747
+ 0 => []
748
+ }[margin.length]
749
+
750
+ sides.zip(positions).each do |side, pos|
751
+ new_margin = options[:"#{side}_margin"] || (margin[pos] if pos)
752
+ state.page.margins[side] = new_margin if new_margin
718
753
  end
719
754
  end
720
755
 
721
756
  def font_metric_cache #:nodoc:
722
- @font_metric_cache ||= FontMetricCache.new( self )
757
+ @font_metric_cache ||= FontMetricCache.new(self)
723
758
  end
724
759
  end
725
760
  end