prawn 0.13.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +10 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -16
  6. data/Rakefile +17 -39
  7. data/lib/prawn/document/bounding_box.rb +85 -42
  8. data/lib/prawn/document/column_box.rb +21 -11
  9. data/lib/prawn/document/internals.rb +40 -147
  10. data/lib/prawn/document/span.rb +25 -17
  11. data/lib/prawn/document.rb +286 -245
  12. data/lib/prawn/encoding.rb +68 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +204 -155
  15. data/lib/prawn/font_metric_cache.rb +25 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +7 -13
  18. data/lib/prawn/fonts/otf.rb +11 -0
  19. data/lib/prawn/fonts/ttc.rb +36 -0
  20. data/lib/prawn/{font → fonts}/ttf.rb +142 -80
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +6 -5
  23. data/lib/prawn/graphics/color.rb +47 -44
  24. data/lib/prawn/graphics/dash.rb +30 -13
  25. data/lib/prawn/graphics/join_style.rb +13 -6
  26. data/lib/prawn/graphics/patterns.rb +221 -90
  27. data/lib/prawn/graphics/transformation.rb +21 -12
  28. data/lib/prawn/graphics/transparency.rb +21 -17
  29. data/lib/prawn/graphics.rb +155 -128
  30. data/lib/prawn/{layout/grid.rb → grid.rb} +110 -47
  31. data/lib/prawn/image_handler.rb +16 -2
  32. data/lib/prawn/images/image.rb +4 -2
  33. data/lib/prawn/images/jpg.rb +39 -30
  34. data/lib/prawn/images/png.rb +132 -169
  35. data/lib/prawn/images.rb +70 -62
  36. data/lib/prawn/measurement_extensions.rb +15 -10
  37. data/lib/prawn/measurements.rb +22 -23
  38. data/lib/prawn/outline.rb +301 -13
  39. data/lib/prawn/repeater.rb +19 -17
  40. data/lib/prawn/security/arcfour.rb +54 -0
  41. data/lib/prawn/security.rb +108 -86
  42. data/lib/prawn/soft_mask.rb +40 -41
  43. data/lib/prawn/stamp.rb +29 -12
  44. data/lib/prawn/text/box.rb +27 -29
  45. data/lib/prawn/text/formatted/arranger.rb +110 -67
  46. data/lib/prawn/text/formatted/box.rb +233 -165
  47. data/lib/prawn/text/formatted/fragment.rb +27 -27
  48. data/lib/prawn/text/formatted/line_wrap.rb +137 -97
  49. data/lib/prawn/text/formatted/parser.rb +149 -127
  50. data/lib/prawn/text/formatted/wrap.rb +57 -37
  51. data/lib/prawn/text/formatted.rb +6 -4
  52. data/lib/prawn/text.rb +105 -73
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +11 -21
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +42 -68
  58. data/{data/images/fractal.jpg → manual/absolute_position.pdf} +0 -0
  59. data/manual/basic_concepts/adding_pages.rb +9 -10
  60. data/manual/basic_concepts/basic_concepts.rb +33 -24
  61. data/manual/basic_concepts/creation.rb +10 -11
  62. data/manual/basic_concepts/cursor.rb +9 -10
  63. data/manual/basic_concepts/measurement.rb +10 -11
  64. data/manual/basic_concepts/origin.rb +8 -9
  65. data/manual/basic_concepts/other_cursor_helpers.rb +17 -18
  66. data/manual/basic_concepts/view.rb +48 -0
  67. data/manual/bounding_box/bounding_box.rb +31 -29
  68. data/manual/bounding_box/bounds.rb +17 -18
  69. data/manual/bounding_box/canvas.rb +8 -9
  70. data/manual/bounding_box/creation.rb +8 -9
  71. data/manual/bounding_box/indentation.rb +22 -23
  72. data/manual/bounding_box/nesting.rb +32 -25
  73. data/manual/bounding_box/russian_boxes.rb +19 -19
  74. data/manual/bounding_box/stretchy.rb +18 -20
  75. data/manual/contents.rb +35 -0
  76. data/manual/cover.rb +43 -0
  77. data/manual/document_and_page_options/background.rb +16 -14
  78. data/manual/document_and_page_options/document_and_page_options.rb +26 -23
  79. data/manual/document_and_page_options/metadata.rb +21 -19
  80. data/manual/document_and_page_options/page_margins.rb +20 -22
  81. data/manual/document_and_page_options/page_size.rb +15 -15
  82. data/manual/document_and_page_options/print_scaling.rb +23 -0
  83. data/manual/example_helper.rb +5 -408
  84. data/manual/graphics/blend_mode.rb +52 -0
  85. data/manual/graphics/circle_and_ellipse.rb +8 -9
  86. data/manual/graphics/color.rb +11 -13
  87. data/manual/graphics/common_lines.rb +13 -12
  88. data/manual/graphics/fill_and_stroke.rb +10 -11
  89. data/manual/graphics/fill_rules.rb +13 -12
  90. data/manual/graphics/gradients.rb +28 -22
  91. data/manual/graphics/graphics.rb +52 -46
  92. data/manual/graphics/helper.rb +20 -10
  93. data/manual/graphics/line_width.rb +13 -12
  94. data/manual/graphics/lines_and_curves.rb +13 -14
  95. data/manual/graphics/polygon.rb +10 -12
  96. data/manual/graphics/rectangle.rb +7 -8
  97. data/manual/graphics/rotate.rb +9 -12
  98. data/manual/graphics/scale.rb +19 -18
  99. data/manual/graphics/soft_masks.rb +5 -7
  100. data/manual/graphics/stroke_cap.rb +10 -11
  101. data/manual/graphics/stroke_dash.rb +16 -17
  102. data/manual/graphics/stroke_join.rb +10 -11
  103. data/manual/graphics/translate.rb +13 -13
  104. data/manual/graphics/transparency.rb +11 -13
  105. data/manual/{manual/how_to_read_this_manual.rb → how_to_read_this_manual.rb} +23 -25
  106. data/manual/images/absolute_position.rb +9 -10
  107. data/manual/images/fit.rb +9 -10
  108. data/manual/images/horizontal.rb +13 -14
  109. data/manual/images/images.rb +31 -30
  110. data/manual/images/plain_image.rb +6 -7
  111. data/manual/images/scale.rb +12 -13
  112. data/manual/images/vertical.rb +19 -17
  113. data/manual/images/width_and_height.rb +13 -14
  114. data/manual/layout/boxes.rb +14 -15
  115. data/manual/layout/content.rb +12 -13
  116. data/manual/layout/layout.rb +19 -20
  117. data/manual/layout/simple_grid.rb +8 -9
  118. data/manual/outline/add_subsection_to.rb +26 -27
  119. data/manual/outline/insert_section_after.rb +19 -20
  120. data/manual/outline/outline.rb +23 -22
  121. data/manual/outline/sections_and_pages.rb +24 -25
  122. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  123. data/manual/repeatable_content/page_numbering.rb +20 -19
  124. data/manual/repeatable_content/repeatable_content.rb +26 -22
  125. data/manual/repeatable_content/repeater.rb +18 -19
  126. data/manual/repeatable_content/stamp.rb +18 -19
  127. data/manual/security/encryption.rb +8 -11
  128. data/manual/security/permissions.rb +20 -15
  129. data/manual/security/security.rb +20 -20
  130. data/manual/table.rb +16 -0
  131. data/manual/text/alignment.rb +17 -18
  132. data/manual/text/color.rb +13 -13
  133. data/manual/text/column_box.rb +10 -12
  134. data/manual/text/fallback_fonts.rb +29 -25
  135. data/manual/text/font.rb +17 -18
  136. data/manual/text/font_size.rb +21 -22
  137. data/manual/text/font_style.rb +12 -10
  138. data/manual/text/formatted_callbacks.rb +36 -26
  139. data/manual/text/formatted_text.rb +41 -34
  140. data/manual/text/free_flowing_text.rb +28 -29
  141. data/manual/text/inline.rb +23 -26
  142. data/manual/text/kerning_and_character_spacing.rb +20 -21
  143. data/manual/text/leading.rb +10 -11
  144. data/manual/text/line_wrapping.rb +40 -21
  145. data/manual/text/paragraph_indentation.rb +17 -12
  146. data/manual/text/positioned_text.rb +19 -20
  147. data/manual/text/registering_families.rb +33 -30
  148. data/manual/text/rendering_and_color.rb +11 -12
  149. data/manual/text/right_to_left_text.rb +31 -20
  150. data/manual/text/rotation.rb +36 -27
  151. data/manual/text/single_usage.rb +13 -14
  152. data/manual/text/text.rb +62 -62
  153. data/manual/text/text_box_excess.rb +22 -19
  154. data/manual/text/text_box_extensions.rb +21 -18
  155. data/manual/text/text_box_overflow.rb +28 -21
  156. data/manual/text/utf8.rb +16 -17
  157. data/manual/text/win_ansi_charset.rb +29 -26
  158. data/prawn.gemspec +45 -43
  159. data/spec/extensions/encoding_helpers.rb +4 -3
  160. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  161. data/spec/prawn/document/column_box_spec.rb +75 -0
  162. data/spec/prawn/document/security_spec.rb +176 -0
  163. data/spec/prawn/document_annotations_spec.rb +76 -0
  164. data/spec/prawn/document_destinations_spec.rb +15 -0
  165. data/spec/prawn/document_grid_spec.rb +99 -0
  166. data/spec/prawn/document_reference_spec.rb +27 -0
  167. data/spec/prawn/document_span_spec.rb +44 -0
  168. data/spec/prawn/document_spec.rb +805 -0
  169. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  170. data/spec/prawn/font_spec.rb +544 -0
  171. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  172. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  173. data/spec/prawn/graphics_spec.rb +872 -0
  174. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  175. data/spec/prawn/image_handler_spec.rb +53 -0
  176. data/spec/prawn/images/jpg_spec.rb +20 -0
  177. data/spec/prawn/images/png_spec.rb +283 -0
  178. data/spec/prawn/images_spec.rb +229 -0
  179. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  180. data/spec/prawn/outline_spec.rb +512 -0
  181. data/spec/prawn/repeater_spec.rb +166 -0
  182. data/spec/prawn/soft_mask_spec.rb +74 -0
  183. data/spec/prawn/stamp_spec.rb +173 -0
  184. data/spec/prawn/text/box_spec.rb +1110 -0
  185. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  186. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  187. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  188. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  189. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  190. data/spec/prawn/text_draw_text_spec.rb +150 -0
  191. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  192. data/spec/prawn/text_spacing_spec.rb +95 -0
  193. data/spec/prawn/text_spec.rb +603 -0
  194. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  195. data/spec/prawn/transformation_stack_spec.rb +66 -0
  196. data/spec/prawn/view_spec.rb +63 -0
  197. data/spec/prawn_manual_spec.rb +35 -0
  198. data/spec/spec_helper.rb +22 -21
  199. data.tar.gz.sig +0 -0
  200. metadata +168 -307
  201. metadata.gz.sig +0 -0
  202. data/README.md +0 -109
  203. data/data/encodings/win_ansi.txt +0 -29
  204. data/data/images/16bit.alpha +0 -0
  205. data/data/images/16bit.dat +0 -0
  206. data/data/images/16bit.png +0 -0
  207. data/data/images/arrow.png +0 -0
  208. data/data/images/arrow2.png +0 -0
  209. data/data/images/barcode_issue.png +0 -0
  210. data/data/images/dice.alpha +0 -0
  211. data/data/images/dice.dat +0 -0
  212. data/data/images/dice.png +0 -0
  213. data/data/images/dice_interlaced.png +0 -0
  214. data/data/images/indexed_color.dat +0 -0
  215. data/data/images/indexed_color.png +0 -0
  216. data/data/images/letterhead.jpg +0 -0
  217. data/data/images/page_white_text.alpha +0 -0
  218. data/data/images/page_white_text.dat +0 -0
  219. data/data/images/page_white_text.png +0 -0
  220. data/data/images/pigs.jpg +0 -0
  221. data/data/images/prawn.png +0 -0
  222. data/data/images/ruport.png +0 -0
  223. data/data/images/ruport_data.dat +0 -0
  224. data/data/images/ruport_transparent.png +0 -0
  225. data/data/images/ruport_type0.png +0 -0
  226. data/data/images/stef.jpg +0 -0
  227. data/data/images/tru256.bmp +0 -0
  228. data/data/images/web-links.dat +0 -1
  229. data/data/images/web-links.png +0 -0
  230. data/data/pdfs/complex_template.pdf +0 -0
  231. data/data/pdfs/contains_ttf_font.pdf +0 -0
  232. data/data/pdfs/encrypted.pdf +0 -0
  233. data/data/pdfs/form.pdf +1 -819
  234. data/data/pdfs/hexagon.pdf +0 -61
  235. data/data/pdfs/indirect_reference.pdf +0 -86
  236. data/data/pdfs/multipage_template.pdf +0 -127
  237. data/data/pdfs/nested_pages.pdf +0 -118
  238. data/data/pdfs/page_without_mediabox.pdf +0 -193
  239. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  240. data/data/pdfs/two_hexagons.pdf +0 -90
  241. data/data/pdfs/version_1_6.pdf +0 -61
  242. data/data/shift_jis_text.txt +0 -1
  243. data/lib/pdf/core/annotations.rb +0 -60
  244. data/lib/pdf/core/byte_string.rb +0 -9
  245. data/lib/pdf/core/destinations.rb +0 -90
  246. data/lib/pdf/core/document_state.rb +0 -78
  247. data/lib/pdf/core/filter_list.rb +0 -51
  248. data/lib/pdf/core/filters.rb +0 -36
  249. data/lib/pdf/core/graphics_state.rb +0 -68
  250. data/lib/pdf/core/literal_string.rb +0 -16
  251. data/lib/pdf/core/name_tree.rb +0 -177
  252. data/lib/pdf/core/object_store.rb +0 -320
  253. data/lib/pdf/core/outline.rb +0 -315
  254. data/lib/pdf/core/page.rb +0 -212
  255. data/lib/pdf/core/page_geometry.rb +0 -126
  256. data/lib/pdf/core/pdf_object.rb +0 -124
  257. data/lib/pdf/core/reference.rb +0 -103
  258. data/lib/pdf/core/stream.rb +0 -98
  259. data/lib/pdf/core/text.rb +0 -275
  260. data/lib/pdf/core.rb +0 -35
  261. data/lib/prawn/compatibility.rb +0 -91
  262. data/lib/prawn/document/graphics_state.rb +0 -73
  263. data/lib/prawn/document/snapshot.rb +0 -89
  264. data/lib/prawn/font/afm.rb +0 -203
  265. data/lib/prawn/layout.rb +0 -20
  266. data/lib/prawn/table/cell/image.rb +0 -70
  267. data/lib/prawn/table/cell/in_table.rb +0 -27
  268. data/lib/prawn/table/cell/span_dummy.rb +0 -92
  269. data/lib/prawn/table/cell/subtable.rb +0 -65
  270. data/lib/prawn/table/cell/text.rb +0 -153
  271. data/lib/prawn/table/cell.rb +0 -770
  272. data/lib/prawn/table/cells.rb +0 -295
  273. data/lib/prawn/table.rb +0 -643
  274. data/manual/example_file.rb +0 -116
  275. data/manual/example_package.rb +0 -53
  276. data/manual/example_section.rb +0 -46
  277. data/manual/manual/cover.rb +0 -35
  278. data/manual/manual/foreword.rb +0 -85
  279. data/manual/manual/manual.rb +0 -35
  280. data/manual/syntax_highlight.rb +0 -52
  281. data/manual/table/basic_block.rb +0 -53
  282. data/manual/table/before_rendering_page.rb +0 -26
  283. data/manual/table/cell_border_lines.rb +0 -24
  284. data/manual/table/cell_borders_and_bg.rb +0 -31
  285. data/manual/table/cell_dimensions.rb +0 -30
  286. data/manual/table/cell_text.rb +0 -38
  287. data/manual/table/column_widths.rb +0 -30
  288. data/manual/table/content_and_subtables.rb +0 -39
  289. data/manual/table/creation.rb +0 -27
  290. data/manual/table/filtering.rb +0 -36
  291. data/manual/table/flow_and_header.rb +0 -17
  292. data/manual/table/image_cells.rb +0 -33
  293. data/manual/table/position.rb +0 -29
  294. data/manual/table/row_colors.rb +0 -20
  295. data/manual/table/span.rb +0 -30
  296. data/manual/table/style.rb +0 -22
  297. data/manual/table/table.rb +0 -52
  298. data/manual/table/width.rb +0 -27
  299. data/manual/templates/full_template.rb +0 -25
  300. data/manual/templates/page_template.rb +0 -48
  301. data/manual/templates/templates.rb +0 -27
  302. data/manual/text/group.rb +0 -29
  303. data/spec/acceptance/png.rb +0 -23
  304. data/spec/annotations_spec.rb +0 -74
  305. data/spec/bounding_box_spec.rb +0 -493
  306. data/spec/cell_spec.rb +0 -628
  307. data/spec/column_box_spec.rb +0 -33
  308. data/spec/destinations_spec.rb +0 -15
  309. data/spec/document_spec.rb +0 -761
  310. data/spec/extensions/mocha.rb +0 -44
  311. data/spec/filters_spec.rb +0 -34
  312. data/spec/font_metric_cache_spec.rb +0 -52
  313. data/spec/font_spec.rb +0 -464
  314. data/spec/formatted_text_arranger_spec.rb +0 -421
  315. data/spec/formatted_text_box_spec.rb +0 -650
  316. data/spec/formatted_text_fragment_spec.rb +0 -298
  317. data/spec/graphics_spec.rb +0 -651
  318. data/spec/grid_spec.rb +0 -85
  319. data/spec/image_handler_spec.rb +0 -42
  320. data/spec/images_spec.rb +0 -157
  321. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  322. data/spec/jpg_spec.rb +0 -25
  323. data/spec/line_wrap_spec.rb +0 -333
  324. data/spec/measurement_units_spec.rb +0 -23
  325. data/spec/name_tree_spec.rb +0 -112
  326. data/spec/object_store_spec.rb +0 -170
  327. data/spec/outline_spec.rb +0 -448
  328. data/spec/pdf_object_spec.rb +0 -172
  329. data/spec/png_spec.rb +0 -240
  330. data/spec/reference_spec.rb +0 -82
  331. data/spec/repeater_spec.rb +0 -158
  332. data/spec/security_spec.rb +0 -158
  333. data/spec/snapshot_spec.rb +0 -186
  334. data/spec/soft_mask_spec.rb +0 -117
  335. data/spec/span_spec.rb +0 -44
  336. data/spec/stamp_spec.rb +0 -158
  337. data/spec/stream_spec.rb +0 -58
  338. data/spec/stroke_styles_spec.rb +0 -211
  339. data/spec/table/span_dummy_spec.rb +0 -17
  340. data/spec/table_spec.rb +0 -1355
  341. data/spec/template_spec.rb +0 -351
  342. data/spec/text_at_spec.rb +0 -130
  343. data/spec/text_box_spec.rb +0 -1030
  344. data/spec/text_rendering_mode_spec.rb +0 -45
  345. data/spec/text_spacing_spec.rb +0 -93
  346. data/spec/text_spec.rb +0 -425
  347. data/spec/text_with_inline_formatting_spec.rb +0 -35
  348. data/spec/transparency_spec.rb +0 -89
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # encryption.rb : Implements encrypted PDF and access permissions.
4
4
  #
