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,140 +1,191 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # text/rectangle.rb : Implements text boxes
4
- #
5
- # Copyright November 2009, Daniel Nelson. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
- #
9
-
10
3
  require_relative 'formatted/box'
11
4
 
12
5
  module Prawn
13
- module Text
6
+ module Text # rubocop: disable Style/Documentation
14
7
  # @group Stable API
15
8
 
16
- # Draws the requested text into a box. When the text overflows
17
- # the rectangle, you shrink to fit, or truncate the text. Text
18
- # boxes are independent of the document y position.
9
+ # Draws the requested text into a box.
10
+ #
11
+ # When the text overflows the rectangle, you shrink to fit, or truncate the
12
+ # text. Text boxes are independent of the document y position.
19
13
  #
20
- # == Encoding
14
+ # #### Encoding
21
15
  #
22
- # Note that strings passed to this function should be encoded as UTF-8.
23
- # If you get unexpected characters appearing in your rendered document,
24
- # check this.
16
+ # Note that strings passed to this function should be encoded as UTF-8. If
17
+ # you get unexpected characters appearing in your rendered document, check
18
+ # this.
25
19
  #
26
- # If the current font is a built-in one, although the string must be
27
- # encoded as UTF-8, only characters that are available in WinAnsi
28
- # are allowed.
20
+ # If the current font is a built-in one, although the string must be encoded
21
+ # as UTF-8, only characters that are available in WinAnsi are allowed.
29
22
  #
30
23
  # If an empty box is rendered to your PDF instead of the character you
31
24
  # wanted it usually means the current font doesn't include that character.
32
25
  #
