prawn 2.3.0 → 2.5.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 (203) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/prawn/document/bounding_box.rb +223 -143
  4. data/lib/prawn/document/column_box.rb +61 -26
  5. data/lib/prawn/document/internals.rb +25 -16
  6. data/lib/prawn/document/span.rb +21 -18
  7. data/lib/prawn/document.rb +273 -182
  8. data/lib/prawn/encoding.rb +2 -5
  9. data/lib/prawn/errors.rb +23 -34
  10. data/lib/prawn/font.rb +254 -139
  11. data/lib/prawn/font_metric_cache.rb +18 -16
  12. data/lib/prawn/fonts/afm.rb +99 -57
  13. data/lib/prawn/fonts/dfont.rb +7 -1
  14. data/lib/prawn/fonts/otf.rb +4 -1
  15. data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  16. data/lib/prawn/fonts/ttc.rb +7 -2
  17. data/lib/prawn/fonts/ttf.rb +345 -107
  18. data/lib/prawn/fonts.rb +14 -0
  19. data/lib/prawn/graphics/blend_mode.rb +25 -28
  20. data/lib/prawn/graphics/cap_style.rb +9 -12
  21. data/lib/prawn/graphics/color.rb +75 -50
  22. data/lib/prawn/graphics/dash.rb +45 -42
  23. data/lib/prawn/graphics/join_style.rb +18 -12
  24. data/lib/prawn/graphics/patterns.rb +239 -110
  25. data/lib/prawn/graphics/transformation.rb +51 -44
  26. data/lib/prawn/graphics/transparency.rb +16 -40
  27. data/lib/prawn/graphics.rb +370 -260
  28. data/lib/prawn/grid.rb +219 -57
  29. data/lib/prawn/image_handler.rb +27 -10
  30. data/lib/prawn/images/image.rb +8 -10
  31. data/lib/prawn/images/jpg.rb +46 -20
  32. data/lib/prawn/images/png.rb +94 -42
  33. data/lib/prawn/images.rb +70 -81
  34. data/lib/prawn/measurement_extensions.rb +39 -8
  35. data/lib/prawn/measurements.rb +60 -5
  36. data/lib/prawn/outline.rb +120 -113
  37. data/lib/prawn/repeater.rb +52 -36
  38. data/lib/prawn/security/arcfour.rb +4 -4
  39. data/lib/prawn/security.rb +106 -98
  40. data/lib/prawn/soft_mask.rb +42 -30
  41. data/lib/prawn/stamp.rb +38 -42
  42. data/lib/prawn/text/box.rb +156 -105
  43. data/lib/prawn/text/formatted/arranger.rb +121 -41
  44. data/lib/prawn/text/formatted/box.rb +239 -163
  45. data/lib/prawn/text/formatted/fragment.rb +130 -14
  46. data/lib/prawn/text/formatted/line_wrap.rb +49 -38
  47. data/lib/prawn/text/formatted/parser.rb +116 -74
  48. data/lib/prawn/text/formatted/wrap.rb +25 -26
  49. data/lib/prawn/text/formatted.rb +75 -0
  50. data/lib/prawn/text.rb +456 -211
  51. data/lib/prawn/transformation_stack.rb +29 -10
  52. data/lib/prawn/utilities.rb +13 -13
  53. data/lib/prawn/version.rb +2 -1
  54. data/lib/prawn/view.rb +69 -54
  55. data/lib/prawn.rb +24 -18
  56. data.tar.gz.sig +0 -0
  57. metadata +55 -262
  58. metadata.gz.sig +3 -4
  59. data/.yardopts +0 -10
  60. data/Gemfile +0 -5
  61. data/Rakefile +0 -54
  62. data/manual/absolute_position.pdf +0 -0
  63. data/manual/basic_concepts/adding_pages.rb +0 -26
  64. data/manual/basic_concepts/basic_concepts.rb +0 -43
  65. data/manual/basic_concepts/creation.rb +0 -38
  66. data/manual/basic_concepts/cursor.rb +0 -32
  67. data/manual/basic_concepts/measurement.rb +0 -24
  68. data/manual/basic_concepts/origin.rb +0 -37
  69. data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
  70. data/manual/basic_concepts/view.rb +0 -48
  71. data/manual/bounding_box/bounding_box.rb +0 -41
  72. data/manual/bounding_box/bounds.rb +0 -48
  73. data/manual/bounding_box/canvas.rb +0 -23
  74. data/manual/bounding_box/creation.rb +0 -22
  75. data/manual/bounding_box/indentation.rb +0 -45
  76. data/manual/bounding_box/nesting.rb +0 -52
  77. data/manual/bounding_box/russian_boxes.rb +0 -40
  78. data/manual/bounding_box/stretchy.rb +0 -29
  79. data/manual/contents.rb +0 -35
  80. data/manual/cover.rb +0 -43
  81. data/manual/document_and_page_options/background.rb +0 -25
  82. data/manual/document_and_page_options/document_and_page_options.rb +0 -34
  83. data/manual/document_and_page_options/metadata.rb +0 -25
  84. data/manual/document_and_page_options/page_margins.rb +0 -36
  85. data/manual/document_and_page_options/page_size.rb +0 -34
  86. data/manual/document_and_page_options/print_scaling.rb +0 -22
  87. data/manual/example_helper.rb +0 -8
  88. data/manual/graphics/blend_mode.rb +0 -52
  89. data/manual/graphics/circle_and_ellipse.rb +0 -21
  90. data/manual/graphics/color.rb +0 -22
  91. data/manual/graphics/common_lines.rb +0 -29
  92. data/manual/graphics/fill_and_stroke.rb +0 -41
  93. data/manual/graphics/fill_rules.rb +0 -37
  94. data/manual/graphics/gradients.rb +0 -43
  95. data/manual/graphics/graphics.rb +0 -64
  96. data/manual/graphics/helper.rb +0 -27
  97. data/manual/graphics/line_width.rb +0 -36
  98. data/manual/graphics/lines_and_curves.rb +0 -40
  99. data/manual/graphics/polygon.rb +0 -27
  100. data/manual/graphics/rectangle.rb +0 -20
  101. data/manual/graphics/rotate.rb +0 -25
  102. data/manual/graphics/scale.rb +0 -42
  103. data/manual/graphics/soft_masks.rb +0 -44
  104. data/manual/graphics/stroke_cap.rb +0 -30
  105. data/manual/graphics/stroke_dash.rb +0 -47
  106. data/manual/graphics/stroke_join.rb +0 -29
  107. data/manual/graphics/translate.rb +0 -28
  108. data/manual/graphics/transparency.rb +0 -33
  109. data/manual/how_to_read_this_manual.rb +0 -39
  110. data/manual/images/absolute_position.rb +0 -22
  111. data/manual/images/fit.rb +0 -20
  112. data/manual/images/horizontal.rb +0 -24
  113. data/manual/images/images.rb +0 -41
  114. data/manual/images/plain_image.rb +0 -17
  115. data/manual/images/scale.rb +0 -21
  116. data/manual/images/vertical.rb +0 -27
  117. data/manual/images/width_and_height.rb +0 -24
  118. data/manual/layout/boxes.rb +0 -26
  119. data/manual/layout/content.rb +0 -24
  120. data/manual/layout/layout.rb +0 -27
  121. data/manual/layout/simple_grid.rb +0 -22
  122. data/manual/outline/add_subsection_to.rb +0 -60
  123. data/manual/outline/insert_section_after.rb +0 -46
  124. data/manual/outline/outline.rb +0 -33
  125. data/manual/outline/sections_and_pages.rb +0 -66
  126. data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
  127. data/manual/repeatable_content/page_numbering.rb +0 -55
  128. data/manual/repeatable_content/repeatable_content.rb +0 -35
  129. data/manual/repeatable_content/repeater.rb +0 -54
  130. data/manual/repeatable_content/stamp.rb +0 -40
  131. data/manual/security/encryption.rb +0 -28
  132. data/manual/security/permissions.rb +0 -41
  133. data/manual/security/security.rb +0 -28
  134. data/manual/table.rb +0 -16
  135. data/manual/text/alignment.rb +0 -43
  136. data/manual/text/color.rb +0 -24
  137. data/manual/text/column_box.rb +0 -30
  138. data/manual/text/fallback_fonts.rb +0 -41
  139. data/manual/text/font.rb +0 -40
  140. data/manual/text/font_size.rb +0 -44
  141. data/manual/text/font_style.rb +0 -22
  142. data/manual/text/formatted_callbacks.rb +0 -65
  143. data/manual/text/formatted_text.rb +0 -58
  144. data/manual/text/free_flowing_text.rb +0 -50
  145. data/manual/text/inline.rb +0 -40
  146. data/manual/text/kerning_and_character_spacing.rb +0 -38
  147. data/manual/text/leading.rb +0 -24
  148. data/manual/text/line_wrapping.rb +0 -60
  149. data/manual/text/paragraph_indentation.rb +0 -32
  150. data/manual/text/positioned_text.rb +0 -37
  151. data/manual/text/registering_families.rb +0 -51
  152. data/manual/text/rendering_and_color.rb +0 -36
  153. data/manual/text/right_to_left_text.rb +0 -54
  154. data/manual/text/rotation.rb +0 -47
  155. data/manual/text/single_usage.rb +0 -36
  156. data/manual/text/text.rb +0 -75
  157. data/manual/text/text_box_excess.rb +0 -35
  158. data/manual/text/text_box_extensions.rb +0 -48
  159. data/manual/text/text_box_overflow.rb +0 -49
  160. data/manual/text/utf8.rb +0 -27
  161. data/manual/text/win_ansi_charset.rb +0 -62
  162. data/prawn.gemspec +0 -57
  163. data/spec/data/curves.pdf +0 -66
  164. data/spec/extensions/encoding_helpers.rb +0 -11
  165. data/spec/prawn/document/bounding_box_spec.rb +0 -546
  166. data/spec/prawn/document/column_box_spec.rb +0 -75
  167. data/spec/prawn/document/security_spec.rb +0 -176
  168. data/spec/prawn/document_annotations_spec.rb +0 -76
  169. data/spec/prawn/document_destinations_spec.rb +0 -15
  170. data/spec/prawn/document_grid_spec.rb +0 -99
  171. data/spec/prawn/document_reference_spec.rb +0 -27
  172. data/spec/prawn/document_span_spec.rb +0 -36
  173. data/spec/prawn/document_spec.rb +0 -802
  174. data/spec/prawn/font_metric_cache_spec.rb +0 -54
  175. data/spec/prawn/font_spec.rb +0 -542
  176. data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
  177. data/spec/prawn/graphics/transparency_spec.rb +0 -81
  178. data/spec/prawn/graphics_spec.rb +0 -837
  179. data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
  180. data/spec/prawn/image_handler_spec.rb +0 -53
  181. data/spec/prawn/images/jpg_spec.rb +0 -20
  182. data/spec/prawn/images/png_spec.rb +0 -283
  183. data/spec/prawn/images_spec.rb +0 -224
  184. data/spec/prawn/measurements_extensions_spec.rb +0 -24
  185. data/spec/prawn/outline_spec.rb +0 -412
  186. data/spec/prawn/repeater_spec.rb +0 -165
  187. data/spec/prawn/soft_mask_spec.rb +0 -74
  188. data/spec/prawn/stamp_spec.rb +0 -172
  189. data/spec/prawn/text/box_spec.rb +0 -1112
  190. data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
  191. data/spec/prawn/text/formatted/box_spec.rb +0 -846
  192. data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
  193. data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
  194. data/spec/prawn/text/formatted/parser_spec.rb +0 -697
  195. data/spec/prawn/text_draw_text_spec.rb +0 -149
  196. data/spec/prawn/text_rendering_mode_spec.rb +0 -48
  197. data/spec/prawn/text_spacing_spec.rb +0 -95
  198. data/spec/prawn/text_spec.rb +0 -603
  199. data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
  200. data/spec/prawn/transformation_stack_spec.rb +0 -66
  201. data/spec/prawn/view_spec.rb +0 -63
  202. data/spec/prawn_manual_spec.rb +0 -35
  203. data/spec/spec_helper.rb +0 -48
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # encryption.rb : Implements encrypted PDF and access permissions.
4
- #
5
- # Copyright August 2008, Brad Ediger. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
-
9
3
  require 'digest/md5'