5
5
  # Copyright August 2008, Brad Ediger. All Rights Reserved.
@@ -7,17 +7,15 @@
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
9
  require 'digest/md5'
10
- require 'rc4'
11
10
 
12
- require_relative '../pdf/core/byte_string'
11
+ require_relative 'security/arcfour'
13
12
 
14
13
  module Prawn
15
14
  class Document
16
-
17
15
  # Implements PDF encryption (password protection and permissions) as
18
16
  # specified in the PDF Reference, version 1.3, section 3.5 "Encryption".
19
17
  module Security
20
- include PDF::Core
18
+ # @group Experimental API
21
19
 
22
20
  # Encrypts the document, to protect confidential data or control
23
21
  # modifications to the document. The encryption algorithm used is
@@ -87,15 +85,15 @@ module Prawn
87
85
  # not a limitation of Prawn, but is rather a built-in limitation of the
88
86
  # PDF format.
89
87
  #
90
- def encrypt_document(options={})
91
- Prawn.verify_options [:user_password, :owner_password, :permissions],
88
+ def encrypt_document(options = {})
89
+ Prawn.verify_options %i[user_password owner_password permissions],
92
90
  options
93
- @user_password = options.delete(:user_password) || ""
91
+ @user_password = options.delete(:user_password) || ''
94
92
 