33
- # == Options (default values marked in [])
34
- #
35
- # <tt>:kerning</tt>:: <tt>boolean</tt>. Whether or not to use kerning (if it
36
- # is available with the current font)
37
- # [value of document.default_kerning?]
38
- # <tt>:size</tt>:: <tt>number</tt>. The font size to use. [current font
39
- # size]
40
- # <tt>:character_spacing</tt>:: <tt>number</tt>. The amount of space to add
41
- # to or remove from the default character
42
- # spacing. [0]
43
- # <tt>:disable_wrap_by_char</tt>:: <tt>boolean</tt> Whether
44
- # or not to prevent mid-word breaks when text does not fit in box. [false]
45
- # <tt>:mode</tt>:: <tt>symbol</tt>. The text rendering mode. See
46
- # documentation for Prawn::Document#text_rendering_mode
47
- # for a list of valid options. [:fill]
48
- # <tt>:style</tt>:: The style to use. The requested style must be part of
49
- # the current font familly. [current style]
50
- #
51
- # <tt>:at</tt>::
52
- # <tt>[x, y]</tt>. The upper left corner of the box
53
- # [@document.bounds.left, @document.bounds.top]
54
- # <tt>:width</tt>::
55
- # <tt>number</tt>. The width of the box
56
- # [@document.bounds.right - @at[0]]
57
- # <tt>:height</tt>::
58
- # <tt>number</tt>. The height of the box [default_height()]
59
- # <tt>:direction</tt>::
60
- # <tt>:ltr</tt>, <tt>:rtl</tt>, Direction of the text (left-to-right
61
- # or right-to-left) [value of document.text_direction]
62
- # <tt>:fallback_fonts</tt>::
63
- # An array of font names. Each name must be the name of an AFM font or
64
- # the name that was used to register a family of external fonts (see
65
- # Prawn::Document#font_families). If present, then each glyph will be
66
- # rendered using the first font that includes the glyph, starting with
67
- # the current font and then moving through :fallback_fonts from
68
- # left to right.
69
- # <tt>:align</tt>::
70
- # <tt>:left</tt>, <tt>:center</tt>, <tt>:right</tt>, or
71
- # <tt>:justify</tt> Alignment within the bounding box
72
- # [:left if direction is :ltr, :right if direction is :rtl]
73
- # <tt>:valign</tt>::
74
- # <tt>:top</tt>, <tt>:center</tt>, or <tt>:bottom</tt>. Vertical
75
- # alignment within the bounding box [:top]
76
- # <tt>:rotate</tt>::
77
- # <tt>number</tt>. The angle to rotate the text
78
- # <tt>:rotate_around</tt>::
79
- # <tt>:center</tt>, <tt>:upper_left</tt>, <tt>:upper_right</tt>,
80
- # <tt>:lower_right</tt>, or <tt>:lower_left</tt>. The point around which
81
- # to rotate the text [:upper_left]
82
- # <tt>:leading</tt>::
83
- # <tt>number</tt>. Additional space between lines [value of
84
- # document.default_leading]
85
- # <tt>:single_line</tt>::
86
- # <tt>boolean</tt>. If true, then only the first line will be drawn
87
- # [false]
88
- # <tt>:overflow</tt>::
89
- # <tt>:truncate</tt>, <tt>:shrink_to_fit</tt>, or <tt>:expand</tt>
90
- # This controls the behavior when the amount of text
91
- # exceeds the available space. [:truncate]
92
- # <tt>:min_font_size</tt>::
93
- # <tt>number</tt>. The minimum font size to use when :overflow is set to
94
- # :shrink_to_fit (that is the font size will not be reduced to less than
95
- # this value, even if it means that some text will be cut off). [5]
96
- #
97
- # == Returns
98
- #
99
- # Returns any text that did not print under the current settings.
100
- #
101
- # == Exceptions
102
- #
103
- # Raises <tt>Prawn::Errors::CannotFit</tt> if not wide enough to print
104
- # any text
105
- #
26
+ # @param string [String]
27
+ # @param options [Hash{Symbol => any}]
28
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
29
+ # Whether or not to use kerning (if it is available with the current
30
+ # font).
31
+ # @option options :size [Number] (current font size)
32
+ # The font size to use.
33
+ # @option options :character_spacing [Number] (0)
34
+ # The amount of space to add to or remove from the default character
35
+ # spacing.
36
+ # @option options :disable_wrap_by_char [Boolean] (false)
37
+ # Whether or not to prevent mid-word breaks when text does not fit in box.
38
+ # @option options :mode [Symbol] (:fill)
39
+ # The text rendering mode. See documentation for
40
+ # {Prawn::Document#text_rendering_mode} for a list of valid options.
41
+ # @option option :style [Symbol] (current style)
42
+ # The style to use. The requested style must be part of the current font
43
+ # family.
44
+ # @option option :at [Array(Number, Number)] (bounds top left corner)
45
+ # The upper left corner of the box.
46
+ # @option options :width [Number] (bounds.right - at[0])
47
+ # The width of the box.
48
+ # @option options :height [Number] (default_height())
49
+ # The height of the box.
50
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
51
+ # Direction of the text (left-to-right or right-to-left).
52
+ # @option options :fallback_fonts [Array<String>]
53
+ # An array of font names. Each name must be the name of an AFM font or the
54
+ # name that was used to register a family of external fonts (see
55
+ # {Prawn::Document#font_families}). If present, then each glyph will be
56
+ # rendered using the first font that includes the glyph, starting with the
57
+ # current font and then moving through `:fallback_fonts`.
58
+ # @option options :align [:left, :center, :right, :justify]
59
+ # (:left if direction is :ltr, :right if direction is :rtl)
60
+ # Alignment within the bounding box.
61
+ # @option options :valign [:top, :center, :bottom] (:top)
62
+ # Vertical alignment within the bounding box.
63
+ # @option options :rotate [Number]
64
+ # The angle to rotate the text.
65
+ # @option options :rotate_around
66
+ # [:center, :upper_left, :upper_right, :lower_right, :lower_left]
67
+ # (:upper_left)
68
+ # The point around which to rotate the text.
69
+ # @option options :leading [Number] (value of document.default_leading)
70
+ # Additional space between lines.
71
+ # @option options :single_line [Boolean] (false)
72
+ # If true, then only the first line will be drawn.
73
+ # @option options :overflow [:truncate, :shrink_to_fit, :expand] (:truncate)
74
+ # This controls the behavior when the amount of text exceeds the available
75
+ # space.
76
+ # @option options :min_font_size [Number] (5)
77
+ # The minimum font size to use when `:overflow` is set to `:shrink_to_fit`
78
+ # (that is the font size will not be reduced to less than this value, even
79
+ # if it means that some text will be cut off).
80
+ # @return [String] Any text that did not print under the current settings.
81
+ # @raise [Prawn::Errors::CannotFit]
82
+ # If not wide enough to print any text.
106
83
  def text_box(string, options = {})
