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
@@ -2,76 +2,195 @@
2
2
 
3
3
  require 'digest/sha1'
4
4
 
5
- # patterns.rb : Implements axial & radial gradients
6
- #
7
- # Originally implemented by Wojciech Piekutowski. November, 2009
8
- # Copyright September 2012, Alexander Mankuta. All Rights Reserved.
9
- #
10
- # This is free software. Please see the LICENSE and COPYING files for details.
11
- #
12
5
  module Prawn
13
6
  module Graphics
7
+ # Implements axial & radial gradients.
14
8
  module Patterns
9
+ # Gradient color stop.
10
+ # @private
15
11
  GradientStop = Struct.new(:position, :color)
12
+
13
+ # @private
16
14
  Gradient = Struct.new(
17
- :type, :apply_transformations, :stops, :from, :to, :r1, :r2
15
+ :type, :apply_transformations, :stops, :from, :to, :r1, :r2,
18
16
  )
19
17
 
20
18
  # @group Stable API
21
19
 
22
20
  # Sets the fill gradient.
23
- # old arguments:
24
- # from, to, color1, color2
25
- # or
26
- # from, r1, to, r2, color1, color2
27
- # new arguments:
28
- # from: [x, y]
29
- # to: [x, y]
30
- # r1: radius
31
- # r2: radius
32
- # stops: [color, color, ...] or
33
- # { position => color, position => color, ... }
34
- # apply_transformations: true
35
21
  #
36
- # Examples:
22
+ # @overload fill_gradient(from, to, color1, color2, apply_margin_options: false)
23
+ # Set an axial (linear) fill gradient.
37
24
  #
38
- # # draws a horizontal axial gradient that starts at red on the left
39
- # # and ends at blue on the right
40
- # fill_gradient from: [0, 0], to: [100, 0], stops: ['red', 'blue']
25
+ # @param from [Array(Number, Number)]
26
+ # Starting point of the gradient.
27
+ # @param to [Array(Number, Number)] ending point of the gradient.
28
+ # @param color1 [Color] starting color of the gradient.
29
+ # @param color2 [Color] ending color of the gradient.
30
+ # @param apply_transformations [Boolean] (false)
31
+ # If set `true`, will transform the gradient's co-ordinate space so it
32
+ # matches the current co-ordinate space of the document. This option
33
+ # will be the default from Prawn v3, and is default `true` if you use
34
+ # the all-keyword version of this method. The default for the
35
+ # positional arguments version (this one), `false`, will mean if you
36
+ # (for example) scale your document by 2 and put a gradient inside,
37
+ # you will have to manually multiply your co-ordinates by 2 so the
38
+ # gradient is correctly positioned.
39
+ # @return [void]
41
40
  #
42
- # # draws a horizontal radial gradient that starts at red, is green
43
- # # 80% of the way through, and finishes blue
44
- # fill_gradient from: [0, 0], r1: 0, to: [100, 0], r2: 180,
45
- # stops: { 0 => 'red', 0.8 => 'green', 1 => 'blue' }
41
+ # @overload fill_gradient(from, r1, to, r2, color1, color2, apply_margin_options: false)
42
+ # Set a radial fill gradient.
46
43
  #
47
- # <tt>from</tt> and <tt>to</tt> specify the axis of where the gradient
48
- # should be painted.
44
+ # @param from [Array(Number, Number)]
45
+ # Starting point of the gradient.
46
+ # @param r1 [Number]
47
+ # Radius of the starting circle of a radial gradient. The circle is
48
+ # centered at `from`.
49
+ # @param to [Array(Number, Number)]
50
+ # Ending point of the gradient.
51
+ # @param r2 [Number]
52
+ # Radius of the ending circle of a radial gradient. The circle is
53
+ # centered at `to`.
54
+ # @param color1 [Color]
55
+ # Starting color.
56
+ # @param color2 [Color]
57
+ # Ending color.
58
+ # @param apply_transformations [Boolean] (false)
59
+ # If set `true`, will transform the gradient's co-ordinate space so it
60
+ # matches the current co-ordinate space of the document. This option
61
+ # will be the default from Prawn v3, and is default `true` if you use
62
+ # the all-keyword version of this method. The default for the
63
+ # positional arguments version (this one), `false`, will mean if you
64
+ # (for example) scale your document by 2 and put a gradient inside,
65
+ # you will have to manually multiply your co-ordinates by 2 so the
66
+ # gradient is correctly positioned.
67
+ # @return [void]
49
68
  #