10
4
 
11
5
  require_relative 'security/arcfour'
@@ -18,76 +12,71 @@ module Prawn
18
12
  # @group Experimental API
19
13
 
20
14
  # Encrypts the document, to protect confidential data or control
21
- # modifications to the document. The encryption algorithm used is
22
- # detailed in the PDF Reference 1.3, section 3.5 "Encryption", and it is
15
+ # modifications to the document. The encryption algorithm used is detailed
16
+ # in the PDF Reference 1.3, section 3.5 "Encryption", and it is
23
17
  # implemented by all major PDF readers.
24
18
  #
25
- # +options+ can contain the following:
26
- #
27
- # <tt>:user_password</tt>:: Password required to open the document. If
28
- # this is omitted or empty, no password will be
29
- # required. The document will still be
30
- # encrypted, but anyone can read it.
31
- #
32
- # <tt>:owner_password</tt>:: Password required to make modifications to
33
- # the document or change or override its
34
- # permissions. If this is set to
35
- # <tt>:random</tt>, a random password will be
36
- # used; this can be useful if you never want
37
- # users to be able to override the document
38
- # permissions.
39
- #
40
- # <tt>:permissions</tt>:: A hash mapping permission symbols (see below) to
41
- # <tt>true</tt> or <tt>false</tt>. True means
42
- # "permitted", and false means "not permitted".
43
- # All permissions default to <tt>true</tt>.
44
- #
45
- # The following permissions can be specified:
46
- #
47
- # <tt>:print_document</tt>:: Print document.
48
- #
49
- # <tt>:modify_contents</tt>:: Modify contents of document (other than text
50
- # annotations and interactive form fields).
51
- #
52
- # <tt>:copy_contents</tt>:: Copy text and graphics from document.
53
- #
54
- # <tt>:modify_annotations</tt>:: Add or modify text annotations and
55
- # interactive form fields.
56
- #
57
- # == Examples
19
+ # #### Examples
58
20
  #