107
84
  options = options.dup
108
85
  options[:document] = self
109
86
 
110
- box = if options[:inline_format]
111
- p = options.delete(:inline_format)
112
- p = [] unless p.is_a?(Array)
113
- array = text_formatter.format(string, *p)
114
- Text::Formatted::Box.new(array, options)
115
- else
116
- Text::Box.new(string, options)
117
- end
87
+ box =
88
+ if options[:inline_format]
89
+ p = options.delete(:inline_format)
90
+ p = [] unless p.is_a?(Array)
91
+ array = text_formatter.format(string, *p)
92
+ Text::Formatted::Box.new(array, options)
93
+ else
94
+ Text::Box.new(string, options)
95
+ end
118
96
 
119
97
  box.render
120
98
  end
121
99
 
122
100
  # @group Experimental API
123
101
 
124
- # Generally, one would use the Prawn::Text#text_box convenience
125
- # method. However, using Text::Box.new in conjunction with
126
- # #render(:dry_run=> true) enables one to do look-ahead calculations prior
127
- # to placing text on the page, or to determine how much vertical space was
128
- # consumed by the printed text
102
+ # Text box.
129
103
  #
104
+ # Generally, one would use the {Prawn::Text#text_box} convenience method.
105
+ # However, using {Prawn::Text::Box#initialize Box.new} in conjunction with
106
+ # `render(dry_run: true)` enables one to do calculations prior to placing
107
+ # text on the page, or to determine how much vertical space was consumed by
108
+ # the printed text.
130
109
  class Box < Prawn::Text::Formatted::Box
110
+ # @param string [String]
111
+ # @param options [Hash{Symbol => any}]
112
+ # @option options :document [Prawn::Document] Owning document.
113
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
114
+ # Whether or not to use kerning (if it is available with the current
115
+ # font).
116
+ # @option options :size [Number] (current font size)
117
+ # The font size to use.
118
+ # @option options :character_spacing [Number] (0)
119
+ # The amount of space to add to or remove from the default character
120
+ # spacing.
121
+ # @option options :disable_wrap_by_char [Boolean] (false)
122
+ # Whether or not to prevent mid-word breaks when text does not fit in box.
123
+ # @option options :mode [Symbol] (:fill)
124
+ # The text rendering mode. See documentation for
125
+ # {Prawn::Document#text_rendering_mode} for a list of valid options.
126
+ # @option option :style [Symbol] (current style)
127
+ # The style to use. The requested style must be part of the current font
128
+ # family.
129
+ # @option option :at [Array(Number, Number)] (bounds top left corner)
130
+ # The upper left corner of the box.
131
+ # @option options :width [Number] (bounds.right - at[0])
132
+ # The width of the box.
133
+ # @option options :height [Number] (default_height())
134
+ # The height of the box.
135
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
136
+ # Direction of the text (left-to-right or right-to-left).
137
+ # @option options :fallback_fonts [Array<String>]
138
+ # An array of font names. Each name must be the name of an AFM font or the
139
+ # name that was used to register a family of external fonts (see
140
+ # {Prawn::Document#font_families}). If present, then each glyph will be
141
+ # rendered using the first font that includes the glyph, starting with the
142
+ # current font and then moving through `:fallback_fonts`.
143
+ # @option options :align [:left, :center, :right, :justify]
144
+ # (:left if direction is :ltr, :right if direction is :rtl)
145
+ # Alignment within the bounding box.
146
+ # @option options :valign [:top, :center, :bottom] (:top)
147
+ # Vertical alignment within the bounding box.
148
+ # @option options :rotate [Number]
149
+ # The angle to rotate the text.
150
+ # @option options :rotate_around
151
+ # [:center, :upper_left, :upper_right, :lower_right, :lower_left]
152
+ # (:upper_left)
153
+ # The point around which to rotate the text.
154
+ # @option options :leading [Number] (value of document.default_leading)
155
+ # Additional space between lines.
156
+ # @option options :single_line [Boolean] (false)
157
+ # If true, then only the first line will be drawn.
158
+ # @option options :overflow [:truncate, :shrink_to_fit, :expand] (:truncate)
159
+ # This controls the behavior when the amount of text exceeds the available
160
+ # space.
161
+ # @option options :min_font_size [Number] (5)
162
+ # The minimum font size to use when `:overflow` is set to `:shrink_to_fit`
163
+ # (that is the font size will not be reduced to less than this value, even
164
+ # if it means that some text will be cut off).
131
165
  def initialize(string, options = {})
