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,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.
@@ -8,17 +8,13 @@
8
8
 
9
9
  require 'digest/md5'
10
10
 
11
- require 'pdf/core/byte_string'
12
-
13
- require 'prawn/security/arcfour'
11
+ require_relative 'security/arcfour'
14
12
 
15
13
  module Prawn
16
14
  class Document
17
-
18
15
  # Implements PDF encryption (password protection and permissions) as
19
16
  # specified in the PDF Reference, version 1.3, section 3.5 "Encryption".
20
17
  module Security
21
-
22
18
  # @group Experimental API
23
19
 
24
20
  # Encrypts the document, to protect confidential data or control
@@ -89,15 +85,15 @@ module Prawn
89
85
  # not a limitation of Prawn, but is rather a built-in limitation of the
90
86
  # PDF format.
91
87
  #
92
- def encrypt_document(options={})
93
- Prawn.verify_options [:user_password, :owner_password, :permissions],
88
+ def encrypt_document(options = {})
89
+ Prawn.verify_options %i[user_password owner_password permissions],
94
90
  options
95
- @user_password = options.delete(:user_password) || ""
91
+ @user_password = options.delete(:user_password) || ''
96
92
 
97
93
  @owner_password = options.delete(:owner_password) || @user_password
98
94
  if @owner_password == :random
99
95
  # Generate a completely ridiculous password
100
- @owner_password = (1..32).map{ rand(256) }.pack("c*")
96
+ @owner_password = (1..32).map { rand(256) }.pack('c*')
101
97
  end
102
98
 
103
99
  self.permissions = options.delete(:permissions) || {}
@@ -113,8 +109,8 @@ module Prawn
113
109
  # See Algorithm 3.1.
114
110
  def self.encrypt_string(str, key, id, gen)
115
111
  # Convert ID and Gen number into little-endian truncated byte strings
116
- id = [id].pack('V')[0,3]
117
- gen = [gen].pack('V')[0,2]
112
+ id = [id].pack('V')[0, 3]
113
+ gen = [gen].pack('V')[0, 2]
118
114
  extended_key = "#{key}#{id}#{gen}"
119
115
 
120
116
  # Compute the RC4 key from the extended key and perform the encryption
@@ -126,32 +122,41 @@ module Prawn
126
122
 
127
123
  # Provides the values for the trailer encryption dictionary.
128
124
  def encryption_dictionary
129
- { :Filter => :Standard, # default PDF security handler
130
- :V => 1, # "Algorithm 3.1", PDF reference 1.3
131
- :R => 2, # Revision 2 of the algorithm
132
- :O => PDF::Core::ByteString.new(owner_password_hash),
133
- :U => PDF::Core::ByteString.new(user_password_hash),
134
- :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
+ }
135
133
  end
136
134
 
137
135
  # Flags in the permissions word, numbered as LSB = 1
138
- PermissionsBits = { :print_document => 3,
139
- :modify_contents => 4,
140
- :copy_contents => 5,
141
- :modify_annotations => 6 }
142
-
143
- FullPermissions = 0b1111_1111_1111_1111_1111_1111_1111_1111
144
-
145
- def permissions=(perms={})
146
- @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
147
149
  perms.each do |key, value|
148
- unless PermissionsBits[key]
149
- raise ArgumentError, "Unknown permission :#{key}. Valid options: " +
150
- 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
+ )
151
156
  end
152
157
 
153
158
  # 0-based bit number, from LSB
154
- bit_position = PermissionsBits[key] - 1
159
+ bit_position = PERMISSIONS_BITS[key] - 1
155
160
 
156
161
  if value # set bit
157
162
  @permissions |= (1 << bit_position)
@@ -162,44 +167,44 @@ module Prawn
162
167
  end
163
168
 
164
169
  def permissions_value
165
- @permissions || FullPermissions
170
+ @permissions || FULL_PERMISSIONS
166
171
  end
167
172
 
168
- PasswordPadding =
169
- "28BF4E5E4E758A4164004E56FFFA01082E2E00B6D0683E802F0CA9FE6453697A".
170
- scan(/../).map{|x| x.to_i(16)}.pack("c*")
173
+ PASSWORD_PADDING =
174
+ '28BF4E5E4E758A4164004E56FFFA01082E2E00B6D0683E802F0CA9FE6453697A'
175
+ .scan(/../).map { |x| x.to_i(16) }.pack('c*')
171
176
 
172
177
  # Pads or truncates a password to 32 bytes as per Alg 3.2.
173
178
  def pad_password(password)
