prawn 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/prawn/document/bounding_box.rb +223 -143
  4. data/lib/prawn/document/column_box.rb +61 -26
  5. data/lib/prawn/document/internals.rb +25 -16
  6. data/lib/prawn/document/span.rb +21 -18
  7. data/lib/prawn/document.rb +273 -182
  8. data/lib/prawn/encoding.rb +2 -5
  9. data/lib/prawn/errors.rb +23 -34
  10. data/lib/prawn/font.rb +254 -139
  11. data/lib/prawn/font_metric_cache.rb +18 -16
  12. data/lib/prawn/fonts/afm.rb +99 -57
  13. data/lib/prawn/fonts/dfont.rb +7 -1
  14. data/lib/prawn/fonts/otf.rb +4 -1
  15. data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  16. data/lib/prawn/fonts/ttc.rb +7 -2
  17. data/lib/prawn/fonts/ttf.rb +345 -107
  18. data/lib/prawn/fonts.rb +14 -0
  19. data/lib/prawn/graphics/blend_mode.rb +25 -28
  20. data/lib/prawn/graphics/cap_style.rb +9 -12
  21. data/lib/prawn/graphics/color.rb +75 -50
  22. data/lib/prawn/graphics/dash.rb +45 -42
  23. data/lib/prawn/graphics/join_style.rb +18 -12
  24. data/lib/prawn/graphics/patterns.rb +239 -110
  25. data/lib/prawn/graphics/transformation.rb +51 -44
  26. data/lib/prawn/graphics/transparency.rb +16 -40
  27. data/lib/prawn/graphics.rb +370 -260
  28. data/lib/prawn/grid.rb +219 -57
  29. data/lib/prawn/image_handler.rb +27 -10
  30. data/lib/prawn/images/image.rb +8 -10
  31. data/lib/prawn/images/jpg.rb +46 -20
  32. data/lib/prawn/images/png.rb +94 -42
  33. data/lib/prawn/images.rb +70 -81
  34. data/lib/prawn/measurement_extensions.rb +39 -8
  35. data/lib/prawn/measurements.rb +60 -5
  36. data/lib/prawn/outline.rb +120 -113
  37. data/lib/prawn/repeater.rb +52 -36
  38. data/lib/prawn/security/arcfour.rb +4 -4
  39. data/lib/prawn/security.rb +106 -98
  40. data/lib/prawn/soft_mask.rb +42 -30
  41. data/lib/prawn/stamp.rb +38 -42
  42. data/lib/prawn/text/box.rb +156 -105
  43. data/lib/prawn/text/formatted/arranger.rb +121 -41
  44. data/lib/prawn/text/formatted/box.rb +239 -163
  45. data/lib/prawn/text/formatted/fragment.rb +130 -14
  46. data/lib/prawn/text/formatted/line_wrap.rb +49 -38
  47. data/lib/prawn/text/formatted/parser.rb +116 -74
  48. data/lib/prawn/text/formatted/wrap.rb +25 -26
  49. data/lib/prawn/text/formatted.rb +75 -0
  50. data/lib/prawn/text.rb +456 -211
  51. data/lib/prawn/transformation_stack.rb +29 -10
  52. data/lib/prawn/utilities.rb +13 -13
  53. data/lib/prawn/version.rb +2 -1
  54. data/lib/prawn/view.rb +69 -54
  55. data/lib/prawn.rb +24 -18
  56. data.tar.gz.sig +0 -0
  57. metadata +55 -262
  58. metadata.gz.sig +3 -4
  59. data/.yardopts +0 -10
  60. data/Gemfile +0 -5
  61. data/Rakefile +0 -54
  62. data/manual/absolute_position.pdf +0 -0
  63. data/manual/basic_concepts/adding_pages.rb +0 -26
  64. data/manual/basic_concepts/basic_concepts.rb +0 -43
  65. data/manual/basic_concepts/creation.rb +0 -38
  66. data/manual/basic_concepts/cursor.rb +0 -32
  67. data/manual/basic_concepts/measurement.rb +0 -24
  68. data/manual/basic_concepts/origin.rb +0 -37
  69. data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
  70. data/manual/basic_concepts/view.rb +0 -48
  71. data/manual/bounding_box/bounding_box.rb +0 -41
  72. data/manual/bounding_box/bounds.rb +0 -48
  73. data/manual/bounding_box/canvas.rb +0 -23
  74. data/manual/bounding_box/creation.rb +0 -22
  75. data/manual/bounding_box/indentation.rb +0 -45
  76. data/manual/bounding_box/nesting.rb +0 -52
  77. data/manual/bounding_box/russian_boxes.rb +0 -40
  78. data/manual/bounding_box/stretchy.rb +0 -29
  79. data/manual/contents.rb +0 -35
  80. data/manual/cover.rb +0 -43
  81. data/manual/document_and_page_options/background.rb +0 -25
  82. data/manual/document_and_page_options/document_and_page_options.rb +0 -34
  83. data/manual/document_and_page_options/metadata.rb +0 -25
  84. data/manual/document_and_page_options/page_margins.rb +0 -36
  85. data/manual/document_and_page_options/page_size.rb +0 -34
  86. data/manual/document_and_page_options/print_scaling.rb +0 -22
  87. data/manual/example_helper.rb +0 -8
  88. data/manual/graphics/blend_mode.rb +0 -52
  89. data/manual/graphics/circle_and_ellipse.rb +0 -21
  90. data/manual/graphics/color.rb +0 -22
  91. data/manual/graphics/common_lines.rb +0 -29
  92. data/manual/graphics/fill_and_stroke.rb +0 -41
  93. data/manual/graphics/fill_rules.rb +0 -37
  94. data/manual/graphics/gradients.rb +0 -43
  95. data/manual/graphics/graphics.rb +0 -64
  96. data/manual/graphics/helper.rb +0 -27
  97. data/manual/graphics/line_width.rb +0 -36
  98. data/manual/graphics/lines_and_curves.rb +0 -40
  99. data/manual/graphics/polygon.rb +0 -27
  100. data/manual/graphics/rectangle.rb +0 -20
  101. data/manual/graphics/rotate.rb +0 -25
  102. data/manual/graphics/scale.rb +0 -42
  103. data/manual/graphics/soft_masks.rb +0 -44
  104. data/manual/graphics/stroke_cap.rb +0 -30
  105. data/manual/graphics/stroke_dash.rb +0 -47
  106. data/manual/graphics/stroke_join.rb +0 -29
  107. data/manual/graphics/translate.rb +0 -28
  108. data/manual/graphics/transparency.rb +0 -33
  109. data/manual/how_to_read_this_manual.rb +0 -39
  110. data/manual/images/absolute_position.rb +0 -22
  111. data/manual/images/fit.rb +0 -20
  112. data/manual/images/horizontal.rb +0 -24
  113. data/manual/images/images.rb +0 -41
  114. data/manual/images/plain_image.rb +0 -17
  115. data/manual/images/scale.rb +0 -21
  116. data/manual/images/vertical.rb +0 -27
  117. data/manual/images/width_and_height.rb +0 -24
  118. data/manual/layout/boxes.rb +0 -26
  119. data/manual/layout/content.rb +0 -24
  120. data/manual/layout/layout.rb +0 -27
  121. data/manual/layout/simple_grid.rb +0 -22
  122. data/manual/outline/add_subsection_to.rb +0 -60
  123. data/manual/outline/insert_section_after.rb +0 -46
  124. data/manual/outline/outline.rb +0 -33
  125. data/manual/outline/sections_and_pages.rb +0 -66
  126. data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
  127. data/manual/repeatable_content/page_numbering.rb +0 -55
  128. data/manual/repeatable_content/repeatable_content.rb +0 -35
  129. data/manual/repeatable_content/repeater.rb +0 -54
  130. data/manual/repeatable_content/stamp.rb +0 -40
  131. data/manual/security/encryption.rb +0 -28
  132. data/manual/security/permissions.rb +0 -41
  133. data/manual/security/security.rb +0 -28
  134. data/manual/table.rb +0 -16
  135. data/manual/text/alignment.rb +0 -43
  136. data/manual/text/color.rb +0 -24
  137. data/manual/text/column_box.rb +0 -30
  138. data/manual/text/fallback_fonts.rb +0 -41
  139. data/manual/text/font.rb +0 -40
  140. data/manual/text/font_size.rb +0 -44
  141. data/manual/text/font_style.rb +0 -22
  142. data/manual/text/formatted_callbacks.rb +0 -65
  143. data/manual/text/formatted_text.rb +0 -58
  144. data/manual/text/free_flowing_text.rb +0 -50
  145. data/manual/text/inline.rb +0 -40
  146. data/manual/text/kerning_and_character_spacing.rb +0 -38
  147. data/manual/text/leading.rb +0 -24
  148. data/manual/text/line_wrapping.rb +0 -60
  149. data/manual/text/paragraph_indentation.rb +0 -32
  150. data/manual/text/positioned_text.rb +0 -37
  151. data/manual/text/registering_families.rb +0 -51
  152. data/manual/text/rendering_and_color.rb +0 -36
  153. data/manual/text/right_to_left_text.rb +0 -54
  154. data/manual/text/rotation.rb +0 -47
  155. data/manual/text/single_usage.rb +0 -36
  156. data/manual/text/text.rb +0 -75
  157. data/manual/text/text_box_excess.rb +0 -35
  158. data/manual/text/text_box_extensions.rb +0 -48
  159. data/manual/text/text_box_overflow.rb +0 -49
  160. data/manual/text/utf8.rb +0 -27
  161. data/manual/text/win_ansi_charset.rb +0 -62
  162. data/prawn.gemspec +0 -57
  163. data/spec/data/curves.pdf +0 -66
  164. data/spec/extensions/encoding_helpers.rb +0 -11
  165. data/spec/prawn/document/bounding_box_spec.rb +0 -546
  166. data/spec/prawn/document/column_box_spec.rb +0 -75
  167. data/spec/prawn/document/security_spec.rb +0 -176
  168. data/spec/prawn/document_annotations_spec.rb +0 -76
  169. data/spec/prawn/document_destinations_spec.rb +0 -15
  170. data/spec/prawn/document_grid_spec.rb +0 -99
  171. data/spec/prawn/document_reference_spec.rb +0 -27
  172. data/spec/prawn/document_span_spec.rb +0 -36
  173. data/spec/prawn/document_spec.rb +0 -802
  174. data/spec/prawn/font_metric_cache_spec.rb +0 -54
  175. data/spec/prawn/font_spec.rb +0 -542
  176. data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
  177. data/spec/prawn/graphics/transparency_spec.rb +0 -81
  178. data/spec/prawn/graphics_spec.rb +0 -837
  179. data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
  180. data/spec/prawn/image_handler_spec.rb +0 -53
  181. data/spec/prawn/images/jpg_spec.rb +0 -20
  182. data/spec/prawn/images/png_spec.rb +0 -283
  183. data/spec/prawn/images_spec.rb +0 -224
  184. data/spec/prawn/measurements_extensions_spec.rb +0 -24
  185. data/spec/prawn/outline_spec.rb +0 -412
  186. data/spec/prawn/repeater_spec.rb +0 -165
  187. data/spec/prawn/soft_mask_spec.rb +0 -74
  188. data/spec/prawn/stamp_spec.rb +0 -172
  189. data/spec/prawn/text/box_spec.rb +0 -1112
  190. data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
  191. data/spec/prawn/text/formatted/box_spec.rb +0 -846
  192. data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
  193. data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
  194. data/spec/prawn/text/formatted/parser_spec.rb +0 -697
  195. data/spec/prawn/text_draw_text_spec.rb +0 -149
  196. data/spec/prawn/text_rendering_mode_spec.rb +0 -48
  197. data/spec/prawn/text_spacing_spec.rb +0 -95
  198. data/spec/prawn/text_spec.rb +0 -603
  199. data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
  200. data/spec/prawn/transformation_stack_spec.rb +0 -66
  201. data/spec/prawn/view_spec.rb +0 -63
  202. data/spec/prawn_manual_spec.rb +0 -35
  203. data/spec/spec_helper.rb +0 -48