50
- # <tt>r1</tt> and <tt>r2</tt>, if specified, make a radial gradient with
51
- # the starting circle of radius <tt>r1</tt> centered at <tt>from</tt>
52
- # and ending at a circle of radius <tt>r2</tt> centered at <tt>to</tt>.
53
- # If <tt>r1</tt> is not specified, a axial gradient will be drawn.
69
+ # @overload fill_gradient(from:, to:, r1: nil, r2: nil, stops:, apply_margin_options: true)
70
+ # Set the fill gradient.
54
71
  #
55
- # <tt>stops</tt> is an array or hash of stops. Each stop is either just a
56
- # string indicating the color, in which case the stops will be evenly
57
- # distributed across the gradient, or a hash where the key is
58
- # a position between 0 and 1 indicating what distance through the
59
- # gradient the color should change, and the value is a color string.
72
+ # @example Draw a horizontal axial gradient that starts at red on the left and ends at blue on the right
73
+ # fill_gradient from: [0, 0], to: [100, 0], stops: ['ff0000', '0000ff']
74
+ #
75
+ # @example Draw a horizontal radial gradient that starts at red, is green 80% through, and finishes blue
76
+ # fill_gradient from: [0, 0], r1: 0, to: [100, 0], r2: 180,
77
+ # stops: { 0 => 'ff0000', 0.8 => '00ff00', 1 => '0000ff' }
60
78
  #
61
- # Option <tt>apply_transformations</tt>, if set true, will transform the
62
- # gradient's co-ordinate space so it matches the current co-ordinate
63
- # space of the document. This option will be the default from Prawn v3,
64
- # and is default true if you use the new arguments format.
65
- # The default for the old arguments format, false, will mean if you
66
- # (for example) scale your document by 2 and put a gradient inside, you
67
- # will have to manually multiply your co-ordinates by 2 so the gradient
68
- # is correctly positioned.
79
+ # @param from [Array(Number, Number)]
80
+ # Starting point of the gradient.
81
+ # @param r1 [Number, nil]
82
+ # Radius of the starting circle of a radial gradient. The circle is
83
+ # centered at `from`. If omitted a linear gradient will be produced.
84
+ # @param to [Array(Number, Number)]
85
+ # Ending point of the gradient.
86
+ # @param r2 [Number, nil]
87
+ # Radius of the ending circle of a radial gradient. The circle is
88
+ # centered at `to`.
89
+ # @param stops [Array<Color>, Hash{Number => Color}]
90
+ # Color stops. Each stop is either just a color, in which case the
91
+ # stops will be evenly distributed across the gradient, or a hash
92
+ # where the key is a position between 0 and 1 indicating what distance
93
+ # through the gradient the color should change, and the value is
94
+ # a color.
95
+ # @param apply_transformations [Boolean] (true)
96
+ # If set `true`, will transform the gradient's co-ordinate space so it
97
+ # matches the current co-ordinate space of the document. This option
98
+ # will be the default from Prawn v3, and is default `true` if you use
99
+ # the all-keyword version of this method (this one). The default for
100
+ # the old arguments format, `false`, will mean if you (for example)
101
+ # scale your document by 2 and put a gradient inside, you will have to
102
+ # manually multiply your co-ordinates by 2 so the gradient is
103
+ # correctly positioned.
104
+ # @return [void]
69
105
  def fill_gradient(*args, **kwargs)
70
106
  set_gradient(:fill, *args, **kwargs)
71
107
  end
72
108
 
73
109
  # Sets the stroke gradient.
