prawn 2.4.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 +213 -141
  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 +20 -18
  7. data/lib/prawn/document.rb +257 -171
  8. data/lib/prawn/encoding.rb +2 -5
  9. data/lib/prawn/errors.rb +23 -34
  10. data/lib/prawn/font.rb +248 -135
  11. data/lib/prawn/font_metric_cache.rb +11 -10
  12. data/lib/prawn/fonts/afm.rb +85 -45
  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 +305 -93
  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 +57 -34
  22. data/lib/prawn/graphics/dash.rb +45 -42
  23. data/lib/prawn/graphics/join_style.rb +17 -11
  24. data/lib/prawn/graphics/patterns.rb +190 -69
  25. data/lib/prawn/graphics/transformation.rb +48 -41
  26. data/lib/prawn/graphics/transparency.rb +16 -40
  27. data/lib/prawn/graphics.rb +363 -253
  28. data/lib/prawn/grid.rb +184 -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 +42 -19
  32. data/lib/prawn/images/png.rb +92 -41
  33. data/lib/prawn/images.rb +44 -57
  34. data/lib/prawn/measurement_extensions.rb +39 -8
  35. data/lib/prawn/measurements.rb +60 -5
  36. data/lib/prawn/outline.rb +114 -108
  37. data/lib/prawn/repeater.rb +51 -35
  38. data/lib/prawn/security/arcfour.rb +4 -4
  39. data/lib/prawn/security.rb +75 -70
  40. data/lib/prawn/soft_mask.rb +42 -30
  41. data/lib/prawn/stamp.rb +38 -42
  42. data/lib/prawn/text/box.rb +146 -96
  43. data/lib/prawn/text/formatted/arranger.rb +87 -26
  44. data/lib/prawn/text/formatted/box.rb +221 -150
  45. data/lib/prawn/text/formatted/fragment.rb +130 -14
  46. data/lib/prawn/text/formatted/line_wrap.rb +33 -24
  47. data/lib/prawn/text/formatted/parser.rb +112 -72
  48. data/lib/prawn/text/formatted/wrap.rb +12 -17
  49. data/lib/prawn/text/formatted.rb +75 -0
  50. data/lib/prawn/text.rb +441 -196
  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 +68 -53
  55. data/lib/prawn.rb +23 -18
  56. data.tar.gz.sig +0 -0
  57. metadata +54 -177
  58. metadata.gz.sig +0 -0
  59. data/.yardopts +0 -10
  60. data/Gemfile +0 -5
  61. data/Rakefile +0 -25
  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 -29
  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 -23
  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 -38
  94. data/manual/graphics/gradients.rb +0 -43
  95. data/manual/graphics/graphics.rb +0 -64
  96. data/manual/graphics/helper.rb +0 -34
  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 -29
  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 -30
  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 -43
  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 -25
  142. data/manual/text/formatted_callbacks.rb +0 -70
  143. data/manual/text/formatted_text.rb +0 -61
  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 -31
  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 -52
  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 -51
  160. data/manual/text/utf8.rb +0 -27
  161. data/manual/text/win_ansi_charset.rb +0 -62
  162. data/prawn.gemspec +0 -51
  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 -550
  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 -44
  173. data/spec/prawn/document_spec.rb +0 -805
  174. data/spec/prawn/font_metric_cache_spec.rb +0 -54
  175. data/spec/prawn/font_spec.rb +0 -544
  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 -872
  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 -229
  184. data/spec/prawn/measurements_extensions_spec.rb +0 -24
  185. data/spec/prawn/outline_spec.rb +0 -512
  186. data/spec/prawn/repeater_spec.rb +0 -166
  187. data/spec/prawn/soft_mask_spec.rb +0 -74
  188. data/spec/prawn/stamp_spec.rb +0 -173
  189. data/spec/prawn/text/box_spec.rb +0 -1110
  190. data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
  191. data/spec/prawn/text/formatted/box_spec.rb +0 -849
  192. data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
  193. data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -495
  194. data/spec/prawn/text/formatted/parser_spec.rb +0 -697
  195. data/spec/prawn/text_draw_text_spec.rb +0 -150
  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]