132
166
  super([{ text: string }], options)
133
167
  end
134
168
 
169
+ # Render text to the document based on the settings defined in
170
+ # constructor.
171
+ #
172
+ # In order to facilitate look-ahead calculations, this method accepts
173
+ # a `dry_run: true` option. If provided, then everything is executed as if
174
+ # rendering, with the exception that nothing is drawn on the page. Useful
175
+ # for look-ahead computations of height, unprinted text, etc.
176
+ #
177
+ # @param flags [Hash{Symbol => any}]
178
+ # @option flags :dry_run [Boolean] (false)
179
+ # Do not draw the text. Everything else is done.
180
+ # @return [String]
181
+ # Any text that did not print under the current settings.
182
+ # @raise [Prawn::Text::Formatted::Arranger::BadFontFamily]
183
+ # If no font family is defined for the current font.
184
+ # @raise [Prawn::Errors::CannotFit]
185
+ # If not wide enough to print any text.
135
186
  def render(flags = {})
136
187
  leftover = super(flags)
137
- leftover.collect { |hash| hash[:text] }.join
188
+ leftover.map { |hash| hash[:text] }.join
138
189
  end
139
190
  end
140
191
  end
@@ -1,18 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # core/text/formatted/arranger.rb : Implements a data structure for 2-stage
4
- # processing of lines of formatted text
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
3
  module Prawn
11
4
  module Text
12
- module Formatted #:nodoc:
5
+ module Formatted
6
+ # D data structure for 2-stage processing of lines of formatted text.
13
7
  # @private
8
+ class Arranger
9
+ # You're getting this because you're trying to get some information from
10
+ # the arranger before it finished processing text.
11
+ class NotFinalized < StandardError
12
+ # @private
13
+ DEFAULT_MESSAGE = 'Lines must be finalized'
14
+
15
+ # @private
16
+ MESSAGE_WITH_METHOD = 'Lines must be finalized before calling #%<method>s'
17
+
18
+ def initialize(message = DEFAULT_MESSAGE, method: nil)
19
+ if method && message == DEFAULT_MESSAGE
20
+ super(format(MESSAGE_WITH_METHOD, method: method))
21
+ else
22
+ super(message)
23
+ end
24
+ end
25
+ end
26
+
27
+ # You're getting this because a font doesn't have a family name.
28
+ class BadFontFamily < StandardError
29
+ def initialize(message = 'Bad font family')
30
+ super
31
+ end
32
+ end
14
33
 
15
- class Arranger #:nodoc:
16
34
  attr_reader :max_line_height
17
35
  attr_reader :max_descender
18
36
  attr_reader :max_ascender
@@ -31,39 +49,55 @@ module Prawn
31
49
  @kerning = options[:kerning]
32
50
  end
33
51
 
52
+ # Number of spaces in the text.
53
+ #
54
+ # @return [Integer]
55
+ # @raise [NotFinalized]
34
56
  def space_count
35
57
  unless finalized
36
- raise 'Lines must be finalized before calling #space_count'
58
+ raise NotFinalized.new(method: 'space_count')
37
59
  end
38
60
 
39
- @fragments.inject(0) do |sum, fragment|
61
+ @fragments.reduce(0) do |sum, fragment|
40
62
  sum + fragment.space_count
41
63
  end
42
64
  end
43
65
 
66
+ # Line width.
67
+ #
68
+ # @return [Number]
69
+ # @raise [NotFinalized]
44
70
  def line_width
45
71
  unless finalized
46
- raise 'Lines must be finalized before calling #line_width'
72
+ raise raise NotFinalized.new(method: 'line_width')
47
73
  end
48
74
 
49
- @fragments.inject(0) do |sum, fragment|
75
+ @fragments.reduce(0) do |sum, fragment|
50
76
  sum + fragment.width
51
77
  end
52
78
  end
53
79
 
80
+ # Line text.
81
+ #
82
+ # @return [String]
83
+ # @raise [NotFinalized]
54
84
  def line
55
85
  unless finalized