174
179
  password = password[0, 32]
175
- password + PasswordPadding[0, 32 - password.length]
180
+ password + PASSWORD_PADDING[0, 32 - password.length]
176
181
  end
177
182
 
178
183
  def user_encryption_key
179
- @user_encryption_key ||= begin
180
- md5 = Digest::MD5.new
181
- md5 << pad_password(@user_password)
182
- md5 << owner_password_hash
183
- md5 << [permissions_value].pack("V")
184
- md5.digest[0, 5]
185
- 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
186
192
  end
187
193
 
188
194
  # The O (owner) value in the encryption dictionary. Algorithm 3.3.
189
195
  def owner_password_hash
190
- @owner_password_hash ||= begin
191
- key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
192
- Arcfour.new(key).encrypt(pad_password(@user_password))
193
- 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
194
201
  end
195
202
 
196
203
  # The U (user) value in the encryption dictionary. Algorithm 3.4.
197
204
  def user_password_hash
198
- Arcfour.new(user_encryption_key).encrypt(PasswordPadding)
205
+ Arcfour.new(user_encryption_key).encrypt(PASSWORD_PADDING)
199
206
  end
200
-
201
207
  end
202
-
203
208
  end
204
209
  end
205
210
 
@@ -208,56 +213,65 @@ module PDF
208
213
  module Core
209
214
  module_function
210
215
 
211
- # Like PdfObject, but returns an encrypted result if required.
216
+ # Like pdf_object, but returns an encrypted result if required.
212
217
  # For direct objects, requires the object identifier and generation number
213
218
  # from the indirect object referencing obj.
214
219
  #
215
220
  # @private
216
- def EncryptedPdfObject(obj, key, id, gen, in_content_stream=false)
221
+ def encrypted_pdf_object(obj, key, id, gen, in_content_stream = false)
217
222
  case obj
218
223
  when Array
219
- "[" << obj.map { |e|
220
- EncryptedPdfObject(e, key, id, gen, in_content_stream)
221
- }.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}]"
222
228
  when LiteralString
223
- 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}" }
224
233
  "(#{obj})"
225
234
  when Time
226
- obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
227
- 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}" }
228
240
  "(#{obj})"
229
241
  when String
230
- PdfObject(
242
+ pdf_object(
231
243
  ByteString.new(
232
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)),
233
- in_content_stream)
244
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen)
245
+ ),
246
+ in_content_stream
247
+ )
234
248
  when ::Hash
235
- output = "<< "
236
- obj.each do |k,v|
237
- unless String === k || Symbol === k
249
+ hash_content = obj.map do |k, v|
250
+ unless k.is_a?(String) || k.is_a?(Symbol)
238
251
  raise PDF::Core::Errors::FailedObjectConversion,
239
- "A PDF Dictionary must be keyed by names"
252
+ 'A PDF Dictionary must be keyed by names'
240
253
  end
241
- output << PdfObject(k.to_sym, in_content_stream) << " " <<
242
- EncryptedPdfObject(v, key, id, gen, in_content_stream) << "\n"
243
- end
244
- 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}>>"
245
257
  when NameTree::Value
246
- PdfObject(obj.name) + " " +
247
- 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)}"
248
259
  when PDF::Core::OutlineRoot, PDF::Core::OutlineItem
249
- EncryptedPdfObject(obj.to_hash, key, id, gen, in_content_stream)
250
- else # delegate back to PdfObject
251
- 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)
252
263
  end
253
264
  end
254
265
 
255
-
256
266
  # @private
257
267
  class Stream
258
268
  def encrypted_object(key, id, gen)
259
269
  if filtered_stream
260
- "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"
261
275
  else
262
276
  ''
263
277
  end
@@ -266,23 +280,24 @@ module PDF
266
280
 
267
281
  # @private
268
282
  class Reference
269
-
270
283
  # Returns the object definition for the object this references, keyed from
271
284
  # +key+.
272
285
  def encrypted_object(key)
273
- @on_encode.call(self) if @on_encode
286
+ @on_encode&.call(self)
274
287
 
275
- output = "#{@identifier} #{gen} obj\n"
276
- unless @stream.empty?
277
- output << PDF::Core::EncryptedPdfObject(data.merge(@stream.data), key, @identifier, gen) << "\n" <<
278
- @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"
279
292
  else
280
- 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)
281
297
  end
282
298
 
283
299
  output << "endobj\n"
284
300
  end
285
-
286
301
  end
287
302
  end
288
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,7 +8,6 @@
8
8
  #