74
- # See fill_gradient for a description of the arguments to this method.
110
+ #
111
+ # @overload fill_gradient(from, to, color1, color2, apply_margin_options: false)
112
+ # Set an axial (linear) stroke gradient.
113
+ #
114
+ # @param from [Array(Number, Number)]
115
+ # Starting point of the gradient.
116
+ # @param to [Array(Number, Number)] ending point of the gradient.
117
+ # @param color1 [Color] starting color of the gradient.
118
+ # @param color2 [Color] ending color of the gradient.
119
+ # @param apply_transformations [Boolean] (false)
120
+ # If set `true`, will transform the gradient's co-ordinate space so it
121
+ # matches the current co-ordinate space of the document. This option
122
+ # will be the default from Prawn v3, and is default `true` if you use
123
+ # the all-keyword version of this method. The default for the
124
+ # positional arguments version (this one), `false`, will mean if you
125
+ # (for example) scale your document by 2 and put a gradient inside,
126
+ # you will have to manually multiply your co-ordinates by 2 so the
127
+ # gradient is correctly positioned.
128
+ # @return [void]
129
+ #
130
+ # @overload fill_gradient(from, r1, to, r2, color1, color2, apply_margin_options: false)
131
+ # Set a radial stroke gradient.
132
+ #
133
+ # @param from [Array(Number, Number)]
134
+ # Starting point of the gradient.
135
+ # @param r1 [Number]
136
+ # Radius of the starting circle of a radial gradient. The circle is
137
+ # centered at `from`.
138
+ # @param to [Array(Number, Number)]
139
+ # Ending point of the gradient.
140
+ # @param r2 [Number]
141
+ # Radius of the ending circle of a radial gradient. The circle is
142
+ # centered at `to`.
143
+ # @param color1 [Color]
144
+ # Starting color.
145
+ # @param color2 [Color]
146
+ # Ending color.
147
+ # @param apply_transformations [Boolean] (false)
148
+ # If set `true`, will transform the gradient's co-ordinate space so it
149
+ # matches the current co-ordinate space of the document. This option
150
+ # will be the default from Prawn v3, and is default `true` if you use
151
+ # the all-keyword version of this method. The default for the
152
+ # positional arguments version (this one), `false`, will mean if you
153
+ # (for example) scale your document by 2 and put a gradient inside,
154
+ # you will have to manually multiply your co-ordinates by 2 so the
155
+ # gradient is correctly positioned.
156
+ # @return [void]
157
+ #
158
+ # @overload fill_gradient(from:, to:, r1: nil, r2: nil, stops:, apply_margin_options: true)
159
+ # Set the stroke gradient.
160
+ #
161
+ # @example Draw a horizontal axial gradient that starts at red on the left and ends at blue on the right
162
+ # stroke_gradient from: [0, 0], to: [100, 0], stops: ['ff0000', '0000ff']
163
+ #
164
+ # @example Draw a horizontal radial gradient that starts at red, is green 80% through, and finishes blue
165
+ # stroke_gradient from: [0, 0], r1: 0, to: [100, 0], r2: 180,
166
+ # stops: { 0 => 'ff0000', 0.8 => '00ff00', 1 => '0000ff' }
167
+ #
168
+ # @param from [Array(Number, Number)]
169
+ # Starting point of the gradient.
170
+ # @param r1 [Number, nil]
171
+ # Radius of the starting circle of a radial gradient. The circle is
172
+ # centered at `from`. If omitted a linear gradient will be produced.
173
+ # @param to [Array(Number, Number)]
174
+ # Ending point of the gradient.
175
+ # @param r2 [Number, nil]
176
+ # Radius of the ending circle of a radial gradient. The circle is
177
+ # centered at `to`.
178
+ # @param stops [Array<Color>, Hash{Number => Color}]
179
+ # Color stops. Each stop is either just a color, in which case the
180
+ # stops will be evenly distributed across the gradient, or a hash
181
+ # where the key is a position between 0 and 1 indicating what distance
182
+ # through the gradient the color should change, and the value is
183
+ # a color.
184
+ # @param apply_transformations [Boolean] (true)
185
+ # If set `true`, will transform the gradient's co-ordinate space so it
186
+ # matches the current co-ordinate space of the document. This option
187
+ # will be the default from Prawn v3, and is default `true` if you use
188
+ # the all-keyword version of this method (this one). The default for
189
+ # the old arguments format, `false`, will mean if you (for example)
190
+ # scale your document by 2 and put a gradient inside, you will have to
191
+ # manually multiply your co-ordinates by 2 so the gradient is
192
+ # correctly positioned.
193
+ # @return [void]
75
194
  def stroke_gradient(*args, **kwargs)