56
- raise 'Lines must be finalized before calling #line'
86
+ raise NotFinalized.new(method: 'line')
57
87
  end
58
88
 
59
- @fragments.collect do |fragment|
60
- fragment.text.dup.encode(::Encoding::UTF_8)
61
- rescue ::Encoding::InvalidByteSequenceError,
62
- ::Encoding::UndefinedConversionError
63
- fragment.text.dup.force_encoding(::Encoding::UTF_8)
64
- end.join
89
+ @fragments.map { |fragment|
90
+ begin
91
+ fragment.text.dup.encode(::Encoding::UTF_8)
92
+ rescue ::Encoding::InvalidByteSequenceError, ::Encoding::UndefinedConversionError
93
+ fragment.text.dup.force_encoding(::Encoding::UTF_8)
94
+ end
95
+ }.join
65
96
  end
66
97
 
98
+ # Finish laying out current line.
99
+ #
100
+ # @return [void]
67
101
  def finalize_line
68
102
  @finalized = true
69
103
 
@@ -76,7 +110,7 @@ module Prawn
76
110
  fragment = Prawn::Text::Formatted::Fragment.new(
77
111
  text,
78
112
  format_state,
79
- @document
113
+ @document,
80
114
  )
81
115
  @fragments << fragment
82
116
  self.fragment_measurements = fragment
@@ -84,6 +118,10 @@ module Prawn
84
118
  end
85
119
  end
86
120
 
121
+ # Set new fragment array.
122
+ #
123
+ # @param array [Array<Hash>]
124
+ # @return [void]
87
125
  def format_array=(array)
88
126
  initialize_line
89
127
  @unconsumed = []
@@ -94,6 +132,9 @@ module Prawn
94
132
  end
95
133
  end
96
134
 
135
+ # Prepare for new line layout.
136
+ #
137
+ # @return [void]
97
138
  def initialize_line
98
139
  @finalized = false
99
140
  @max_line_height = 0
@@ -104,13 +145,20 @@ module Prawn
104
145
  @fragments = []
105
146
  end
106
147
 
148
+ # Were all fragments processed?
149
+ #
150
+ # @return [Boolean]
107
151
  def finished?
108
152
  @unconsumed.empty?
109
153
  end
110
154
 
155
+ # Get the next unprocessed string.
156
+ #
157
+ # @return [String, nil]
158
+ # @raise [NotFinalized]
111
159
  def next_string
112
160
  if finalized
113
- raise 'Lines must not be finalized when calling #next_string'
161
+ raise NotFinalized.new(method: 'next_string')
114
162
  end
115
163
 
116
164
  next_unconsumed_hash = @unconsumed.shift
@@ -124,6 +172,9 @@ module Prawn
124
172
  end
125
173
  end
126
174
 
175
+ # Get the next unprocessed string keeping it in the queue.
176
+ #
177
+ # @return [String, nil]
127
178
  def preview_next_string
128
179
  next_unconsumed_hash = @unconsumed.first
129
180
 
@@ -132,6 +183,11 @@ module Prawn
132
183
  end
133
184
  end
134
185
 
186
+ # Apply color and font settings.
187
+ #
188
+ # @param fragment [Prawn::Text::Formatted::Fragment]
189
+ # @yield
190
+ # @return [void]
135
191
  def apply_color_and_font_settings(fragment, &block)
136
192
  if fragment.color
137
193
  original_fill_color = @document.fill_color
@@ -146,6 +202,11 @@ module Prawn
146
202
  end
147
203
  end
148
204
 
205
+ # Apply font settings.
206
+ #
207
+ # @param fragment [Prawn::Text::Formatted::Fragment]
208
+ # @yield
209
+ # @return [void]
149
210
  def apply_font_settings(fragment = nil, &block)
150
211
  if fragment.nil?
151
212
  font = current_format_state[:font]
@@ -163,10 +224,10 @@ module Prawn
163
224
 
164
225
  @document.character_spacing(character_spacing) do
165
226
  if font || font_style != :normal
166
- raise 'Bad font family' unless @document.font.family
227
+ raise BadFontFamily unless @document.font.family
167
228
 
168
229
  @document.font(
169
- font || @document.font.family, style: font_style
230
+ font || @document.font.family, style: font_style,
170
231
  ) do
171
232
  apply_font_size(size, styles, &block)