@@ -1,42 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # text/formatted/parser.rb : Implements a bi-directional parser between a subset
4
- # of html and formatted text arrays
5
- #
6
- # Copyright February 2010, Daniel Nelson. All Rights Reserved.
7
- #
8
- # This is free software. Please see the LICENSE and COPYING files for details.
9
- #
10
-
11
3
  module Prawn
12
4
  module Text
13
5
  module Formatted
6
+ # Implements a bi-directional parser between a subset of html and
7
+ # formatted text arrays.
14
8
  class Parser
15
9
  # @group Extension API
16
10
 
17
- PARSER_REGEX = begin
18
- regex_string = "\n|" \
19
- '<b>|</b>|' \
20
- '<i>|</i>|' \
21
- '<u>|</u>|' \
22
- '<strikethrough>|</strikethrough>|' \
23
- '<sub>|</sub>|' \
24
- '<sup>|</sup>|' \
25
- '<link[^>]*>|</link>|' \
26
- '<color[^>]*>|</color>|' \
27
- '<font[^>]*>|</font>|' \
28
- '<strong>|</strong>|' \
29
- '<em>|</em>|' \
30
- '<a[^>]*>|</a>|' \
31
- "[^<\n]+"
32
- Regexp.new(regex_string, Regexp::MULTILINE)
33
- end
11
+ # Parser regular expression.
12
+ # @private
13
+ PARSER_REGEX =
14
+ begin
15
+ regex_string =
16
+ "\n|" \
17
+ '<b>|</b>|' \
18
+ '<i>|</i>|' \
19
+ '<u>|</u>|' \
20
+ '<strikethrough>|</strikethrough>|' \
21
+ '<sub>|</sub>|' \
22
+ '<sup>|</sup>|' \
23
+ '<link[^>]*>|</link>|' \
24
+ '<color[^>]*>|</color>|' \
25
+ '<font[^>]*>|</font>|' \
26
+ '<strong>|</strong>|' \
27
+ '<em>|</em>|' \
28
+ '<a[^>]*>|</a>|' \
29
+ "[^<\n]+"
30
+ Regexp.new(regex_string, Regexp::MULTILINE)
31
+ end
32
+
33
+ # Escaped characters.
34
+ # @private
35
+ ESCAPE_CHARS = {
36
+ '&' => '&amp;',
37
+ '>' => '&gt;',
38
+ '<' => '&lt;',
39
+ }.freeze
40
+
41
+ # @private
42
+ UNESCAPE_CHARS = ESCAPE_CHARS.invert.freeze
34
43
 