@@ -128,7 +124,7 @@ module Prawn
128
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
 
@@ -210,7 +206,7 @@ end
210
206
 
211
207
  # @private
212
208
  module PDF
213
- module Core
209
+ module Core # rubocop: disable Style/Documentation
214
210
  module_function
215
211
 
216
212
  # Like pdf_object, but returns an encrypted result if required.
@@ -221,38 +217,38 @@ module PDF
221
217
  def encrypted_pdf_object(obj, key, id, gen, in_content_stream = false)
222
218
  case obj
223
219
  when Array
224
- array_content = obj.map do |e|
220
+ array_content = obj.map { |e|
225
221
  encrypted_pdf_object(e, key, id, gen, in_content_stream)
226
- end.join(' ')
222
+ }.join(' ')
227
223
  "[#{array_content}]"
228
224
  when LiteralString
229
225
  obj =
230
226
  ByteString.new(
231
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
232
- ).gsub(/[\\\n()]/) { |m| "\\#{m}" }
227
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen),
228
+ ).gsub(/[\\\r()]/, STRING_ESCAPE_MAP)
233
229
  "(#{obj})"
234
230
  when Time
235
231
  obj = "#{obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop}'00'"
236
232
  obj =
237
233
  ByteString.new(
238
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
239
- ).gsub(/[\\\n()]/) { |m| "\\#{m}" }
234
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen),
235
+ ).gsub(/[\\\r()]/, STRING_ESCAPE_MAP)
240
236
  "(#{obj})"
241
237
  when String
242
238
  pdf_object(
243
239
  ByteString.new(
244
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
240
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen),
245
241
  ),
246
- in_content_stream
242
+ in_content_stream,
247
243
  )
248
244
  when ::Hash
249
- hash_content = obj.map do |k, v|
245
+ hash_content = obj.map { |k, v|
250
246
  unless k.is_a?(String) || k.is_a?(Symbol)
251
247
  raise PDF::Core::Errors::FailedObjectConversion,
252
248
  'A PDF Dictionary must be keyed by names'
253
249
  end
254
250
  "#{pdf_object(k.to_sym, in_content_stream)} #{encrypted_pdf_object(v, key, id, gen, in_content_stream)}\n"
255
- end.join('')
251
+ }.join('')
256
252
  "<< #{hash_content}>>"
257
253
  when NameTree::Value
258
254
  "#{pdf_object(obj.name)} #{encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)}"
@@ -265,11 +261,17 @@ module PDF
265
261
 
266
262
  # @private
267
263
  class Stream
264
+ # Encrypt stream.
265
+ #
266
+ # @param key [String]
267
+ # @param id [Integer]
268
+ # @param gen [Integer]
269
+ # @return [String]
268
270
  def encrypted_object(key, id, gen)
269
271
  if filtered_stream
270
272
  "stream\n#{
271
273
  Prawn::Document::Security.encrypt_string(
272
- filtered_stream, key, id, gen
274
+ filtered_stream, key, id, gen,
273
275
  )
274
276
  }\nendstream\n"
275
277
  else
@@ -281,7 +283,10 @@ module PDF
281
283
  # @private
282
284
  class Reference
283
285
  # Returns the object definition for the object this references, keyed from
284
- # +key+.
286
+ # `key`.
287
+ #
288
+ # @param key [String]
289
+ # @return [String]
285
290
  def encrypted_object(key)
286
291
  @on_encode&.call(self)
287
292
 
@@ -291,7 +296,7 @@ module PDF
291
296
  PDF::Core.encrypted_pdf_object(data, key, @identifier, gen) << "\n"
292
297
  else
293
298
  output << PDF::Core.encrypted_pdf_object(
294
- data.merge(@stream.data), key, @identifier, gen
299
+ data.merge(@stream.data), key, @identifier, gen,
295
300
  ) << "\n" <<
296
301
  @stream.encrypted_object(key, @identifier, gen)
297
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