95
93
  @owner_password = options.delete(:owner_password) || @user_password
96
94
  if @owner_password == :random
97
95
  # Generate a completely ridiculous password
98
- @owner_password = (1..32).map{ rand(256) }.pack("c*")
96
+ @owner_password = (1..32).map { rand(256) }.pack('c*')
99
97
  end
100
98
 
101
99
  self.permissions = options.delete(:permissions) || {}
@@ -111,45 +109,54 @@ module Prawn
111
109
  # See Algorithm 3.1.
112
110
  def self.encrypt_string(str, key, id, gen)
113
111
  # Convert ID and Gen number into little-endian truncated byte strings
114
- id = [id].pack('V')[0,3]
115
- gen = [gen].pack('V')[0,2]
112
+ id = [id].pack('V')[0, 3]
113
+ gen = [gen].pack('V')[0, 2]
116
114
  extended_key = "#{key}#{id}#{gen}"
117
115
 
118
116
  # Compute the RC4 key from the extended key and perform the encryption
119
117
  rc4_key = Digest::MD5.digest(extended_key)[0, 10]
120
- RC4.new(rc4_key).encrypt(str)
118
+ Arcfour.new(rc4_key).encrypt(str)
121
119
  end
122
120
 
123
121
  private
124
122
 
125
123
  # Provides the values for the trailer encryption dictionary.