44
+ # Parse formatted string.
45
+ #
46
+ # @param string [String]
47
+ # @return [Array<Hash>] Text fragments.
35
48
  def self.format(string, *_args)
36
49
  tokens = string.gsub(%r{<br\s*/?>}, "\n").scan(PARSER_REGEX)
37
50
  array_from_tokens(tokens)
38
51
  end
39
52
 
53
+ # Serialize text fragments to an inline format string.
54
+ #
55
+ # @param array [Array<Hash>]
56
+ # @return [String]
40
57
  def self.to_string(array)
41
58
  prefixes = {
42
59
  bold: '<b>',
@@ -44,7 +61,7 @@ module Prawn
44
61
  underline: '<u>',
45
62
  strikethrough: '<strikethrough>',
46
63
  subscript: '<sub>',
47
- superscript: '<sup>'
64
+ superscript: '<sup>',
48
65
  }
49
66
  suffixes = {
50
67
  bold: '</b>',
@@ -52,53 +69,60 @@ module Prawn
52
69
  underline: '</u>',
53
70
  strikethrough: '</strikethrough>',
54
71
  subscript: '</sub>',
55
- superscript: '</sup>'
72
+ superscript: '</sup>',
56
73
  }
57
- array.collect do |hash|
58
- prefix = ''
59
- suffix = ''
60
- hash[:styles]&.each do |style|
61
- prefix += prefixes[style]
62
- suffix = suffixes[style] + suffix
63
- end
74
+ array
75
+ .map { |hash|
76
+ prefix = ''
77
+ suffix = ''
78
+ hash[:styles]&.each do |style|
79
+ prefix += prefixes[style]
80
+ suffix = suffixes[style] + suffix
81
+ end
64
82
 
65
- font = hash[:font] ? " name='#{hash[:font]}'" : nil
66
- size = hash[:size] ? " size='#{hash[:size]}'" : nil
67
- character_spacing =
68
- if hash[:character_spacing]
69
- " character_spacing='#{hash[:character_spacing]}'"
83
+ font = hash[:font] ? " name='#{hash[:font]}'" : nil
84
+ size = hash[:size] ? " size='#{hash[:size]}'" : nil
85
+ character_spacing =
86
+ if hash[:character_spacing]
87
+ " character_spacing='#{hash[:character_spacing]}'"
88
+ end
89
+ if font || size || character_spacing
90
+ prefix += "<font#{font}#{size}#{character_spacing}>"
91
+ suffix = '</font>'
70
92
  end
71
- if font || size || character_spacing
72
- prefix += "<font#{font}#{size}#{character_spacing}>"
73
- suffix = '</font>'
74
- end
75
93
 
76
- link = hash[:link] ? " href='#{hash[:link]}'" : nil
77
- anchor = hash[:anchor] ? " anchor='#{hash[:anchor]}'" : nil
78
- if link || anchor
79
- prefix += "<link#{link}#{anchor}>"
80
- suffix = '</link>'
81
- end
94
+ link = hash[:link] ? " href='#{hash[:link]}'" : nil
95
+ anchor = hash[:anchor] ? " anchor='#{hash[:anchor]}'" : nil
96
+ if link || anchor
97
+ prefix += "<link#{link}#{anchor}>"
98
+ suffix = '</link>'
99
+ end
82
100
 
83
- if hash[:color]
84
- prefix += if hash[:color].is_a?(Array)
85
- "<color c='#{hash[:color][0]}'" \
86
- " m='#{hash[:color][1]}'" \
87
- " y='#{hash[:color][2]}'" \
88
- " k='#{hash[:color][3]}'>"
89
- else
90
- "<color rgb='#{hash[:color]}'>"
91
- end
92
- suffix = '</color>'
93
- end
101
+ if hash[:color]
102
+ prefix +=
103
+ if hash[:color].is_a?(Array)
104
+ "<color c='#{hash[:color][0]}' " \
105
+ "m='#{hash[:color][1]}' " \
106
+ "y='#{hash[:color][2]}' " \
107
+ "k='#{hash[:color][3]}'>"
108
+ else
109
+ "<color rgb='#{hash[:color]}'>"
110
+ end
111
+ suffix = '</color>'
112
+ end
94
113
 
95
- string = hash[:text].gsub('&', '&amp;').gsub('>', '&gt;')
96
- .gsub('<', '&lt;')
97
- prefix + string + suffix
98
- end.join
114
+ string = escape(hash[:text])
115
+ prefix + string + suffix
116
+ }
117
+ .join
99
118
  end