76
195
  set_gradient(:stroke, *args, **kwargs)
77
196
  end
@@ -83,9 +202,9 @@ module Prawn
83
202
 
84
203
  patterns = page.resources[:Pattern] ||= {}
85
204
 
86
- registry_key = gradient_registry_key gradient
205
+ registry_key = gradient_registry_key(gradient)
87
206
 
88
- unless patterns.key? "SP#{registry_key}"
207
+ unless patterns.key?("SP#{registry_key}")
89
208
  shading = gradient_registry[registry_key]
90
209
  unless shading
91
210
  shading = create_gradient_pattern(gradient)
@@ -95,17 +214,18 @@ module Prawn
95
214
  patterns["SP#{registry_key}"] = shading
96
215
  end
97
216
 
98
- operator = case type
99
- when :fill
100
- 'scn'
101
- when :stroke
102
- 'SCN'
103
- else
104
- raise ArgumentError, "unknown type '#{type}'"
105
- end
106
-
107
- set_color_space type, :Pattern
108
- renderer.add_content "/SP#{registry_key} #{operator}"
217
+ operator =
218
+ case type
219
+ when :fill
220
+ 'scn'
221
+ when :stroke
222
+ 'SCN'
223
+ else
224
+ raise ArgumentError, "unknown type '#{type}'"
225
+ end
226
+
227
+ set_color_space(type, :Pattern)
228
+ renderer.add_content("/SP#{registry_key} #{operator}")
109
229
  end
110
230
 
111
231
  # rubocop: disable Metrics/ParameterLists
@@ -113,6 +233,7 @@ module Prawn
113
233
  *arguments, from: nil, to: nil, r1: nil, r2: nil, stops: nil,
114
234
  apply_transformations: nil
115
235
  )
236
+
116
237
  case arguments.length
117
238
  when 0
118
239
  apply_transformations = true if apply_transformations.nil?
@@ -128,21 +249,22 @@ module Prawn
128
249
  raise ArgumentError, 'At least two stops must be specified'
129
250
  end
130
251
 
131
- stops = stops.map.with_index do |stop, index|
132
- case stop
133
- when Array, Hash
134
- position, color = stop
135
- else
136
- position = index / (stops.length.to_f - 1)
137
- color = stop
138
- end
252
+ stops =
253
+ stops.map.with_index { |stop, index|
254
+ case stop
255
+ when Array, Hash
256
+ position, color = stop
257
+ else
258
+ position = index / (Float(stops.length) - 1)
259
+ color = stop
260
+ end
139
261
 
140
- unless (0..1).cover?(position)
141
- raise ArgumentError, 'position must be between 0 and 1'
142
- end
262
+ unless (0..1).cover?(position)
263
+ raise ArgumentError, 'position must be between 0 and 1'
264
+ end
143
265
 
144
- GradientStop.new(position, normalize_color(color))
145
- end
266
+ GradientStop.new(position, normalize_color(color))
267
+ }
146
268
 
147
269
  if stops.first.position != 0
148
270
  raise ArgumentError, 'The first stop must have a position of 0'
@@ -159,8 +281,10 @@ module Prawn
159
281
  r1 ? :radial : :axial,
160
282
  apply_transformations,
161
283
  stops,
162
- from, to,
163
- r1, r2
284
+ from,
285
+ to,
286
+ r1,
287
+ r2,
164
288
  )
165
289
  end