172
233
  end
@@ -176,6 +237,12 @@ module Prawn
176
237
  end
177
238
  end
178
239
 
240
+ # Update last fragment's text.
241
+ #
242
+ # @param printed [String]
243
+ # @param unprinted [String]
244
+ # @param normalized_soft_hyphen [Boolean]
245
+ # @return [void]
179
246
  def update_last_string(printed, unprinted, normalized_soft_hyphen = nil)
180
247
  return if printed.nil?
181
248
 
@@ -195,14 +262,21 @@ module Prawn
195
262
  load_previous_format_state if printed.empty?
196
263
  end
197
264
 
265
+ # Get the next fragment.
266
+ #
267
+ # @return [Prawn::Text::Formatted::Fragment]
268
+ # @raise [NotFinalized]
198
269
  def retrieve_fragment
199
270
  unless finalized
200
- raise 'Lines must be finalized before fragments can be retrieved'
271
+ raise NotFinalized, 'Lines must be finalized before fragments can be retrieved'
201
272
  end
202
273
 
203
274
  @fragments.shift
204
275
  end
205
276
 
277
+ # Repack remaining fragments.
278
+ #
279
+ # @return [void]
206
280
  def repack_unretrieved
207
281
  new_unconsumed = []
208
282
  # rubocop: disable Lint/AssignmentInCondition
@@ -214,10 +288,13 @@ module Prawn
214
288
  @unconsumed = new_unconsumed.concat(@unconsumed)
215
289
  end
216
290
 
291
+ # Get font variant from fragment styles.
292
+ #
293
+ # @param styles [Array<Symbol>]
294
+ # @return [Symbol]
217
295
  def font_style(styles)
218
- if styles.nil?
219
- :normal
220
- elsif styles.include?(:bold) && styles.include?(:italic)
296
+ styles = Array(styles)
297
+ if styles.include?(:bold) && styles.include?(:italic)
221
298
  :bold_italic
222
299
  elsif styles.include?(:bold)
223
300
  :bold
@@ -240,31 +317,34 @@ module Prawn
240
317
  end
241
318
  end
242
319
 
243
- def apply_font_size(size, styles)
320
+ def apply_font_size(size, styles, &block)
244
321
  if subscript?(styles) || superscript?(styles)
245
322
  relative_size = 0.583
246
- size = if size.nil?
247
- @document.font_size * relative_size
248
- else
249
- size * relative_size
250
- end
323
+ size =
324
+ if size.nil?
325
+ @document.font_size * relative_size
326
+ else
327
+ size * relative_size
328
+ end
251
329
  end
252
330
  if size.nil?
253
331
  yield
254
332
  else
255
- @document.font_size(size) { yield }
333
+ @document.font_size(size, &block)
256
334
  end
257
335
  end
258
336
 
259
337
  def subscript?(styles)
260
338
  if styles.nil? then false
261
- else styles.include?(:subscript)
339
+ else
340
+ styles.include?(:subscript)
262
341
  end
263
342
  end
264
343
 
265
344
  def superscript?(styles)
266
345
  if styles.nil? then false
267
- else styles.include?(:superscript)
346
+ else
347
+ styles.include?(:superscript)
268
348
  end
269
349
  end
270
350
 
@@ -288,7 +368,7 @@ module Prawn
288
368
  apply_font_settings(fragment) do
289
369
  fragment.width = @document.width_of(
290
370
  fragment.text,
291
- kerning: @kerning
371
+ kerning: @kerning,
292
372
  )
293
373
  fragment.line_height = @document.font.height
294
374
  fragment.descender = @document.font.descender
@@ -299,15 +379,15 @@ module Prawn
299
379
  def line_measurement_maximums=(fragment)
300
380
  @max_line_height = [
301
381
  defined?(@max_line_height) && @max_line_height,
302
- fragment.line_height
382
+ fragment.line_height,
303
383
  ].compact.max
304
384
  @max_descender = [
305
385
  defined?(@max_descender) && @max_descender,
306
- fragment.descender
386
+ fragment.descender,
307
387
  ].compact.max
308
388
  @max_ascender = [
309
389
  defined?(@max_ascender) && @max_ascender,
310
- fragment.ascender
390
+ fragment.ascender,
311
391
  ].compact.max
312
392
  end
313
393
  end