100
119
 
101
- def self.array_paragraphs(array) #:nodoc:
120
+ # Break text into paragraphs.
121
+ #
122
+ # @private
123
+ # @param array [Array<Hash>] Text fragments.
124
+ # @return [Array<Array<Hash>>] Pragraphs of text fragments.
125
+ def self.array_paragraphs(array)
102
126
  paragraphs = []
103
127
  paragraph = []
104
128
  previous_string = "\n"
@@ -121,6 +145,9 @@ module Prawn
121
145
  paragraphs
122
146
  end
123
147
 
148
+ # @private
149
+ # @param tokens [Array<String>]
150
+ # @return [Array<Hash>]
124
151
  def self.array_from_tokens(tokens)
125
152
  array = []
126
153
  styles = []
@@ -187,16 +214,16 @@ module Prawn
187
214
 
188
215
  match = /c="#?([^"]*)"/.match(token) ||
189
216
  /c='#?([^']*)'/.match(token)
190
- c = match[1].to_i unless match.nil?
217
+ c = Integer(match[1], 10) unless match.nil?
191
218
  match = /m="#?([^"]*)"/.match(token) ||
192
219
  /m='#?([^']*)'/.match(token)
193
- m = match[1].to_i unless match.nil?
220
+ m = Integer(match[1], 10) unless match.nil?
194
221
  match = /y="#?([^"]*)"/.match(token) ||
