prawn 0.13.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
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,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"
10
- require "prawn/document/bounding_box"
11
- require "prawn/document/column_box"
12
- require "prawn/document/internals"
13
- require "prawn/document/span"
14
- require "prawn/document/snapshot"
15
- require "prawn/document/graphics_state"
9
+ require 'stringio'
16
10
 
17
- module Prawn
11
+ require_relative 'document/bounding_box'
12
+ require_relative 'document/column_box'
13
+ require_relative 'document/internals'
14
+ require_relative 'document/span'
18
15
 
16
+ module Prawn
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,14 +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::Snapshot
57
- include Prawn::Document::GraphicsState
58
54
  include Prawn::Document::Security
59
55
  include Prawn::Text
60
56
  include Prawn::Graphics
61
57
  include Prawn::Images
62
58
  include Prawn::Stamp
63
59
  include Prawn::SoftMask
60
+ include Prawn::TransformationStack
61
+
62
+ # @group Extension API
63
+
64
+ # NOTE: We probably need to rethink the options validation system, but this
65
+ # constant temporarily allows for extensions to modify the list.
66
+
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
64
73
 
65
74
  # Any module added to this array will be included into instances of
66
75
  # Prawn::Document at the per-object level. These will also be inherited by
@@ -82,14 +91,29 @@ module Prawn
82
91
  # party!
83
92
  # end
84
93
  #
94
+ #
85
95
  def self.extensions
86
96
  @extensions ||= []
87
97
  end
88
98
 
89
- def self.inherited(base) #:nodoc:
99
+ # @private
100
+ def self.inherited(base)
101
+ super
90
102
  extensions.each { |e| base.extensions << e }
91
103
  end
92
104
 
105
+ # @group Stable Attributes
106
+
107
+ attr_accessor :margin_box
108
+ attr_reader :margins, :y
109
+ attr_accessor :page_number
110
+
111
+ # @group Extension Attributes
112
+
113
+ attr_accessor :text_formatter
114
+
115
+ # @group Stable API
116
+
93
117
  # Creates and renders a PDF document.
94
118
  #
95
119
  # When using the implicit block form, Prawn will evaluate the block
@@ -117,32 +141,37 @@ module Prawn
117
141
  # pdf.draw_text content, :at => [200,720], :size => 32
118
142
  # end
119
143
  #
120
- def self.generate(filename,options={},&block)
121
- pdf = new(options,&block)
144
+ def self.generate(filename, options = {}, &block)
145
+ pdf = new(options, &block)
122
146
  pdf.render_file(filename)
123
147
  end
124
148
 
125
149
  # Creates a new PDF Document. The following options are available (with
126
150
  # the default values marked in [])
127
151
  #
128
- # <tt>:page_size</tt>:: One of the Document::PageGeometry sizes [LETTER]
152
+ # <tt>:page_size</tt>:: One of the PDF::Core::PageGeometry sizes [LETTER]
129
153
  # <tt>:page_layout</tt>:: Either <tt>:portrait</tt> or <tt>:landscape</tt>
130
154
  # <tt>:margin</tt>:: Sets the margin on all sides in points [0.5 inch]
131
155
  # <tt>:left_margin</tt>:: Sets the left margin in points [0.5 inch]
132
156
  # <tt>:right_margin</tt>:: Sets the right margin in points [0.5 inch]
133
157
  # <tt>:top_margin</tt>:: Sets the top margin in points [0.5 inch]
134
158
  # <tt>:bottom_margin</tt>:: Sets the bottom margin in points [0.5 inch]
135
- # <tt>:skip_page_creation</tt>:: Creates a document without starting the first page [false]
136
- # <tt>:compress</tt>:: Compresses content streams before rendering them [false]
137
- # <tt>:optimize_objects</tt>:: Reduce number of PDF objects in output, at expense of render time [false]
138
- # <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]
139
165
  # <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
140
- # <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
141
- # <tt>:template</tt>:: The path to an existing PDF file to use as a template [nil]
142
- # <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]
143
171
  #