59
21
  # Deny printing to everyone, but allow anyone to open without a password:
60
22
  #
61
- # encrypt_document :permissions => { :print_document => false },
62
- # :owner_password => :random
23
+ # ```ruby
24
+ # encrypt_document permissions: { print_document: false },
25
+ # owner_password: :random
26
+ # ```
63
27
  #
64
28
  # Set a user and owner password on the document, with full permissions for
65
29
  # both the user and the owner:
66
30
  #
67
- # encrypt_document :user_password => 'foo', :owner_password => 'bar'
31
+ # ```ruby
32
+ # encrypt_document user_password: 'foo', owner_password: 'bar'
33
+ # ```
68
34
  #
69
35
  # Set no passwords, grant all permissions (This is useful because the
70
36
  # default in some readers, if no permissions are specified, is "deny"):
71
37
  #
72
- # encrypt_document
38
+ # ```ruby
39
+ # encrypt_document
40
+ # ```
73
41
  #
74
- # == Caveats
42
+ # #### Caveats
75
43
  #
76
44
  # * The encryption used is weak; the key is password-derived and is
77
45
  # limited to 40 bits, due to US export controls in effect at the time
78
46
  # the PDF standard was written.
79
- #
80
47
  # * There is nothing technologically requiring PDF readers to respect the