195
222
  /y='#?([^']*)'/.match(token)
196
- y = match[1].to_i unless match.nil?
223
+ y = Integer(match[1], 10) unless match.nil?
197
224
  match = /k="#?([^"]*)"/.match(token) ||
198
225
  /k='#?([^']*)'/.match(token)
199
- k = match[1].to_i unless match.nil?
226
+ k = Integer(match[1], 10) unless match.nil?
200
227
  colors << [c, m, y, k] if [c, m, y, k].all?
201
228
 
202
229
  # intend to support rgb="#ffffff" or rgb='#ffffff',
@@ -213,14 +240,13 @@ module Prawn
213
240
 
214
241
  matches = /size="([^"]*)"/.match(token) ||
215
242
  /size='([^']*)'/.match(token)
216
- sizes << matches[1].to_f unless matches.nil?
243
+ sizes << Float(matches[1]) unless matches.nil?
217
244
 
218
245
  matches = /character_spacing="([^"]*)"/.match(token) ||
219
246
  /character_spacing='([^']*)'/.match(token)
220
- character_spacings << matches[1].to_f unless matches.nil?
247
+ character_spacings << Float(matches[1]) unless matches.nil?
221
248
  else
222
- string = token.gsub('&lt;', '<').gsub('&gt;', '>')
223
- .gsub('&amp;', '&')
249
+ string = unescape(token)
224
250
  array << {
225
251
  text: string,
226
252
  styles: styles.dup,
@@ -230,12 +256,28 @@ module Prawn
230
256
  anchor: anchor,
231
257
  font: fonts.last,
232
258
  size: sizes.last,
233
- character_spacing: character_spacings.last
259
+ character_spacing: character_spacings.last,
234
260
  }