126
124
  def encryption_dictionary
127
- { :Filter => :Standard, # default PDF security handler
128
- :V => 1, # "Algorithm 3.1", PDF reference 1.3
129
- :R => 2, # Revision 2 of the algorithm
130
- :O => ByteString.new(owner_password_hash),
131
- :U => ByteString.new(user_password_hash),
132
- :P => permissions_value }
125
+ {
126
+ Filter: :Standard, # default PDF security handler
127
+ V: 1, # "Algorithm 3.1", PDF reference 1.3
128
+ R: 2, # Revision 2 of the algorithm
129
+ O: PDF::Core::ByteString.new(owner_password_hash),
130
+ U: PDF::Core::ByteString.new(user_password_hash),
131
+ P: permissions_value
132
+ }
133
133
  end
134
134
 
135
135
  # Flags in the permissions word, numbered as LSB = 1
136
- PermissionsBits = { :print_document => 3,
137
- :modify_contents => 4,
138
- :copy_contents => 5,
139
- :modify_annotations => 6 }
140
-
141
- FullPermissions = 0b1111_1111_1111_1111_1111_1111_1111_1111
142
-
143
- def permissions=(perms={})
144
- @permissions ||= FullPermissions
136
+ PERMISSIONS_BITS = {
137
+ print_document: 3,
138
+ modify_contents: 4,
139
+ copy_contents: 5,
140
+ modify_annotations: 6
141
+ }.freeze
142
+ private_constant :PERMISSIONS_BITS
143
+
144
+ FULL_PERMISSIONS = 0b1111_1111_1111_1111_1111_1111_1111_1111
145
+ private_constant :FULL_PERMISSIONS
146
+
147
+ def permissions=(perms = {})
148
+ @permissions ||= FULL_PERMISSIONS
145
149
  perms.each do |key, value|