144
- # Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
145
- # 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.
146
175
  #
147
176
  # The :margin can also be an array much like CSS shorthand:
148
177
  #
@@ -153,8 +182,8 @@ module Prawn
153
182
  # # Top is 10, right is 20, bottom is 30, left is 40.
154
183
  # :margin => [10, 20, 30, 40]
155
184
  #
156
- # Additionally, :page_size can be specified as a simple two value array giving
157
- # 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.
158
187
  #
159
188
  # Usage:
160
189
  #
@@ -162,54 +191,47 @@ module Prawn
162
191
  # pdf = Prawn::Document.new
163
192
  #
164
193
  # # New document, A4 paper, landscaped
165
- # pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
194
+ # pdf = Prawn::Document.new(page_size: "A4", page_layout: :landscape)
166
195
  #
167
196
  # # New document, Custom size
168
- # pdf = Prawn::Document.new(:page_size => [200, 300])
197
+ # pdf = Prawn::Document.new(page_size: [200, 300])
169
198
  #
170
199
  # # New document, with background
171
- # pdf = Prawn::Document.new(:background => "#{Prawn::DATADIR}/images/pigs.jpg")
200
+ # pdf = Prawn::Document.new(
201
+ # background: "#{Prawn::DATADIR}/images/pigs.jpg"
202
+ # )
172
203
  #
173
- def initialize(options={},&block)
204
+ def initialize(options = {}, &block)
174
205
  options = options.dup
175
206
 
176
- Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
177
- :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
178
- :compress, :skip_encoding, :background, :info,
179
- :optimize_objects, :template, :text_formatter], options
207
+ Prawn.verify_options VALID_OPTIONS, options
180
208
 
181
209
  # need to fix, as the refactoring breaks this
182
210
  # raise NotImplementedError if options[:skip_page_creation]
183
211
 
184
212
  self.class.extensions.reverse_each { |e| extend e }
185
- @internal_state = PDF::Core::DocumentState.new(options)
186
- @internal_state.populate_pages_from_store(self)
187
- 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
216
+
217
+ renderer.min_version(1.6) if options[:print_scaling] == :none
188
218
 
189
219
  @background = options[:background]
190
220
  @background_scale = options[:background_scale] || 1
191
- @font_size = 12
221
+ @font_size = 12
192
222
 
193
- @bounding_box = nil
194
- @margin_box = nil
223
+ @bounding_box = nil
224
+ @margin_box = nil
195
225
 
196
226
  @page_number = 0
197
227
 
198
- @text_formatter = options.delete(:text_formatter) || Text::Formatted::Parser
228
+ @text_formatter = options.delete(:text_formatter) ||
229
+ Text::Formatted::Parser
199
230
 
200
231
  options[:size] = options.delete(:page_size)
201
232
  options[:layout] = options.delete(:page_layout)
202
233
 
203
- if options[:template]
204
- fresh_content_streams(options)
205
- go_to_page(1)
206
- else
207
- if options[:skip_page_creation] || options[:template]
208
- start_new_page(options.merge(:orphan => true))
209
- else
210
- start_new_page(options)
211
- end
212
- end
234
+ initialize_first_page(options)
213
235
 
214
236
  @bounding_box = @margin_box
215
237
 
@@ -218,19 +240,7 @@ module Prawn
218
240
  end
219
241
  end
220
242
 
221
- attr_accessor :margin_box
222
- attr_reader :margins, :y
223
- attr_writer :font_size
224
- attr_accessor :page_number
225
- attr_accessor :text_formatter
226
-
227
- def state
228
- @internal_state
229
- end
230
-
231
- def page
232
- state.page
233
- end
243
+ # @group Stable API
234
244
 
235
245
  # Creates and advances to a new page in the document.
236
246
  #
@@ -242,31 +252,30 @@ module Prawn
242
252
  # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
243
253
  # pdf.start_new_page(:margin => 100)
244
254
  #