166
290
  # rubocop: enable Metrics/ParameterLists
@@ -174,7 +298,7 @@ module Prawn
174
298
  x2, y2,
175
299
  gradient.r1 || -1, gradient.r2 || -1,
176
300
  gradient.stops.length,
177
- gradient.stops.map { |s| [s.position, s.color] }
301
+ gradient.stops.map { |s| [s.position, s.color] },
178
302
  ].flatten
179
303
  Digest::SHA1.hexdigest(key.join(','))
180
304
  end
@@ -187,58 +311,63 @@ module Prawn
187
311
  if gradient.apply_transformations.nil? &&
188
312
  current_transformation_matrix_with_translation(0, 0) !=
189
313
  [1, 0, 0, 1, 0, 0]
190
- warn 'Gradients in Prawn 2.x and lower are not correctly positioned '\
191
- 'when a transformation has been made to the document. ' \
192
- "Pass 'apply_transformations: true' to correctly transform the " \
193
- 'gradient, or see ' \
194
- 'https://github.com/prawnpdf/prawn/wiki/Gradient-Transformations ' \
195
- 'for more information.'
196
- end
197
-
198
- shader_stops = gradient.stops.each_cons(2).map do |first, second|
199
- ref!(
200
- FunctionType: 2,
201
- Domain: [0.0, 1.0],
202
- C0: first.color,
203
- C1: second.color,
204
- N: 1.0
314
+ warn(
315
+ 'Gradients in Prawn 2.x and lower are not correctly positioned ' \
316
+ 'when a transformation has been made to the document. ' \
317
+ "Pass 'apply_transformations: true' to correctly transform the " \
318
+ 'gradient, or see ' \
319
+ 'https://github.com/prawnpdf/prawn/wiki/Gradient-Transformations ' \
320
+ 'for more information.',
205
321
  )
206
322
  end
207
323
 
324
+ shader_stops =
325
+ gradient.stops.each_cons(2).map { |first, second|
326
+ ref!(
327
+ FunctionType: 2,
328
+ Domain: [0.0, 1.0],
329
+ C0: first.color,
330
+ C1: second.color,
331
+ N: 1.0,
332
+ )
333
+ }
334
+
208
335
  # If there's only two stops, we can use the single shader.
209
336
  # Otherwise we stitch the multiple shaders together.
210
- shader = if shader_stops.length == 1
211
- shader_stops.first
212
- else
213
- ref!(
214
- FunctionType: 3, # stitching function
215
- Domain: [0.0, 1.0],
216
- Functions: shader_stops,
217
- Bounds: gradient.stops[1..-2].map(&:position),
218
- Encode: [0.0, 1.0] * shader_stops.length
219
- )
220
- end
337
+ shader =
338
+ if shader_stops.length == 1
339
+ shader_stops.first
340
+ else
341
+ ref!(
342
+ FunctionType: 3, # stitching function
343
+ Domain: [0.0, 1.0],
344
+ Functions: shader_stops,
345
+ Bounds: gradient.stops[1..-2].map(&:position),
346
+ Encode: [0.0, 1.0] * shader_stops.length,
347
+ )
348
+ end
221
349
 
222
350
  x1, y1, x2, y2, transformation = gradient_coordinates(gradient)
223
351
 
224
- coords = if gradient.type == :axial
225
- [0, 0, x2 - x1, y2 - y1]
226
- else
227
- [0, 0, gradient.r1, x2 - x1, y2 - y1, gradient.r2]
228
- end
352
+ coords =
353
+ if gradient.type == :axial
354
+ [0, 0, x2 - x1, y2 - y1]
355
+ else
356
+ [0, 0, gradient.r1, x2 - x1, y2 - y1, gradient.r2]
357
+ end
229
358
 
230
359
  shading = ref!(
231
360
  ShadingType: gradient.type == :axial ? 2 : 3,
232
361
  ColorSpace: color_space(gradient.stops.first.color),
233
362
  Coords: coords,
234
363
  Function: shader,
235
- Extend: [true, true]
364
+ Extend: [true, true],
236
365
  )
237
366
 
238
367
  ref!(
239
368
  PatternType: 2, # shading pattern
240
369
  Shading: shading,
241
- Matrix: transformation
370
+ Matrix: transformation,
242
371
  )
243
372
  end
244
373
 
@@ -1,36 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # transformation.rb: Implements rotate, translate, skew, scale and a generic
4
- # transformation_matrix
5
- #
6
- # Copyright January 2010, Michael Witrant. All Rights Reserved.
7
- #
8
- # This is free software. Please see the LICENSE and COPYING files for details.
9
-
10
3
  module Prawn
11
4
  module Graphics
5
+ # Implements user-space coordinate transformation.
12
6
  module Transformation
13
7
  # @group Stable API
14
8
 
15
- # Rotate the user space. If a block is not provided, then you must save
9
+ # Rotate the user space. If a block is not provided, then you must save
16
10
  # and restore the graphics state yourself.
17
11
  #
18
- # == Options
19
- # <tt>:origin</tt>:: <tt>[number, number]</tt>. The point around which to
20
- # rotate. A block must be provided if using the :origin
21
- #
22
- # raises <tt>Prawn::Errors::BlockRequired</tt> if an :origin option is
23
- # provided, but no block is given
24
- #
25
- # Example without a block:
26
- #
12
+ # @example
27
13
  # save_graphics_state
28
14
  # rotate 30
29
15
  # text "rotated text"
30
16
  # restore_graphics_state
31
17
  #
32
- # Example with a block: rotating a rectangle around its upper-left corner
33
- #
18
+ # @example Rotating a rectangle around its upper-left corner
34
19
  # x = 300
35
20
  # y = 300
36
21
  # width = 150
@@ -40,6 +25,14 @@ module Prawn
40
25
  # pdf.stroke_rectangle([x, y], width, height)
41
26
  # end
42
27
  #
28
+ # @param angle [Number] Angle in degrees.
29
+ # @param options [Hash{Symbol => any}]
30
+ # @option options :origin [Array(Number, Number)] Rotation origin point.
31
+ # A block must be provided if specified.
32
+ # @yield
33
+ # @raise [Prawn::Errors::BlockRequired] if an `:origin` option is
34
+ # provided, but no block is given.
35
+ # @return [void]
43
36
  def rotate(angle, options = {}, &block)
44
37
  Prawn.verify_options(:origin, options)
45
38
  rad = degree_to_rad(angle)
@@ -48,31 +41,28 @@ module Prawn
48
41
  if options[:origin].nil?
49
42
  transformation_matrix(cos, sin, -sin, cos, 0, 0, &block)
50
43
  else
51
- raise Prawn::Errors::BlockRequired unless block_given?
44
+ raise Prawn::Errors::BlockRequired unless block
52
45
 
53
46
  x = options[:origin][0] + bounds.absolute_left
54
47
  y = options[:origin][1] + bounds.absolute_bottom
55
- x_prime = x * cos - y * sin
56
- y_prime = x * sin + y * cos
48
+ x_prime = (x * cos) - (y * sin)
49
+ y_prime = (x * sin) + (y * cos)
57
50
  translate(x - x_prime, y - y_prime) do
58
51
  transformation_matrix(cos, sin, -sin, cos, 0, 0, &block)
59
52
  end
60
53
  end
61
54
  end
62
55
 
63
- # Translate the user space. If a block is not provided, then you must
56
+ # Translate the user space. If a block is not provided, then you must
64
57
  # save and restore the graphics state yourself.
65
58
  #
66
- # Example without a block: move the text up and over 10
67
- #
59
+ # @example Move the text up and over 10
68
60
  # save_graphics_state
69
61
  # translate(10, 10)
70
62
  # text "scaled text"
71
63
  # restore_graphics_state
72
64
  #
73
- # Example with a block: draw a rectangle with its upper-left corner at
74
- # x + 10, y + 10
75
- #
65
+ # @example draw a rectangle with its upper-left corner at x + 10, y + 10
76
66
  # x = 300
77
67
  # y = 300
78
68
  # width = 150
@@ -81,29 +71,24 @@ module Prawn
81
71
  # pdf.stroke_rectangle([x, y], width, height)
82
72
  # end
83
73
  #
74
+ # @param x [Number]
75
+ # @param y [Number]
76
+ # @yield
77
+ # @return [void]
84
78
  def translate(x, y, &block)
85
79
  transformation_matrix(1, 0, 0, 1, x, y, &block)
86
80
  end
87
81
 
88
- # Scale the user space. If a block is not provided, then you must save
82
+ # Scale the user space. If a block is not provided, then you must save
89
83
  # and restore the graphics state yourself.
90
84
  #
91
- # == Options
92
- # <tt>:origin</tt>:: <tt>[number, number]</tt>. The point from which to
93
- # scale. A block must be provided if using the :origin
94
- #
95
- # raises <tt>Prawn::Errors::BlockRequired</tt> if an :origin option is
96
- # provided, but no block is given
97
- #
98
- # Example without a block:
99
- #
85
+ # @example
100
86
  # save_graphics_state
101
87
  # scale 1.5
102
88
  # text "scaled text"
103
89
  # restore_graphics_state
104
90
  #
105
- # Example with a block: scale a rectangle from its upper-left corner
106
- #
91
+ # @example Scale a rectangle from its upper-left corner
107
92
  # x = 300
108
93
  # y = 300
109
94
  # width = 150
@@ -113,12 +98,20 @@ module Prawn
113
98
  # pdf.stroke_rectangle([x, y], width, height)
114
99
  # end
115
100
  #
101
+ # @param factor [Number] Scale factor.
102
+ # @param options [Hash{Symbol => any}]
103
+ # @option options :origin [Array(Number, Number)] The point from which to
104
+ # scale. A block must be provided if specified.
105
+ # @yield
106
+ # @raise [Prawn::Errors::BlockRequired] If an `:origin` option is
107
+ # provided, but no block is given.
108
+ # @return [void]
116
109
  def scale(factor, options = {}, &block)
117
110
  Prawn.verify_options(:origin, options)
118
111
  if options[:origin].nil?
119
112
  transformation_matrix(factor, 0, 0, factor, 0, 0, &block)
120
113
  else
121
- raise Prawn::Errors::BlockRequired unless block_given?
114
+ raise Prawn::Errors::BlockRequired unless block
122
115
 
123
116
  x = options[:origin][0] + bounds.absolute_left
124
117
  y = options[:origin][1] + bounds.absolute_bottom
@@ -142,19 +135,33 @@ module Prawn
142
135
  # end
143
136
 
144
137
  # Transform the user space (see notes for rotate regarding graphics state)
145
- # Generally, one would use the rotate, scale, translate, and skew
138
+ # Generally, one would use the {rotate}, {scale}, and {translate}
146
139
  # convenience methods instead of calling transformation_matrix directly
140
+ #
141
+ # @param matrix [Array(Number, Number, Number, Number, Number, Number)]
142
+ # Transformation matrix.
143
+ #
144
+ # The six elements correspond to the following elements of the
145
+ # transformation matrix:
146
+ #
147
+ # ```plain
148
+ # a b 0
149
+ # c d 0
150
+ # e f 0
151
+ # ```
152
+ # @yield
153
+ # @return [void]
147
154
  def transformation_matrix(*matrix)
148
155
  if matrix.length != 6
149
156
  raise ArgumentError,
150
157
  'Transformation matrix must have exacty 6 elements'
151
158
  end
152
- values = matrix.map { |x| x.to_f.round(5) }.join(' ')
153
159
  save_graphics_state if block_given?
154
160
 
155
161
  add_to_transformation_stack(*matrix)
156
162
 
157
- renderer.add_content "#{values} cm"
163
+ values = PDF::Core.real_params(matrix)
164
+ renderer.add_content("#{values} cm")
158
165
  if block_given?
159
166
  yield
160
167
  restore_graphics_state