146
- unless PermissionsBits[key]
147
- raise ArgumentError, "Unknown permission :#{key}. Valid options: " +
148
- PermissionsBits.keys.map { |k| k.inspect }.join(", ")
150
+ unless PERMISSIONS_BITS[key]
151
+ raise(
152
+ ArgumentError,
153
+ "Unknown permission :#{key}. Valid options: " +
154
+ PERMISSIONS_BITS.keys.map(&:inspect).join(', ')
155
+ )
149
156
  end
150
157
 
151
158
  # 0-based bit number, from LSB
152
- bit_position = PermissionsBits[key] - 1
159
+ bit_position = PERMISSIONS_BITS[key] - 1
153
160
 
154
161
  if value # set bit
155
162
  @permissions |= (1 << bit_position)
@@ -160,122 +167,137 @@ module Prawn
160
167
  end
161
168
 
162
169
  def permissions_value
163
- @permissions || FullPermissions
170
+ @permissions || FULL_PERMISSIONS
164
171
  end
165
172
 
166
- PasswordPadding =
167
- "28BF4E5E4E758A4164004E56FFFA01082E2E00B6D0683E802F0CA9FE6453697A".
168
- scan(/../).map{|x| x.to_i(16)}.pack("c*")
173
+ PASSWORD_PADDING =
174
+ '28BF4E5E4E758A4164004E56FFFA01082E2E00B6D0683E802F0CA9FE6453697A'
175
+ .scan(/../).map { |x| x.to_i(16) }.pack('c*')
169
176
 
170
177
  # Pads or truncates a password to 32 bytes as per Alg 3.2.
171
178
  def pad_password(password)
172
179
  password = password[0, 32]
173
- password + PasswordPadding[0, 32 - password.length]
180
+ password + PASSWORD_PADDING[0, 32 - password.length]
174
181
  end
175
182
 
176
183
  def user_encryption_key
177
- @user_encryption_key ||= begin
178
- md5 = Digest::MD5.new
179
- md5 << pad_password(@user_password)
180
- md5 << owner_password_hash
181
- md5 << [permissions_value].pack("V")
182
- md5.digest[0, 5]
183
- end
184
+ @user_encryption_key ||=
185
+ begin
186
+ md5 = Digest::MD5.new
187
+ md5 << pad_password(@user_password)
188
+ md5 << owner_password_hash
189
+ md5 << [permissions_value].pack('V')
190
+ md5.digest[0, 5]
191
+ end
184
192
  end
185
193
 
186
194
  # The O (owner) value in the encryption dictionary. Algorithm 3.3.
187
195
  def owner_password_hash
188
- @owner_password_hash ||= begin
189
- key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
190
- RC4.new(key).encrypt(pad_password(@user_password))
191
- end
196
+ @owner_password_hash ||=
197
+ begin
198
+ key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
199
+ Arcfour.new(key).encrypt(pad_password(@user_password))
200
+ end
192
201
  end
193
202
 
194
203
  # The U (user) value in the encryption dictionary. Algorithm 3.4.
195
204
  def user_password_hash
196
- RC4.new(user_encryption_key).encrypt(PasswordPadding)
205
+ Arcfour.new(user_encryption_key).encrypt(PASSWORD_PADDING)
197
206
  end
198
-
199
207
  end
200
-
201
208
  end
202
209
  end
203
210
 
204
- module PDF #:nodoc:
211
+ # @private
212
+ module PDF
205
213
  module Core
206
214
  module_function
207
215
 
208
- # Like PdfObject, but returns an encrypted result if required.
216
+ # Like pdf_object, but returns an encrypted result if required.
209
217
  # For direct objects, requires the object identifier and generation number
210
218
  # from the indirect object referencing obj.
211
- def EncryptedPdfObject(obj, key, id, gen, in_content_stream=false)
219
+ #
220
+ # @private
221
+ def encrypted_pdf_object(obj, key, id, gen, in_content_stream = false)
212
222
  case obj
213
223
  when Array
214
- "[" << obj.map { |e|
215
- EncryptedPdfObject(e, key, id, gen, in_content_stream)
216
- }.join(' ') << "]"
224
+ array_content = obj.map do |e|
225
+ encrypted_pdf_object(e, key, id, gen, in_content_stream)
226
+ end.join(' ')
227
+ "[#{array_content}]"
217
228
  when LiteralString
218
- obj = ByteString.new(Prawn::Document::Security.encrypt_string(obj, key, id, gen)).gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
229
+ obj =
230
+ ByteString.new(
231
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen)
232
+ ).gsub(/[\\\n()]/) { |m| "\\#{m}" }
219
233
  "(#{obj})"