81
48
  # permissions embedded in a document. Many PDF readers do not.
82
- #
83
- # * In short, you have <b>no security at all</b> against a moderately
49
+ # * In short, you have **no security at all** against a moderately
84
50
  # motivated person. Don't use this for anything super-serious. This is
85
51
  # not a limitation of Prawn, but is rather a built-in limitation of the
86
52
  # PDF format.
87
53
  #
54
+ # @param options [Hash{Symbol => any}]
55
+ # @option options :user_password [String]
56
+ # Password required to open the document. If this is omitted or empty,
57
+ # no password will be required. The document will still be encrypted,
58
+ # but anyone can read it.
59
+ # @option options :owner_password [String, :random]
60
+ # Password required to make modifications to the document or change or
61
+ # override its permissions. If this is set to `:random`, a random
62
+ # password will be used; this can be useful if you never want users to
63
+ # be able to override the document permissions.
64
+ # @option options :permissions [Hash{Symbol => Boolean}]
65
+ # A hash mapping permission symbols (see below) to `true` or `false`.
66
+ # `true` means "permitted", and `false` means "not permitted". All
67
+ # permissions default to `true`.
68
+ #
69
+ # The following permissions can be specified:
70
+ #
71
+ # - `:print_document` -- Print document.
72
+ # - `:modify_contents` -- Modify contents of document (other than text
73
+ # annotations and interactive form fields).
74
+ # - `:copy_contents` -- Copy text and graphics from document.
75
+ # - `:modify_annotations` -- Add or modify text annotations and
76
+ # interactive form fields.
77
+ # @return [void]
88
78
  def encrypt_document(options = {})
89
- Prawn.verify_options %i[user_password owner_password permissions],
90
- options
79
+ Prawn.verify_options(%i[user_password owner_password permissions], options)
91
80
  @user_password = options.delete(:user_password) || ''
92
81
 
93
82
  @owner_password = options.delete(:owner_password) || @user_password
@@ -104,9 +93,16 @@ module Prawn
104
93
  state.encryption_key = user_encryption_key
105
94
  end
106
95
 
107
- # Encrypts the given string under the given key, also requiring the
108
- # object ID and generation number of the reference.
96
+ # Encrypts the given string under the given key, also requiring the object
97
+ # ID and generation number of the reference.
98
+ #
109
99
  # See Algorithm 3.1.