245
- # A template for a page can be specified by pointing to the path of and existing pdf.
246
- # One can also specify which page of the template which defaults otherwise to 1.
247
- #
248
- # pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
249
- #
250
- # Note: templates get indexed by either the object_id of the filename or stream
251
- # entered so that if you reuse the same template multiple times be sure to use the
252
- # same instance for more efficient use of resources and smaller rendered pdfs.
253
255
  def start_new_page(options = {})
254
- if last_page = state.page
255
- last_page_size = last_page.size
256
- last_page_layout = last_page.layout
257
- 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
258
261
  end
259
262
 
260
- page_options = {:size => options[:size] || last_page_size,
261
- :layout => options[:layout] || last_page_layout,
262
- :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
+ }
263
268
  if last_page
264
- new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
265
- #erase the color space so that it gets reset on new page for fussy pdf-readers
266
- new_graphic_state.color_space = {} if new_graphic_state
267
- 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
268
278
  end
269
- merge_template_options(page_options, options) if options[:template]
270
279
 
271
280
  state.page = PDF::Core::Page.new(self, page_options)
272
281
 
@@ -279,15 +288,17 @@ module Prawn
279
288
  @bounding_box = @margin_box
280
289
  end
281
290
 
282
- state.page.new_content_stream if options[:template]
283
- use_graphic_settings(options[:template])
284
- forget_text_rendering_mode! if options[:template]
291
+ use_graphic_settings
285
292
 
286
293
  unless options[:orphan]
287
294
  state.insert_page(state.page, @page_number)
288
295
  @page_number += 1
289
296
 
290
- 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
291
302
  @y = @bounding_box.absolute_top
292
303
 
293
304
  float do
@@ -296,6 +307,26 @@ module Prawn
296
307
  end
297
308
  end
298
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
+
299
330
  # Returns the number of pages in the document
300
331
  #
301
332
  # pdf = Prawn::Document.new
@@ -312,9 +343,9 @@ module Prawn
312
343
  #
313
344
  # See Prawn::Document#number_pages for a sample usage of this capability.
314
345
  #
315
- def go_to_page(k)
316
- @page_number = k
317
- 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]
318
349
  generate_margin_box
319
350
  @y = @bounding_box.absolute_top
320
351
  end
@@ -361,20 +392,13 @@ module Prawn
361
392
  # Renders the PDF document to string.
362
393
  # Pass an open file descriptor to render to file.
363
394
  #
364
- def render(output = StringIO.new)
365
- finalize_all_page_contents
366
-
367
- render_header(output)
368
- render_body(output)
369
- render_xref(output)
370
- render_trailer(output)
371
- if output.instance_of?(StringIO)
372
- str = output.string
373
- str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
374
- return str
375
- else
376
- 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) }
377
399
  end
400
+
401
+ renderer.render(*arguments, &block)
378
402
  end
379
403
 
380
404
  # Renders the PDF document to file.
@@ -382,8 +406,7 @@ module Prawn
382
406
  # pdf.render_file "foo.pdf"
383
407
  #
384
408
  def render_file(filename)
385
- Kernel.const_defined?("Encoding") ? mode = "wb:ASCII-8BIT" : mode = "wb"
386
- File.open(filename,mode) { |f| render(f) }
409
+ File.open(filename, 'wb') { |f| render(f) }
387
410
  end
388
411
 
389
412
  # The bounds method returns the current bounding box you are currently in,
@@ -392,14 +415,15 @@ module Prawn
392
415
  # block, the box defined by that call will be returned instead of the
393
416
  # document margin box.
394
417
  #
395
- # Another important point about bounding boxes is that all x and y measurements
396
- # within a bounding box code block are relative to the bottom left corner of the
397
- # 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.
398
421
  #
399
422
  # For example:
400
423
  #
401
424
  # Prawn::Document.new do
402
- # # 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
403
427
  #
404
428
  # # Draw a border around the page (the manual way)
405
429
  # stroke do