220
234
  when Time
221
- obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
222
- obj = ByteString.new(Prawn::Document::Security.encrypt_string(obj, key, id, gen)).gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
235
+ obj = "#{obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop}'00'"
236
+ obj =
237
+ ByteString.new(
238
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen)
239
+ ).gsub(/[\\\n()]/) { |m| "\\#{m}" }
223
240
  "(#{obj})"
224
241
  when String
225
- PdfObject(
242
+ pdf_object(
226
243
  ByteString.new(
227
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)),
228
- in_content_stream)
244
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen)
245
+ ),
246
+ in_content_stream
247
+ )
229
248
  when ::Hash
230
- output = "<< "
231
- obj.each do |k,v|
232
- unless String === k || Symbol === k
249
+ hash_content = obj.map do |k, v|
250
+ unless k.is_a?(String) || k.is_a?(Symbol)
233
251
  raise PDF::Core::Errors::FailedObjectConversion,
234
- "A PDF Dictionary must be keyed by names"
252
+ 'A PDF Dictionary must be keyed by names'
235
253
  end
236
- output << PdfObject(k.to_sym, in_content_stream) << " " <<
237
- EncryptedPdfObject(v, key, id, gen, in_content_stream) << "\n"
238
- end
239
- output << ">>"
254
+ "#{pdf_object(k.to_sym, in_content_stream)} #{encrypted_pdf_object(v, key, id, gen, in_content_stream)}\n"
255
+ end.join('')
256
+ "<< #{hash_content}>>"
240
257
  when NameTree::Value
241
- PdfObject(obj.name) + " " +
242
- EncryptedPdfObject(obj.value, key, id, gen, in_content_stream)
258
+ "#{pdf_object(obj.name)} #{encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)}"
243
259
  when PDF::Core::OutlineRoot, PDF::Core::OutlineItem
244
- EncryptedPdfObject(obj.to_hash, key, id, gen, in_content_stream)
245
- else # delegate back to PdfObject
246
- PdfObject(obj, in_content_stream)
260
+ encrypted_pdf_object(obj.to_hash, key, id, gen, in_content_stream)
261
+ else # delegate back to pdf_object
262
+ pdf_object(obj, in_content_stream)
247
263
  end
248
264
  end
249
265
 
250
-
266
+ # @private
251
267
  class Stream
252
268
  def encrypted_object(key, id, gen)
253
269
  if filtered_stream
254
- "stream\n#{Prawn::Document::Security.encrypt_string filtered_stream, key, id, gen}\nendstream\n"
270
+ "stream\n#{
271
+ Prawn::Document::Security.encrypt_string(
272
+ filtered_stream, key, id, gen
273
+ )
274
+ }\nendstream\n"
255
275
  else
256
276
  ''
257
277
  end
258
278
  end
259
279
  end
260
280
 
281
+ # @private
261
282
  class Reference
262
-
263
283
  # Returns the object definition for the object this references, keyed from
264
284
  # +key+.
265
285
  def encrypted_object(key)
266
- @on_encode.call(self) if @on_encode
286
+ @on_encode&.call(self)
267
287
 
268
- output = "#{@identifier} #{gen} obj\n"
269
- unless @stream.empty?
270
- output << PDF::Core::EncryptedPdfObject(data.merge(@stream.data), key, @identifier, gen) << "\n" <<
271
- @stream.encrypted_object(key, @identifier, gen)
288
+ output = +"#{@identifier} #{gen} obj\n"
289
+ if @stream.empty?
290
+ output <<
291
+ PDF::Core.encrypted_pdf_object(data, key, @identifier, gen) << "\n"
272
292
  else
273
- output << PDF::Core::EncryptedPdfObject(data, key, @identifier, gen) << "\n"
293
+ output << PDF::Core.encrypted_pdf_object(
294
+ data.merge(@stream.data), key, @identifier, gen
295
+ ) << "\n" <<
296
+ @stream.encrypted_object(key, @identifier, gen)
274
297
  end
275
298
 
276
299
  output << "endobj\n"
277
300
  end
278
-
279
301
  end
280
302
  end
281
303
  end
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # soft_mask.rb : Implements soft-masking
4
4
  #
5
5
  # Copyright September 2012, Alexander Mankuta. All Rights Reserved.
@@ -8,9 +8,8 @@
8
8
  #
9
9
 
10
10
  module Prawn
11
-
12
11
  # The Prawn::SoftMask module is used to create arbitrary transparency in
13
- # document. Using a soft mask allows creaing more visually rich documents.
12
+ # document. Using a soft mask allows creating more visually rich documents.
14
13
  #
15
14
  # You must group soft mask and graphics it's applied to under
16
15
  # save_graphics_state because soft mask is a part of graphic state in PDF.
@@ -26,62 +25,62 @@ module Prawn
26
25
  # end
27
26
  #
28
27
  module SoftMask
28
+ # @group Stable API
29
+
29
30
  def soft_mask(&block)
30
- min_version(1.4)
31
+ renderer.min_version(1.4)
31
32
 
32
- group_attrs = ref!({
33
- :Type => :Group,
34
- :S => :Transparency,
35
- :CS => :DeviceRGB,
36
- :I => false,
37
- :K => false
38
- })
33
+ group_attrs = ref!(
34
+ Type: :Group,
35
+ S: :Transparency,
36
+ CS: :DeviceRGB,
37
+ I: false,
38
+ K: false
39
+ )
39
40
 
40
- group = ref!({
41
- :Type => :XObject,
42
- :Subtype => :Form,
43
- :BBox => state.page.dimensions,
44
- :Group => group_attrs,
45
- })
41
+ group = ref!(
42
+ Type: :XObject,
43
+ Subtype: :Form,
44
+ BBox: state.page.dimensions,
45
+ Group: group_attrs
46
+ )
46
47
 