100
+ #
101
+ # @param str [String]
102
+ # @param key [String]
103
+ # @param id [Integer]
104
+ # @param gen [Integer]
105
+ # @return [String]
110
106
  def self.encrypt_string(str, key, id, gen)
111
107
  # Convert ID and Gen number into little-endian truncated byte strings
112
108
  id = [id].pack('V')[0, 3]
@@ -124,11 +120,11 @@ module Prawn
124
120
  def encryption_dictionary
125
121
  {
126
122
  Filter: :Standard, # default PDF security handler
127
- V: 1, # "Algorithm 3.1", PDF reference 1.3
128
- R: 2, # Revision 2 of the algorithm
123
+ V: 1, # "Algorithm 3.1", PDF reference 1.3
124
+ R: 2, # Revision 2 of the algorithm
129
125
  O: PDF::Core::ByteString.new(owner_password_hash),
130
126
  U: PDF::Core::ByteString.new(user_password_hash),
131
- P: permissions_value
127
+ P: permissions_value,
132
128
  }
133
129
  end
134
130
 
@@ -137,7 +133,7 @@ module Prawn
137
133
  print_document: 3,
138
134
  modify_contents: 4,
139
135
  copy_contents: 5,
140
- modify_annotations: 6
136
+ modify_annotations: 6,
141
137
  }.freeze
142
138
  private_constant :PERMISSIONS_BITS
143
139
 
@@ -151,7 +147,7 @@ module Prawn
151
147
  raise(
152
148
  ArgumentError,
153
149
  "Unknown permission :#{key}. Valid options: " +
154
- PERMISSIONS_BITS.keys.map(&:inspect).join(', ')
150
+ PERMISSIONS_BITS.keys.map(&:inspect).join(', '),
155
151
  )
156
152
  end
157
153
 
@@ -181,21 +177,23 @@ module Prawn
181
177
  end
182
178
 
183
179
  def user_encryption_key
184
- @user_encryption_key ||= begin
185
- md5 = Digest::MD5.new
186
- md5 << pad_password(@user_password)
187
- md5 << owner_password_hash
188
- md5 << [permissions_value].pack('V')
189
- md5.digest[0, 5]
190
- end
180
+ @user_encryption_key ||=
181
+ begin
182
+ md5 = Digest::MD5.new
183
+ md5 << pad_password(@user_password)
184
+ md5 << owner_password_hash
185
+ md5 << [permissions_value].pack('V')
186
+ md5.digest[0, 5]
187
+ end
191
188
  end
192
189
 
193
190
  # The O (owner) value in the encryption dictionary. Algorithm 3.3.
194
191
  def owner_password_hash
195
- @owner_password_hash ||= begin
196
- key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
197
- Arcfour.new(key).encrypt(pad_password(@user_password))
198
- end
192
+ @owner_password_hash ||=
193
+ begin
194
+ key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
195
+ Arcfour.new(key).encrypt(pad_password(@user_password))
196
+ end
199
197
  end
200
198
 
201
199
  # The U (user) value in the encryption dictionary. Algorithm 3.4.
@@ -208,7 +206,7 @@ end
208
206
 
209
207
  # @private
210
208
  module PDF
211
- module Core
209
+ module Core # rubocop: disable Style/Documentation
212
210
  module_function
213
211
 
214
212
  # Like pdf_object, but returns an encrypted result if required.
@@ -219,41 +217,41 @@ module PDF
219
217
  def encrypted_pdf_object(obj, key, id, gen, in_content_stream = false)
220
218
  case obj
221
219
  when Array
222
- '[' + obj.map do |e|
220
+ array_content = obj.map { |e|
223
221
  encrypted_pdf_object(e, key, id, gen, in_content_stream)
224
- end.join(' ') + ']'
222
+ }.join(' ')
223
+ "[#{array_content}]"
225
224
  when LiteralString
226
- obj = ByteString.new(
227
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
228
- ).gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
225
+ obj =
226
+ ByteString.new(
227
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen),
228
+ ).gsub(/[\\\r()]/, STRING_ESCAPE_MAP)
229
229
  "(#{obj})"
230
230
  when Time
231
- obj = obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop + "'00'"
232
- obj = ByteString.new(
233
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
234
- ).gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
231
+ obj = "#{obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop}'00'"
232
+ obj =
233
+ ByteString.new(
234
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen),
235
+ ).gsub(/[\\\r()]/, STRING_ESCAPE_MAP)
235
236
  "(#{obj})"