@@ -419,14 +443,15 @@ module Prawn
419
443
 
420
444
  # Returns the innermost non-stretchy bounding box.
421
445
  #
446
+ # @private
422
447
  def reference_bounds
423
448
  @bounding_box.reference_bounds
424
449
  end
425
450
 
426
451
  # Sets Document#bounds to the BoundingBox provided. See above for a brief
427
452
  # description of what a bounding box is. This function is useful if you
428
- # really need to change the bounding box manually, but usually, just entering
429
- # 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.
430
455
  #
431
456
  def bounds=(bounding_box)
432
457
  @bounding_box = bounding_box
@@ -435,15 +460,15 @@ module Prawn
435
460
  # Moves up the document by n points relative to the current position inside
436
461
  # the current bounding box.
437
462
  #
438
- def move_up(n)
439
- self.y += n
463
+ def move_up(amount)
464
+ self.y += amount
440
465
  end
441
466
 
442
- # Moves down the document by n points relative to the current position inside
443
- # the current bounding box.
467
+ # Moves down the document by n points relative to the current position
468
+ # inside the current bounding box.
444
469
  #
445
- def move_down(n)
446
- self.y -= n
470
+ def move_down(amount)
471
+ self.y -= amount
447
472
  end
448
473
 
449
474
  # Moves down the document and then executes a block.
@@ -487,7 +512,6 @@ module Prawn
487
512
  move_down(y)
488
513
  end
489
514
 
490
-
491
515
  # Indents the specified number of PDF points for the duration of the block
492
516
  #
493
517
  # pdf.text "some text"
@@ -504,119 +528,117 @@ module Prawn
504
528
  bounds.indent(left, right, &block)
505
529
  end
506
530
 
507
-
508
- def mask(*fields) # :nodoc:
509
- # Stores the current state of the named attributes, executes the block, and
510
- # then restores the original values after the block has executed.
511
- # -- I will remove the nodoc if/when this feature is a little less hacky
512
- stored = {}
513
- fields.each { |f| stored[f] = send(f) }
514
- yield
515
- fields.each { |f| send("#{f}=", stored[f]) }
516
- end
517
-
518
- # Attempts to group the given block vertically within the current context.
519
- # First attempts to render it in the current position on the current page.
520
- # If that attempt overflows, it is tried anew after starting a new context
521
- # (page or column). Returns a logically true value if the content fits in
522
- # one page/column, false if a new page or column was needed.
523
- #
524
- # Raises CannotGroup if the provided content is too large to fit alone in
525
- # the current page or column.
526
- #
527
- def group(second_attempt=false)
528
- old_bounding_box = @bounding_box
529
- @bounding_box = SimpleDelegator.new(@bounding_box)
530
-
531
- def @bounding_box.move_past_bottom
532
- raise RollbackTransaction
533
- end
534
-
535
- success = transaction { yield }
536
-
537
- @bounding_box = old_bounding_box
538
-
539
- unless success
540
- raise Prawn::Errors::CannotGroup if second_attempt
541
- old_bounding_box.move_past_bottom
542
- group(second_attempt=true) { yield }
543
- end
544
-
545
- success
546
- end
547
-
548
- # Places a text box on specified pages for page numbering. This should be called
549
- # towards the end of document creation, after all your content is already in
550
- # place. In your template string, <page> refers to the current page, and
551
- # <total> refers to the total amount of pages in the document. Page numbering should
552
- # occur at the end of your Prawn::Document.generate block because the method iterates
553
- # 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.
554
538
  #
555
539
  # Parameters are:
556
540
  #
557
541
  # <tt>string</tt>:: Template string for page number wording.
558
542
  # Should include '<page>' and, optionally, '<total>'.
559
543
  # <tt>options</tt>:: A hash for page numbering and text box options.
560
- # <tt>:page_filter</tt>:: A filter to specify which pages to place page numbers on.
561
- # 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?'
562
546
  # <tt>:start_count_at</tt>:: The starting count to increment pages from.