47
48
  state.page.stamp_stream(group, &block)
48
49
 
49
- mask = ref!({
50
- :Type => :Mask,
51
- :S => :Luminosity,
52
- :G => group
53
- })
50
+ mask = ref!(
51
+ Type: :Mask,
52
+ S: :Luminosity,
53
+ G: group
54
+ )
54
55
 
55
- g_state = ref!({
56
- :Type => :ExtGState,
57
- :SMask => mask,
56
+ g_state = ref!(
57
+ Type: :ExtGState,
58
+ SMask: mask,
58
59
 
59
- :AIS => false,
60
- :BM => :Normal,
61
- :OP => false,
62
- :op => false,
63
- :OPM => 1,
64
- :SA => true,
65
- })
60
+ AIS: false,
61
+ BM: :Normal,
62
+ OP: false,
63
+ op: false,
64
+ OPM: 1,
65
+ SA: true
66
+ )
66
67
 
67
68
  registry_key = {
68
- :bbox => state.page.dimensions,
69
- :mask => [group.stream.filters.normalized, group.stream.filtered_stream],
70
- :page => state.page_count,
69
+ bbox: state.page.dimensions,
70
+ mask: [group.stream.filters.normalized, group.stream.filtered_stream],
71
+ page: state.page_count
71
72
  }.hash
72
73
 
73
74
  if soft_mask_registry[registry_key]
74
- [g_state, mask, group, group_attrs].each { |ref| ref.live = false }
75
-
76
- add_content "/#{soft_mask_registry[registry_key]} gs"
75
+ renderer.add_content "/#{soft_mask_registry[registry_key]} gs"
77
76
  else
78
77
  masks = page.resources[:ExtGState] ||= {}
79
- id = masks.empty? ? 'GS1' : masks.keys.sort.last.succ
78
+ id = masks.empty? ? 'GS1' : masks.keys.max.succ
80
79
  masks[id] = g_state
81
80
 
82
81
  soft_mask_registry[registry_key] = id
83
82
 
84
- add_content "/#{id} gs"
83
+ renderer.add_content "/#{id} gs"
85
84
  end
86
85
  end
87
86
 
data/lib/prawn/stamp.rb CHANGED
@@ -1,14 +1,12 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # stamp.rb : Implements a repeatable stamp
4
4
  #
5
5
  # Copyright October 2009, Daniel Nelson. All Rights Reserved.
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
  #
9
-
10
9
  module Prawn
11
-
12
10
  # The Prawn::Stamp module is used to create content that will be
13
11
  # included multiple times in a document. Using a stamp has three
14
12
  # advantages over creating content anew each time it is placed on
@@ -27,6 +25,7 @@ module Prawn
27
25
  # pdf.stamp("my_stamp")
28
26
  #
29
27
  module Stamp
28
+ # @group Stable API
30
29
 
31
30
  # Renders the stamp named <tt>name</tt> to the page
32
31
  # raises <tt>Prawn::Errors::InvalidName</tt> if name.empty?
@@ -42,7 +41,8 @@ module Prawn
42
41
  #
43
42
  def stamp(name)
44
43
  dictionary_name, dictionary = stamp_dictionary(name)
45
- add_content "/#{dictionary_name} Do"
44
+ renderer.add_content "/#{dictionary_name} Do"
45
+ update_annotation_references dictionary.data[:Annots]
46
46
  state.page.xobjects.merge!(dictionary_name => dictionary)
47
47
  end
48
48
 
@@ -107,21 +107,39 @@ module Prawn
107
107
  def create_stamp_dictionary(name)
108
108
  raise Prawn::Errors::InvalidName if name.empty?
109
109
  raise Prawn::Errors::NameTaken unless stamp_dictionary_registry[name].nil?
110
+
110
111
  # BBox origin is the lower left margin of the page, so we need
111
112
  # it to be the full dimension of the page, or else things that
112
113
  # should appear near the top or right margin are invisible
113
- dictionary = ref!(:Type => :XObject,
114
- :Subtype => :Form,
115
- :BBox => [0, 0,
116
- state.page.dimensions[2], state.page.dimensions[3]])
114
+ dictionary = ref!(
115
+ Type: :XObject,
116
+ Subtype: :Form,
117
+ BBox: [
118
+ 0, 0,
119
+ state.page.dimensions[2], state.page.dimensions[3]
120
+ ]
121
+ )
117
122
 
118
123
  dictionary_name = "Stamp#{next_stamp_dictionary_id}"
119
124
 
120
- stamp_dictionary_registry[name] = { :stamp_dictionary_name => dictionary_name,
121
- :stamp_dictionary => dictionary }
125
+ stamp_dictionary_registry[name] = {
126
+ stamp_dictionary_name: dictionary_name,
127
+ stamp_dictionary: dictionary
128
+ }
122
129
  dictionary
123
130
  end
124
131
 
132
+ # Referencing annotations from a stamp XObject doesn't result
133
+ # in a working link. Instead, the references must be appended
134
+ # to the /Annot dictionary of the object that contains the
135
+ # call to the stamp object.
136
+ def update_annotation_references(annots)
137
+ if annots&.any?
138
+ state.page.dictionary.data[:Annots] ||= []
139
+ state.page.dictionary.data[:Annots] |= annots
140
+ end
141
+ end
142
+
125
143
  def freeze_stamp_graphics
126
144
  update_colors
127
145
  write_line_width
@@ -129,6 +147,5 @@ module Prawn
129
147
  write_stroke_join_style
130
148
  write_stroke_dash
131
149
  end
132
-
133
150
  end
134
151
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # text/rectangle.rb : Implements text boxes
4
4
  #
@@ -7,10 +7,11 @@
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
  #
