prawn 2.3.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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