563
- # <tt>:total_pages</tt>:: If provided, will replace <total> with the value given.
564
- # Useful to override the total number of pages when using
565
- # 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.
566
551
  # <tt>:color</tt>:: Text fill color.
567
552
  #
568
- # Please refer to Prawn::Text::text_box for additional options concerning text
569
- # formatting and placement.
570
- #
571
- # Example: Print page numbers on every page except for the first. Start counting from
572
- # five.
553
+ # Please refer to Prawn::Text::text_box for additional options
554
+ # concerning text formatting and placement.
573
555
  #
574
- # Prawn::Document.generate("page_with_numbering.pdf") do
575
- # number_pages "<page> in a total of <total>",
576
- # {:start_count_at => 5,
577
- # :page_filter => lambda{ |pg| pg != 1 },
578
- # :at => [bounds.right - 50, 0],
579
- # :align => :right,
580
- # :size => 14}
581
- # 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
582
569
  #
583
- def number_pages(string, options={})
570
+ def number_pages(string, options = {})
584
571
  opts = options.dup
585
572
  start_count_at = opts.delete(:start_count_at).to_i
586
- page_filter = if opts.has_key?(:page_filter)
587
- opts.delete(:page_filter)
588
- else
589
- :all
590
- end
573
+
574
+ page_filter =
575
+ if opts.key?(:page_filter)
576
+ opts.delete(:page_filter)
577
+ else
578
+ :all
579
+ end
580
+
591
581
  total_pages = opts.delete(:total_pages)
592
582
  txtcolor = opts.delete(:color)
593
583
  # An explicit height so that we can draw page numbers in the margins
594
- opts[:height] = 50 unless opts.has_key?(:height)
584
+ opts[:height] = 50 unless opts.key?(:height)
595
585
 
596
586
  start_count = false
597
587
  pseudopage = 0
598
588
  (1..page_count).each do |p|
599
589
  unless start_count
600
- pseudopage = case start_count_at
601
- when 0
602
- 1
603
- else
604
- start_count_at.to_i
605
- end
590
+ pseudopage =
591
+ case start_count_at
592
+ when 0
593
+ 1
594
+ else
595
+ start_count_at.to_i
596
+ end
606
597
  end
607
598
  if page_match?(page_filter, p)
608
599
  go_to_page(p)
609
- # 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
610
602
  fill_color txtcolor unless txtcolor.nil?
611
603
  total_pages = total_pages.nil? ? page_count : total_pages
612
- str = string.gsub("<page>","#{pseudopage}").gsub("<total>","#{total_pages}")
604
+ str = string.gsub('<page>', pseudopage.to_s)
605
+ .gsub('<total>', total_pages.to_s)
613
606
  text_box str, opts
614
- 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
615
608
  end
616
609
  pseudopage += 1 if start_count
617
610
  end
618
611
  end
619
612
 
613
+ # @group Experimental API
614
+
615
+ # Attempts to group the given block vertically within the current context.
616
+ # First attempts to render it in the current position on the current page.
617
+ # If that attempt overflows, it is tried anew after starting a new context
618
+ # (page or column). Returns a logically true value if the content fits in
619
+ # one page/column, false if a new page or column was needed.
620
+ #
621
+ # Raises CannotGroup if the provided content is too large to fit alone in
622
+ # the current page or column.
623
+ #
624
+ # @private
625
+ def group(*_arguments)
626
+ raise NotImplementedError,
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'
631
+ end
632
+
633
+ # @private
634
+ def transaction
635
+ raise NotImplementedError,
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'
640
+ end
641
+
620
642
  # Provides a way to execute a block of code repeatedly based on a
621
643
  # page_filter.
622
644
  #
@@ -632,9 +654,9 @@ module Prawn
632
654
  when :all
633
655
  true
634
656
  when :odd
635
- page_number % 2 == 1
657
+ page_number.odd?
636
658
  when :even
637
- page_number % 2 == 0
659
+ page_number.even?
638
660
  when Range, Array