236
237
  when String
237
238
  pdf_object(
238
239
  ByteString.new(
239
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
240
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen),
240
241
  ),
241
- in_content_stream
242
+ in_content_stream,
242
243
  )
243
244
  when ::Hash
244
- '<< ' +
245
- obj.map do |k, v|
246
- unless k.is_a?(String) || k.is_a?(Symbol)
247
- raise PDF::Core::Errors::FailedObjectConversion,
248
- 'A PDF Dictionary must be keyed by names'
249
- end
250
- pdf_object(k.to_sym, in_content_stream) + ' ' +
251
- encrypted_pdf_object(v, key, id, gen, in_content_stream) + "\n"
252
- end.join('') +
253
- '>>'
245
+ hash_content = obj.map { |k, v|
246
+ unless k.is_a?(String) || k.is_a?(Symbol)
247
+ raise PDF::Core::Errors::FailedObjectConversion,
248
+ 'A PDF Dictionary must be keyed by names'
249
+ end
250
+ "#{pdf_object(k.to_sym, in_content_stream)} #{encrypted_pdf_object(v, key, id, gen, in_content_stream)}\n"
251
+ }.join('')
252
+ "<< #{hash_content}>>"
254
253
  when NameTree::Value
255
- pdf_object(obj.name) + ' ' +
256
- encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)
254
+ "#{pdf_object(obj.name)} #{encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)}"
257
255
  when PDF::Core::OutlineRoot, PDF::Core::OutlineItem
258
256
  encrypted_pdf_object(obj.to_hash, key, id, gen, in_content_stream)
259
257
  else # delegate back to pdf_object
@@ -263,12 +261,19 @@ module PDF
263
261
 
264
262
  # @private
265
263
  class Stream
264
+ # Encrypt stream.
265
+ #
266
+ # @param key [String]
267
+ # @param id [Integer]
268
+ # @param gen [Integer]
269
+ # @return [String]
266
270
  def encrypted_object(key, id, gen)
267
271
  if filtered_stream
268
- "stream\n" +
272
+ "stream\n#{
269
273
  Prawn::Document::Security.encrypt_string(
270
- filtered_stream, key, id, gen
271
- ) + "\nendstream\n"
274
+ filtered_stream, key, id, gen,
275
+ )
276
+ }\nendstream\n"
272
277
  else
273
278
  ''
274
279
  end
@@ -278,7 +283,10 @@ module PDF
278
283
  # @private
279
284
  class Reference
280
285
  # Returns the object definition for the object this references, keyed from
281
- # +key+.
286
+ # `key`.
287
+ #
288
+ # @param key [String]
289
+ # @return [String]
282
290
  def encrypted_object(key)
283
291
  @on_encode&.call(self)
284
292
 
@@ -288,7 +296,7 @@ module PDF
288
296
  PDF::Core.encrypted_pdf_object(data, key, @identifier, gen) << "\n"
289
297
  else
290
298
  output << PDF::Core.encrypted_pdf_object(
291
- data.merge(@stream.data), key, @identifier, gen
299
+ data.merge(@stream.data), key, @identifier, gen,
292
300
  ) << "\n" <<
293
301
  @stream.encrypted_object(key, @identifier, gen)
294
302
  end
@@ -1,32 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # soft_mask.rb : Implements soft-masking
4
- #
5
- # Copyright September 2012, Alexander Mankuta. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
- #
9
-
10
3
  module Prawn
11
- # The Prawn::SoftMask module is used to create arbitrary transparency in
12
- # document. Using a soft mask allows creating more visually rich documents.
13
- #
14
- # You must group soft mask and graphics it's applied to under
15
- # save_graphics_state because soft mask is a part of graphic state in PDF.
16
- #
17
- # Example:
18
- # pdf.save_graphics_state do
19
- # pdf.soft_mask do
20
- # pdf.fill_color "444444"
21
- # pdf.fill_polygon [0, 40], [60, 10], [120, 40], [60, 68]
22
- # end
23
- # pdf.fill_color '000000'
24
- # pdf.fill_rectangle [0, 50], 120, 68
25
- # end
26
- #
4
+ # This module is used to create arbitrary transparency in document. Using
5
+ # a soft mask allows creating more visually rich documents.
27
6
  module SoftMask
28
7
  # @group Stable API
29
8
 