235
261
  end
236
262
  end
237
263
  array
238
264
  end
265
+
266
+ # Escape characters that can interfere with inline format parsing.
267
+ #
268
+ # @param text [String]
269
+ # @return [String]
270
+ def self.escape(text)
271
+ text.gsub(Regexp.union(ESCAPE_CHARS.keys), ESCAPE_CHARS)
272
+ end
273
+
274
+ # Unescape characters that can interfere with inline format parsing.
275
+ #
276
+ # @param text [String]
277
+ # @return [String]
278
+ def self.unescape(text)
279
+ text.gsub(Regexp.union(UNESCAPE_CHARS.keys), UNESCAPE_CHARS)
280
+ end
239
281
  end
240
282
  end
241
283
  end
@@ -1,25 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # wrap.rb: Handles text wrapping for for formatted text
4
- #
5
- # Contributed by Daniel Nelson
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
-
9
3
  require_relative 'line_wrap'
10
4
  require_relative 'arranger'
11
5
 
12
6
  module Prawn
13
7
  module Text
14
- module Formatted #:nodoc:
8
+ module Formatted
9
+ # Handles text wrapping for for formatted text.
10
+ #
15
11
  # @private
16
-
17
- module Wrap #:nodoc:
12
+ module Wrap
18
13
  def initialize(_array, options)