639
661
  page_filter.include?(page_number)
640
662
  when Proc
@@ -642,26 +664,45 @@ module Prawn
642
664
  end
643
665
  end
644
666
 
667
+ # @private
645
668
 
646
- # Returns true if content streams will be compressed before rendering,
647
- # false otherwise
648
- #
649
- def compression_enabled?
650
- !!state.compress
669
+ def mask(*fields)
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
673
+ stored = {}
674
+ fields.each { |f| stored[f] = public_send(f) }
675
+ yield
676
+ fields.each { |f| public_send("#{f}=", stored[f]) }
651
677
  end
652
678
 
653
- private
679
+ # @group Extension API
680
+
681
+ def initialize_first_page(options)
682
+ if options[:skip_page_creation]
683
+ start_new_page(options.merge(orphan: true))
684
+ else
685
+ start_new_page(options)
686
+ end
687
+ end
688
+
689
+ ## Internals. Don't depend on them!
690
+
691
+ # @private
692
+ attr_accessor :state
654
693
 
655
- def merge_template_options(page_options, options)
656
- object_id = state.store.import_page(options[:template], options[:template_page] || 1)
657
- page_options.merge!(:object_id => object_id, :page_template => true)
694
+ # @private
695
+ def page
696
+ state.page
658
697
  end
659
698
 
660
- # setting override_settings to true ensures that a new graphic state does not end up using
661
- # previous settings especially from imported template streams
699
+ private
700
+
701
+ # setting override_settings to true ensures that a new graphic state does
702
+ # not end up using previous settings.
662
703
  def use_graphic_settings(override_settings = false)
663
- set_fill_color if current_fill_color != "000000" || override_settings
664
- 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
665
706
  write_line_width if line_width != 1 || override_settings
666
707
  write_stroke_cap_style if cap_style != :butt || override_settings
667
708
  write_stroke_join_style if join_style != :miter || override_settings
@@ -670,14 +711,16 @@ module Prawn
670
711
 
671
712
  def generate_margin_box
672
713
  old_margin_box = @margin_box
673
- page = state.page
714
+ page = state.page
674
715
 
675
716
  @margin_box = BoundingBox.new(
676
717
  self,
677
- nil, # margin box has no parent
678
- [ page.margins[:left], page.dimensions[-1] - page.margins[:top] ] ,
679
- :width => page.dimensions[-2] - (page.margins[:left] + page.margins[:right]),
680
- :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])
681
724
  )
682
725
 
683
726
  # This check maintains indentation settings across page breaks
@@ -688,32 +731,30 @@ module Prawn
688
731
 
689
732
  # we must update bounding box if not flowing from the previous page
690
733
  #
691
- # FIXME: This may have a bug where the old margin is restored
692
- # when the bounding box exits.
693
- @bounding_box = @margin_box if old_margin_box == @bounding_box
734
+ @bounding_box = @margin_box unless @bounding_box&.parent
694
735
  end
695
736
 
696
737
  def apply_margin_options(options)
697
- if options[:margin]
698
- # Treat :margin as CSS shorthand with 1-4 values.
699
- margin = Array(options[:margin])
700
- positions = { 4 => [0,1,2,3], 3 => [0,1,2,1],
701
- 2 => [0,1,0,1], 1 => [0,0,0,0] }[margin.length]
702
-
703
- [:top, :right, :bottom, :left].zip(positions).each do |p,i|
704
- options[:"#{p}_margin"] ||= margin[i]
705
- end
706
- end
707
-
708
- [:left,:right,:top,:bottom].each do |side|
709
- if margin = options[:"#{side}_margin"]
710
- state.page.margins[side] = margin
711
- 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
712
753
  end
713
754
  end
714
755
 
715
756
  def font_metric_cache #:nodoc:
716
- @font_metric_cache ||= FontMetricCache.new( self )
757
+ @font_metric_cache ||= FontMetricCache.new(self)
717
758
  end
718
759
  end
719
760
  end