9
+ # Apply soft mask.
10
+ #
11
+ # You must group soft mask and graphics it's applied to under
12
+ # `save_graphics_state` because soft mask is a part of graphic state in PDF.
13
+ #
14
+ # Note that soft mask is applied only to the following content in the
15
+ # graphic state. Anything that comes before `soft_mask` is drawn without
16
+ # mask.
17
+ #
18
+ # Conceptually, soft mask is an alpha channel. Luminosity of the drawing in
19
+ # the soft mask defines the transparency of the drawing the mask is applied
20
+ # to. 0.0 mask luminosity ("black") results in a fully opaque target image and
21
+ # 1.0 mask luminosity ("white") results in a fully transparent target image.
22
+ # Grey values result in some semi-transparent target image.
23
+ #
24
+ # Note: you can use color in mask drawings but it makes harder to reason
25
+ # about the resulting value of alpha channel as it requires an additional
26
+ # luminosity calculation. However, this also allows achieving some advanced
27
+ # artistic effects (e.g. full-color photos in masks to get an effect similar
28
+ # to double exposure).
29
+ #
30
+ # @example
31
+ # pdf.save_graphics_state do
32
+ # pdf.soft_mask do
33
+ # pdf.fill_color "444444"
34
+ # pdf.fill_polygon [0, 40], [60, 10], [120, 40], [60, 68]
35
+ # end
36
+ # pdf.fill_color '000000'
37
+ # pdf.fill_rectangle [0, 50], 120, 68
38
+ # end
39
+ #
40
+ # @yield Mask content.
41
+ # @return [void]
30
42
  def soft_mask(&block)
31
43
  renderer.min_version(1.4)
32
44
 
@@ -35,14 +47,14 @@ module Prawn
35
47
  S: :Transparency,
36
48
  CS: :DeviceRGB,
37
49
  I: false,
38
- K: false
50
+ K: false,
39
51
  )
40
52
 
41
53
  group = ref!(
42
54
  Type: :XObject,
43
55
  Subtype: :Form,
44
56
  BBox: state.page.dimensions,
45
- Group: group_attrs
57
+ Group: group_attrs,
46
58
  )
47
59
 
48
60
  state.page.stamp_stream(group, &block)
@@ -50,7 +62,7 @@ module Prawn
50
62
  mask = ref!(
51
63
  Type: :Mask,
52
64
  S: :Luminosity,
53
- G: group
65
+ G: group,
54
66
  )
55
67
 
56
68
  g_state = ref!(
@@ -62,17 +74,17 @@ module Prawn
62
74
  OP: false,
63
75
  op: false,
64
76
  OPM: 1,
65
- SA: true
77
+ SA: true,
66
78
  )
67
79
 
68
80
  registry_key = {
69
81
  bbox: state.page.dimensions,
70
82
  mask: [group.stream.filters.normalized, group.stream.filtered_stream],
71
- page: state.page_count
83
+ page: state.page_count,
72
84
  }.hash
73
85
 
74
86
  if soft_mask_registry[registry_key]
75
- renderer.add_content "/#{soft_mask_registry[registry_key]} gs"
87
+ renderer.add_content("/#{soft_mask_registry[registry_key]} gs")
76
88
  else
77
89
  masks = page.resources[:ExtGState] ||= {}
78
90
  id = masks.empty? ? 'GS1' : masks.keys.max.succ
@@ -80,7 +92,7 @@ module Prawn
80
92
 
81
93
  soft_mask_registry[registry_key] = id
82
94
 
83
- renderer.add_content "/#{id} gs"
95
+ renderer.add_content("/#{id} gs")
84
96
  end
85
97
  end
86
98
 
data/lib/prawn/stamp.rb CHANGED
@@ -1,80 +1,76 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # stamp.rb : Implements a repeatable stamp
4
- #
5
- # Copyright October 2009, Daniel Nelson. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
- #
9
3
  module Prawn
10
- # The Prawn::Stamp module is used to create content that will be
11
- # included multiple times in a document. Using a stamp has three
12
- # advantages over creating content anew each time it is placed on
13
- # the page:
14
- # i. faster document creation
15
- # ii. smaller final document
16
- # iii. faster display on subsequent displays of the repeated
17
- # element because the viewer application can cache the rendered
18
- # results
4
+ # This module is used to create content that will be included multiple times
5
+ # in a document. Using a stamp has three advantages over creating content anew
6
+ # each time it is placed on the page:
7
+ # * Faster document creation.
8
+ # * Smaller final document.
9
+ # * Faster display on subsequent displays of the repeated element because the
10
+ # viewer application can cache the rendered results.
19
11
  #
20
- # Example:
12
+ # @example
21
13
  # pdf.create_stamp("my_stamp") {