9
9
 
10
10
  module Prawn
11
-
12
11
  # The Prawn::SoftMask module is used to create arbitrary transparency in
13
12
  # document. Using a soft mask allows creating more visually rich documents.
14
13
  #
@@ -29,59 +28,59 @@ module Prawn
29
28
  # @group Stable API
30
29
 
31
30
  def soft_mask(&block)
32
- min_version(1.4)
31
+ renderer.min_version(1.4)
33
32
 
34
- group_attrs = ref!({
35
- :Type => :Group,
36
- :S => :Transparency,
37
- :CS => :DeviceRGB,
38
- :I => false,
39
- :K => false
40
- })
33
+ group_attrs = ref!(
34
+ Type: :Group,
35
+ S: :Transparency,
36
+ CS: :DeviceRGB,
37
+ I: false,
38
+ K: false
39
+ )
41
40
 
42
- group = ref!({
43
- :Type => :XObject,
44
- :Subtype => :Form,
45
- :BBox => state.page.dimensions,
46
- :Group => group_attrs,
47
- })
41
+ group = ref!(
42
+ Type: :XObject,
43
+ Subtype: :Form,
44
+ BBox: state.page.dimensions,
45
+ Group: group_attrs
46
+ )
48
47
 
49
48
  state.page.stamp_stream(group, &block)
50
49
 
51
- mask = ref!({
52
- :Type => :Mask,
53
- :S => :Luminosity,
54
- :G => group
55
- })
50
+ mask = ref!(
51
+ Type: :Mask,
52
+ S: :Luminosity,
53
+ G: group
54
+ )
56
55
 
57
- g_state = ref!({
58
- :Type => :ExtGState,
59
- :SMask => mask,
56
+ g_state = ref!(
57
+ Type: :ExtGState,
58
+ SMask: mask,
60
59
 
61
- :AIS => false,
62
- :BM => :Normal,
63
- :OP => false,
64
- :op => false,
65
- :OPM => 1,
66
- :SA => true,
67
- })
60
+ AIS: false,
61
+ BM: :Normal,
62
+ OP: false,
63
+ op: false,
64
+ OPM: 1,
65
+ SA: true
66
+ )
68
67
 
69
68
  registry_key = {
70
- :bbox => state.page.dimensions,
71
- :mask => [group.stream.filters.normalized, group.stream.filtered_stream],
72
- :page => state.page_count,
69
+ bbox: state.page.dimensions,
70
+ mask: [group.stream.filters.normalized, group.stream.filtered_stream],
71
+ page: state.page_count
73
72
  }.hash
74
73
 
75
74
  if soft_mask_registry[registry_key]
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,7 +25,6 @@ module Prawn
27
25
  # pdf.stamp("my_stamp")
28
26
  #
29
27
  module Stamp
30
-
31
28
  # @group Stable API
32
29
 
33
30
  # Renders the stamp named <tt>name</tt> to the page
@@ -44,7 +41,8 @@ module Prawn
44
41
  #
45
42
  def stamp(name)
46
43
  dictionary_name, dictionary = stamp_dictionary(name)
47
- add_content "/#{dictionary_name} Do"
44
+ renderer.add_content "/#{dictionary_name} Do"
45
+ update_annotation_references dictionary.data[:Annots]
48
46
  state.page.xobjects.merge!(dictionary_name => dictionary)
49
47
  end
50
48
 
@@ -109,21 +107,39 @@ module Prawn
109
107
  def create_stamp_dictionary(name)
110
108
  raise Prawn::Errors::InvalidName if name.empty?
111
109
  raise Prawn::Errors::NameTaken unless stamp_dictionary_registry[name].nil?
110
+
112
111
  # BBox origin is the lower left margin of the page, so we need
113
112
  # it to be the full dimension of the page, or else things that
114
113
  # should appear near the top or right margin are invisible
115
- dictionary = ref!(:Type => :XObject,
116
- :Subtype => :Form,
117
- :BBox => [0, 0,
118
- 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
+ )
119
122
 
120
123
  dictionary_name = "Stamp#{next_stamp_dictionary_id}"
121
124
 
122
- stamp_dictionary_registry[name] = { :stamp_dictionary_name => dictionary_name,
123
- :stamp_dictionary => dictionary }
125
+ stamp_dictionary_registry[name] = {
126
+ stamp_dictionary_name: dictionary_name,
127
+ stamp_dictionary: dictionary
128
+ }
124
129
  dictionary
125
130
  end
126
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
+
127
143
  def freeze_stamp_graphics
128
144
  update_colors
129
145
  write_line_width
@@ -131,6 +147,5 @@ module Prawn
131
147
  write_stroke_join_style
132
148
  write_stroke_dash
133
149
  end
134
-
135
150
  end
136
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,7 +7,7 @@
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
@@ -40,6 +40,8 @@ module Prawn
40
40
  # <tt>:character_spacing</tt>:: <tt>number</tt>. The amount of space to add
41
41
  # to or remove from the default character
42
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]
43
45
  # <tt>:mode</tt>:: <tt>symbol</tt>. The text rendering mode. See