9
9
 
10
- require_relative "formatted/box"
10
+ require_relative 'formatted/box'
11
11
 
12
12
  module Prawn
13
13
  module Text
14
+ # @group Stable API
14
15
 
15
16
  # Draws the requested text into a box. When the text overflows
16
17
  # the rectangle, you shrink to fit, or truncate the text. Text
@@ -39,6 +40,8 @@ module Prawn
39
40
  # <tt>:character_spacing</tt>:: <tt>number</tt>. The amount of space to add
40
41
  # to or remove from the default character
41
42
  # spacing. [0]
43
+ # <tt>:disable_wrap_by_char</tt>:: <tt>boolean</tt> Whether
44
+ # or not to prevent mid-word breaks when text does not fit in box. [false]
42
45
  # <tt>:mode</tt>:: <tt>symbol</tt>. The text rendering mode. See
43
46
  # documentation for Prawn::Document#text_rendering_mode
44
47
  # for a list of valid options. [:fill]
@@ -49,7 +52,8 @@ module Prawn
49
52
  # <tt>[x, y]</tt>. The upper left corner of the box
50
53
  # [@document.bounds.left, @document.bounds.top]
51
54
  # <tt>:width</tt>::
52
- # <tt>number</tt>. The width of the box [@document.bounds.right - @at[0]]
55
+ # <tt>number</tt>. The width of the box
56
+ # [@document.bounds.right - @at[0]]
53
57
  # <tt>:height</tt>::
54
58
  # <tt>number</tt>. The height of the box [default_height()]
55
59
  # <tt>:direction</tt>::
@@ -57,7 +61,7 @@ module Prawn
57
61
  # or right-to-left) [value of document.text_direction]
58
62
  # <tt>:fallback_fonts</tt>::
59
63
  # An array of font names. Each name must be the name of an AFM font or
60
- # the name that was used to register a family of TTF fonts (see
64
+ # the name that was used to register a family of external fonts (see
61
65
  # Prawn::Document#font_families). If present, then each glyph will be
62
66
  # rendered using the first font that includes the glyph, starting with
63
67
  # the current font and then moving through :fallback_fonts from
@@ -69,7 +73,6 @@ module Prawn
69
73
  # <tt>:valign</tt>::
70
74
  # <tt>:top</tt>, <tt>:center</tt>, or <tt>:bottom</tt>. Vertical
71
75
  # alignment within the bounding box [:top]
72
- #
73
76
  # <tt>:rotate</tt>::
74
77
  # <tt>number</tt>. The angle to rotate the text
75
78
  # <tt>:rotate_around</tt>::
@@ -80,9 +83,8 @@ module Prawn
80
83
  # <tt>number</tt>. Additional space between lines [value of
81
84
  # document.default_leading]
82
85
  # <tt>:single_line</tt>::
83
- # <tt>boolean</tt>. If true, then only the first line will be drawn [false]
84
- # <tt>:skip_encoding</tt>::
85
- # <tt>boolean</tt> [false]
86
+ # <tt>boolean</tt>. If true, then only the first line will be drawn
87
+ # [false]
86
88
  # <tt>:overflow</tt>::
87
89
  # <tt>:truncate</tt>, <tt>:shrink_to_fit</tt>, or <tt>:expand</tt>
88
90
  # This controls the behavior when the amount of text
@@ -96,31 +98,30 @@ module Prawn
96
98
  #
97
99
  # Returns any text that did not print under the current settings.
98
100
  #
99
- # NOTE: if an AFM font is used, then the returned text is encoded in
100
- # WinAnsi. Subsequent calls to text_box that pass this returned text back
101
- # into text box must include a :skip_encoding => true option. This is
102
- # unnecessary when using TTF fonts because those operate on UTF-8 encoding.
103
- #
104
101
  # == Exceptions
105
102
  #
106
- # Raises <tt>Prawn::Errrors::CannotFit</tt> if not wide enough to print
103
+ # Raises <tt>Prawn::Errors::CannotFit</tt> if not wide enough to print
107
104
  # any text
108
105
  #
109
- def text_box(string, options={})
106
+ def text_box(string, options = {})
110
107
  options = options.dup
111
108
  options[:document] = self
112
109
 
113
- box = if p = options.delete(:inline_format)
114
- p = [] unless p.is_a?(Array)
115
- array = self.text_formatter.format(string, *p)
116
- Text::Formatted::Box.new(array, options)
117
- else
118
- Text::Box.new(string, options)
119
- end
110
+ box =
111
+ if options[:inline_format]
112
+ p = options.delete(:inline_format)
113
+ p = [] unless p.is_a?(Array)
114
+ array = text_formatter.format(string, *p)
115
+ Text::Formatted::Box.new(array, options)
116
+ else
117
+ Text::Box.new(string, options)
118
+ end
120
119
 
121
120
  box.render
122
121
  end
123
122
 
123
+ # @group Experimental API
124
+
124
125
  # Generally, one would use the Prawn::Text#text_box convenience
125
126
  # method. However, using Text::Box.new in conjunction with
126
127
  # #render(:dry_run=> true) enables one to do look-ahead calculations prior
@@ -128,17 +129,14 @@ module Prawn
128
129
  # consumed by the printed text
129
130
  #
130
131
  class Box < Prawn::Text::Formatted::Box
131
-
132
- def initialize(string, options={})
133
- super([{ :text => string }], options)
132
+ def initialize(string, options = {})
133
+ super([{ text: string }], options)
134
134
  end
135
135
 
136
- def render(flags={})
136
+ def render(flags = {})
137
137
  leftover = super(flags)
138
- leftover.collect { |hash| hash[:text] }.join
138
+ leftover.map { |hash| hash[:text] }.join
139
139
  end
140
-
141
140
  end
142
-
143
141
  end
144
142
  end