19
14
  @line_wrap = Prawn::Text::Formatted::LineWrap.new
20
15
  @arranger = Prawn::Text::Formatted::Arranger.new(
21
16
  @document,
22
- kerning: options[:kerning]
17
+ kerning: options[:kerning],
23
18
  )
24
19
  @disable_wrap_by_char = options[:disable_wrap_by_char]
25
20
  end
@@ -44,7 +39,7 @@ module Prawn
44
39
  #
45
40
  # Returns any formatted text that was not printed
46
41
  #
47
- def wrap(array) #:nodoc:
42
+ def wrap(array)
48
43
  initialize_wrap(array)
49
44
 
50
45
  stop = false
@@ -57,7 +52,7 @@ module Prawn
57
52
  kerning: @kerning,
58
53
  width: available_width,
59
54
  arranger: @arranger,
60
- disable_wrap_by_char: @disable_wrap_by_char
55
+ disable_wrap_by_char: @disable_wrap_by_char,
61
56
  )
62
57
 
63
58
  if enough_height_for_this_line?
@@ -91,22 +86,24 @@ module Prawn
91
86
  printed_fragments << fragment.text
92
87
  fragments_this_line << fragment
93
88
  end
94
- @arranger.fragments.replace []
89
+ @arranger.fragments.replace([])
95
90
 
96
91
  accumulated_width = 0
97
92
  fragments_this_line.reverse! if @direction == :rtl
98
93
  fragments_this_line.each do |fragment_this_line|
99
94
  fragment_this_line.default_direction = @direction
100
95
  format_and_draw_fragment(
101
- fragment_this_line, accumulated_width,
102
- @line_wrap.width, word_spacing
96
+ fragment_this_line,
97
+ accumulated_width,
98
+ @line_wrap.width,
99
+ word_spacing,
103
100
  )
104
101
  accumulated_width += fragment_this_line.width
105
102
  end
106
103
 
107
- @printed_lines << printed_fragments.map do |s|
104
+ @printed_lines << printed_fragments.map { |s|
108
105
  s.dup.force_encoding(::Encoding::UTF_8)
109
- end.join
106
+ }.join
110
107
  end
111
108
 
112
109
  def word_spacing_for_this_line
@@ -122,11 +119,12 @@ module Prawn
122
119
  @line_height = @arranger.max_line_height
123
120
  @descender = @arranger.max_descender
124
121
  @ascender = @arranger.max_ascender
125
- diff = if @baseline_y.zero?
126
- @ascender + @descender
127
- else
128
- @descender + @line_height + @leading
129
- end
122
+ diff =
123
+ if @baseline_y.zero?
124
+ @ascender + @descender
125
+ else
126
+ @descender + @line_height + @leading
127
+ end
130
128
  require_relatived_total_height = @baseline_y.abs + diff
131
129
  if require_relatived_total_height > @height + 0.0001
132
130
  # no room for the full height of this line
@@ -152,12 +150,13 @@ module Prawn
152
150
  @everything_printed = false
153
151
  end
154
152
 
155
- def format_and_draw_fragment(fragment, accumulated_width,
156
- line_width, word_spacing)
153
+ def format_and_draw_fragment(fragment, accumulated_width, line_width, word_spacing)
157
154
  @arranger.apply_color_and_font_settings(fragment) do
158
155
  draw_fragment(
159
- fragment, accumulated_width,
160
- line_width, word_spacing
156
+ fragment,
157
+ accumulated_width,
158
+ line_width,
159
+ word_spacing,
161
160
  )