22
14
  # pdf.fill_circle([10, 15], 5)
23
- # pdf.draw_text("hello world", :at => [20, 10])
15
+ # pdf.draw_text("hello world", at: [20, 10])
24
16
  # }
25
17
  # pdf.stamp("my_stamp")
26
- #
27
18
  module Stamp
28
19
  # @group Stable API
29
20
 
30
- # Renders the stamp named <tt>name</tt> to the page
31
- # raises <tt>Prawn::Errors::InvalidName</tt> if name.empty?
32
- # raises <tt>Prawn::Errors::UndefinedObjectName</tt> if no stamp
33
- # has been created with this name
21
+ # Renders the stamp.
34
22
  #
35
- # Example:
23
+ # @example
36
24
  # pdf.create_stamp("my_stamp") {
37
25
  # pdf.fill_circle([10, 15], 5)
38
- # pdf.text("hello world", :at => [20, 10])
26
+ # pdf.text("hello world", at: [20, 10])
39
27
  # }
40
28
  # pdf.stamp("my_stamp")
41
29
  #
30
+ # @param name [String]
31
+ # @return [void]
32
+ # @raise [Prawn::Errors::InvalidName] if name is empty.
33
+ # @raise [Prawn::Errors::UndefinedObjectName] if no stamp has been created
34
+ # with this name.
42
35
  def stamp(name)
43
36
  dictionary_name, dictionary = stamp_dictionary(name)
44
- renderer.add_content "/#{dictionary_name} Do"
45
- update_annotation_references dictionary.data[:Annots]
37
+ renderer.add_content("/#{dictionary_name} Do")
38
+ update_annotation_references(dictionary.data[:Annots])
46
39
  state.page.xobjects.merge!(dictionary_name => dictionary)
47
40
  end
48
41
 
49
- # Renders the stamp named <tt>name</tt> at a position offset from
50
- # the initial coords at which the elements of the stamp was
51
- # created
42
+ # Renders the stamp at a position offset from the initial coords at which
43
+ # the elements of the stamp was created.
52
44
  #
53
- # Example:
45
+ # @example
54
46
  # pdf.create_stamp("circle") do
55
47
  # pdf.fill_circle([0, 0], 25)
56
48
  # end
57
49
  # # draws a circle at 100, 100
58
50
  # pdf.stamp_at("circle", [100, 100])
59
51
  #
60
- # See stamp() for exceptions that might be raised
61
- #
52
+ # @param name [String]
53
+ # @param point [Array(Number, Number)]
54
+ # @return [void]
55
+ # @see [stamp] for exceptions that might be raised.
62
56
  def stamp_at(name, point)
63
57
  translate(point[0], point[1]) { stamp(name) }
64
58
  end
65
59
 
66
- # Creates a re-usable stamp named <tt>name</tt>
67
- #
68
- # raises <tt>Prawn::Errors::NameTaken</tt> if a stamp already
69
- # exists in this document with this name
70
- # raises <tt>Prawn::Errors::InvalidName</tt> if name.empty?
60
+ # Creates a re-usable stamp.
71
61
  #
72
- # Example:
62
+ # @example
73
63
  # pdf.create_stamp("my_stamp") {
74
64
  # pdf.fill_circle([10, 15], 5)
75
- # pdf.draw_text("hello world", :at => [20, 10])
65
+ # pdf.draw_text("hello world", at: [20, 10])
76
66
  # }
77
67
  #
68
+ # @param name [String] Stamp name.
69
+ # @yield Stamp content.
70
+ # @return [void]
71
+ # @raise [Prawn::Errors::NameTaken]
72
+ # if a stamp already exists in this document with this name.
73
+ # @raise [Prawn::Errors::InvalidName] if name is empty.
78
74
  def create_stamp(name, &block)
79
75
  dictionary = create_stamp_dictionary(name)
80
76
 
@@ -116,15 +112,15 @@ module Prawn
116
112
  Subtype: :Form,
117
113
  BBox: [
118
114
  0, 0,
119
- state.page.dimensions[2], state.page.dimensions[3]
120
- ]
115
+ state.page.dimensions[2], state.page.dimensions[3],
116
+ ],
121
117
  )
122
118
 
123
119
  dictionary_name = "Stamp#{next_stamp_dictionary_id}"
124
120
 
125
121
  stamp_dictionary_registry[name] = {
126
122
  stamp_dictionary_name: dictionary_name,
127
- stamp_dictionary: dictionary
123
+ stamp_dictionary: dictionary,
128
124
  }
129
125
  dictionary
130
126
  end