44
46
  # documentation for Prawn::Document#text_rendering_mode
45
47
  # for a list of valid options. [:fill]
@@ -50,7 +52,8 @@ module Prawn
50
52
  # <tt>[x, y]</tt>. The upper left corner of the box
51
53
  # [@document.bounds.left, @document.bounds.top]
52
54
  # <tt>:width</tt>::
53
- # <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]]
54
57
  # <tt>:height</tt>::
55
58
  # <tt>number</tt>. The height of the box [default_height()]
56
59
  # <tt>:direction</tt>::
@@ -58,7 +61,7 @@ module Prawn
58
61
  # or right-to-left) [value of document.text_direction]
59
62
  # <tt>:fallback_fonts</tt>::
60
63
  # An array of font names. Each name must be the name of an AFM font or
61
- # 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
62
65
  # Prawn::Document#font_families). If present, then each glyph will be
63
66
  # rendered using the first font that includes the glyph, starting with
64
67
  # the current font and then moving through :fallback_fonts from
@@ -70,7 +73,6 @@ module Prawn
70
73
  # <tt>:valign</tt>::
71
74
  # <tt>:top</tt>, <tt>:center</tt>, or <tt>:bottom</tt>. Vertical
72
75
  # alignment within the bounding box [:top]
73
- #
74
76
  # <tt>:rotate</tt>::
75
77
  # <tt>number</tt>. The angle to rotate the text
76
78
  # <tt>:rotate_around</tt>::
@@ -81,9 +83,8 @@ module Prawn
81
83
  # <tt>number</tt>. Additional space between lines [value of
82
84
  # document.default_leading]
83
85
  # <tt>:single_line</tt>::
84
- # <tt>boolean</tt>. If true, then only the first line will be drawn [false]
85
- # <tt>:skip_encoding</tt>::
86
- # <tt>boolean</tt> [false]
86
+ # <tt>boolean</tt>. If true, then only the first line will be drawn
87
+ # [false]
87
88
  # <tt>:overflow</tt>::
88
89
  # <tt>:truncate</tt>, <tt>:shrink_to_fit</tt>, or <tt>:expand</tt>
89
90
  # This controls the behavior when the amount of text
@@ -97,27 +98,24 @@ module Prawn
97
98
  #
98
99
  # Returns any text that did not print under the current settings.
99
100
  #
100
- # NOTE: if an AFM font is used, then the returned text is encoded in
101
- # WinAnsi. Subsequent calls to text_box that pass this returned text back
102
- # into text box must include a :skip_encoding => true option. This is
103
- # unnecessary when using TTF fonts because those operate on UTF-8 encoding.
104
- #
105
101
  # == Exceptions
106
102
  #
107
- # 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
108
104
  # any text
109
105
  #
110
- def text_box(string, options={})
106
+ def text_box(string, options = {})
111
107
  options = options.dup
112
108
  options[:document] = self
113
109
 
114
- box = if p = options.delete(:inline_format)
115
- p = [] unless p.is_a?(Array)
116
- array = self.text_formatter.format(string, *p)
117
- Text::Formatted::Box.new(array, options)
118
- else
119
- Text::Box.new(string, options)
120
- 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
121
119
 
122
120
  box.render
123
121
  end
@@ -131,17 +129,14 @@ module Prawn
131
129
  # consumed by the printed text
132
130
  #
133
131
  class Box < Prawn::Text::Formatted::Box
134
-
135
- def initialize(string, options={})
136
- super([{ :text => string }], options)
132
+ def initialize(string, options = {})
133
+ super([{ text: string }], options)
137
134
  end
138
135
 
139
- def render(flags={})
136
+ def render(flags = {})
140
137
  leftover = super(flags)
141
- leftover.collect { |hash| hash[:text] }.join
138
+ leftover.map { |hash| hash[:text] }.join
142
139
  end
143
-
144
140
  end
145
-
146
141
  end
147
142
  end