162
161
  end
163
162
  end
@@ -2,6 +2,81 @@
2
2
 
3
3
  require_relative 'formatted/wrap'
4
4
 
5
+ module Prawn
6
+ module Text
7
+ # Fancy pretty text.
8
+ module Formatted
9
+ # @group Stable API
10
+
11
+ # Draws the requested formatted text into a box.
12
+ #
13
+ # When the text overflows the rectangle shrink to fit or truncate the
14
+ # text. Text boxes are independent of the document y position.
15
+ #
16
+ # @example
17
+ # formatted_text_box([{ :text => "hello" },
18
+ # { :text => "world",
19
+ # :size => 24,
20
+ # :styles => [:bold, :italic] }])
21
+ #
22
+ # @param array [Array<Hash{Symbol => any}>]
23
+ # Formatted text is an array of hashes, where each hash defines text and
24
+ # format information. The following hash options are supported:
25
+ #
26
+ # - `:text` --- the text to format according to the other hash options.
27
+ # - `:styles` --- an array of styles to apply to this text. Available
28
+ # styles include `:bold`, `:italic`, `:underline`, `:strikethrough`,
29
+ # `:subscript`, and `:superscript`.
30
+ # - `:size` ---a number denoting the font size to apply to this text.
31
+ # - `:character_spacing` --- a number denoting how much to increase or
32
+ # decrease the default spacing between characters.
33
+ # - `:font` --- the name of a font. The name must be an AFM font with
34
+ # the desired faces or must be a font that is already registered using
35
+ # {Prawn::Document#font_families}.
36
+ # - `:color` --- anything compatible with
37
+ # {Prawn::Graphics::Color#fill_color} and
38
+ # {Prawn::Graphics::Color#stroke_color}.
39
+ # - :link` --- a URL to which to create a link. A clickable link will be
40
+ # created to that URL. Note that you must explicitly underline and
41
+ # color using the appropriate tags if you which to draw attention to
42
+ # the link.
43
+ # - `:anchor` --- a destination that has already been or will be
44
+ # registered using
45
+ # `PDF::Core::Destinations#add_dest`{:.language-plain}. A clickable
46
+ # link will be created to that destination. Note that you must
47
+ # explicitly underline and color using the appropriate tags if you
48
+ # which to draw attention to the link.
49
+ # - `:local` --- a file or application to be opened locally. A clickable
50
+ # link will be created to the provided local file or application. If
51
+ # the file is another PDF, it will be opened in a new window. Note
52
+ # that you must explicitly underline and color using the appropriate
53
+ # options if you which to draw attention to the link.
54
+ # - `:draw_text_callback` --- if provided, this Proc will be called
55
+ # instead of {#draw_text!} once per fragment for every low-level
56
+ # addition of text to the page.
57
+ # - `:callback` --- an object (or array of such objects) with two
58
+ # methods: `#render_behind`{:.language-plain} and
59
+ # `#render_in_front`{:.language-plain}, which are called immediately
60
+ # prior to and immediately after rendering the text fragment and which
61
+ # are passed the fragment as an argument.
62
+ # @param options [Hash{Symbol => any}]
63
+ # Accepts the same options as {Text::Box}.
64
+ #
65
+ # @return [Array<Hash>]
66
+ # A formatted text array representing any text that did not print under
67
+ # the current settings.
68
+ #
69
+ # @raise [Prawn::Text::Formatted::Arranger::BadFontFamily]
70
+ # If no font family is defined for the current font.
71
+ # @raise [Prawn::Errors::CannotFit]
72
+ # If not wide enough to print any text.
73
+ def formatted_text_box(array, options = {})
74
+ Text::Formatted::Box.new(array, options.merge(document: self)).render
75
+ end
76
+ end
77
+ end
78
+ end
79
+
5
80
  require_relative 'formatted/box'
6
81
  require_relative 'formatted/parser'
7
82
  require_relative 'formatted/fragment'