prawn 2.1.0 → 2.4.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 (280) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -9
  6. data/Rakefile +9 -41
  7. data/lib/prawn.rb +37 -49
  8. data/lib/prawn/document.rb +193 -141
  9. data/lib/prawn/document/bounding_box.rb +50 -30
  10. data/lib/prawn/document/column_box.rb +7 -7
  11. data/lib/prawn/document/internals.rb +8 -6
  12. data/lib/prawn/document/span.rb +22 -16
  13. data/lib/prawn/encoding.rb +69 -68
  14. data/lib/prawn/errors.rb +12 -7
  15. data/lib/prawn/font.rb +104 -69
  16. data/lib/prawn/font_metric_cache.rb +20 -13
  17. data/lib/prawn/{font → fonts}/afm.rb +108 -72
  18. data/lib/prawn/{font → fonts}/dfont.rb +5 -11
  19. data/lib/prawn/fonts/otf.rb +11 -0
  20. data/lib/prawn/fonts/ttc.rb +36 -0
  21. data/lib/prawn/{font → fonts}/ttf.rb +126 -81
  22. data/lib/prawn/graphics.rb +119 -81
  23. data/lib/prawn/graphics/blend_mode.rb +9 -8
  24. data/lib/prawn/graphics/cap_style.rb +3 -3
  25. data/lib/prawn/graphics/color.rb +43 -39
  26. data/lib/prawn/graphics/dash.rb +23 -11
  27. data/lib/prawn/graphics/join_style.rb +9 -3
  28. data/lib/prawn/graphics/patterns.rb +204 -102
  29. data/lib/prawn/graphics/transformation.rb +15 -9
  30. data/lib/prawn/graphics/transparency.rb +17 -13
  31. data/lib/prawn/grid.rb +84 -48
  32. data/lib/prawn/image_handler.rb +5 -5
  33. data/lib/prawn/images.rb +60 -49
  34. data/lib/prawn/images/image.rb +2 -1
  35. data/lib/prawn/images/jpg.rb +31 -22
  36. data/lib/prawn/images/png.rb +67 -63
  37. data/lib/prawn/measurement_extensions.rb +10 -9
  38. data/lib/prawn/measurements.rb +19 -15
  39. data/lib/prawn/outline.rb +98 -77
  40. data/lib/prawn/repeater.rb +15 -11
  41. data/lib/prawn/security.rb +93 -70
  42. data/lib/prawn/security/arcfour.rb +2 -2
  43. data/lib/prawn/soft_mask.rb +26 -26
  44. data/lib/prawn/stamp.rb +20 -13
  45. data/lib/prawn/text.rb +76 -60
  46. data/lib/prawn/text/box.rb +18 -14
  47. data/lib/prawn/text/formatted.rb +5 -5
  48. data/lib/prawn/text/formatted/arranger.rb +80 -40
  49. data/lib/prawn/text/formatted/box.rb +140 -101
  50. data/lib/prawn/text/formatted/fragment.rb +11 -14
  51. data/lib/prawn/text/formatted/line_wrap.rb +128 -67
  52. data/lib/prawn/text/formatted/parser.rb +147 -123
  53. data/lib/prawn/text/formatted/wrap.rb +48 -32
  54. data/lib/prawn/transformation_stack.rb +7 -5
  55. data/lib/prawn/utilities.rb +7 -22
  56. data/lib/prawn/version.rb +2 -2
  57. data/lib/prawn/view.rb +17 -7
  58. data/manual/basic_concepts/adding_pages.rb +6 -7
  59. data/manual/basic_concepts/basic_concepts.rb +31 -22
  60. data/manual/basic_concepts/creation.rb +10 -11
  61. data/manual/basic_concepts/cursor.rb +4 -5
  62. data/manual/basic_concepts/measurement.rb +7 -8
  63. data/manual/basic_concepts/origin.rb +5 -6
  64. data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
  65. data/manual/basic_concepts/view.rb +22 -16
  66. data/manual/bounding_box/bounding_box.rb +29 -24
  67. data/manual/bounding_box/bounds.rb +11 -12
  68. data/manual/bounding_box/canvas.rb +7 -8
  69. data/manual/bounding_box/creation.rb +6 -7
  70. data/manual/bounding_box/indentation.rb +14 -15
  71. data/manual/bounding_box/nesting.rb +25 -18
  72. data/manual/bounding_box/russian_boxes.rb +14 -13
  73. data/manual/bounding_box/stretchy.rb +12 -13
  74. data/manual/contents.rb +28 -22
  75. data/manual/cover.rb +33 -28
  76. data/manual/document_and_page_options/background.rb +15 -13
  77. data/manual/document_and_page_options/document_and_page_options.rb +25 -20
  78. data/manual/document_and_page_options/metadata.rb +18 -16
  79. data/manual/document_and_page_options/page_margins.rb +18 -20
  80. data/manual/document_and_page_options/page_size.rb +13 -12
  81. data/manual/document_and_page_options/print_scaling.rb +18 -15
  82. data/manual/example_helper.rb +5 -4
  83. data/manual/graphics/blend_mode.rb +12 -9
  84. data/manual/graphics/circle_and_ellipse.rb +4 -5
  85. data/manual/graphics/color.rb +7 -9
  86. data/manual/graphics/common_lines.rb +7 -8
  87. data/manual/graphics/fill_and_stroke.rb +5 -6
  88. data/manual/graphics/fill_rules.rb +10 -10
  89. data/manual/graphics/gradients.rb +27 -21
  90. data/manual/graphics/graphics.rb +48 -40
  91. data/manual/graphics/helper.rb +19 -9
  92. data/manual/graphics/line_width.rb +8 -7
  93. data/manual/graphics/lines_and_curves.rb +7 -8
  94. data/manual/graphics/polygon.rb +6 -8
  95. data/manual/graphics/rectangle.rb +4 -5
  96. data/manual/graphics/rotate.rb +6 -7
  97. data/manual/graphics/scale.rb +14 -15
  98. data/manual/graphics/soft_masks.rb +3 -4
  99. data/manual/graphics/stroke_cap.rb +6 -7
  100. data/manual/graphics/stroke_dash.rb +15 -16
  101. data/manual/graphics/stroke_join.rb +5 -6
  102. data/manual/graphics/translate.rb +10 -10
  103. data/manual/graphics/transparency.rb +7 -8
  104. data/manual/how_to_read_this_manual.rb +6 -6
  105. data/manual/images/absolute_position.rb +6 -7
  106. data/manual/images/fit.rb +7 -8
  107. data/manual/images/horizontal.rb +10 -11
  108. data/manual/images/images.rb +28 -24
  109. data/manual/images/plain_image.rb +5 -6
  110. data/manual/images/scale.rb +9 -10
  111. data/manual/images/vertical.rb +16 -14
  112. data/manual/images/width_and_height.rb +10 -11
  113. data/manual/layout/boxes.rb +5 -6
  114. data/manual/layout/content.rb +7 -8
  115. data/manual/layout/layout.rb +18 -16
  116. data/manual/layout/simple_grid.rb +6 -7
  117. data/manual/outline/add_subsection_to.rb +20 -21
  118. data/manual/outline/insert_section_after.rb +15 -16
  119. data/manual/outline/outline.rb +21 -17
  120. data/manual/outline/sections_and_pages.rb +17 -18
  121. data/manual/repeatable_content/alternate_page_numbering.rb +21 -17
  122. data/manual/repeatable_content/page_numbering.rb +17 -16
  123. data/manual/repeatable_content/repeatable_content.rb +25 -19
  124. data/manual/repeatable_content/repeater.rb +14 -15
  125. data/manual/repeatable_content/stamp.rb +14 -15
  126. data/manual/security/encryption.rb +9 -10
  127. data/manual/security/permissions.rb +21 -14
  128. data/manual/security/security.rb +19 -16
  129. data/manual/table.rb +3 -3
  130. data/manual/text/alignment.rb +16 -17
  131. data/manual/text/color.rb +12 -11
  132. data/manual/text/column_box.rb +9 -10
  133. data/manual/text/fallback_fonts.rb +25 -21
  134. data/manual/text/font.rb +11 -12
  135. data/manual/text/font_size.rb +13 -14
  136. data/manual/text/font_style.rb +10 -8
  137. data/manual/text/formatted_callbacks.rb +33 -24
  138. data/manual/text/formatted_text.rb +36 -25
  139. data/manual/text/free_flowing_text.rb +22 -23
  140. data/manual/text/inline.rb +18 -19
  141. data/manual/text/kerning_and_character_spacing.rb +14 -15
  142. data/manual/text/leading.rb +7 -8
  143. data/manual/text/line_wrapping.rb +37 -18
  144. data/manual/text/paragraph_indentation.rb +12 -14
  145. data/manual/text/positioned_text.rb +15 -16
  146. data/manual/text/registering_families.rb +20 -21
  147. data/manual/text/rendering_and_color.rb +9 -10
  148. data/manual/text/right_to_left_text.rb +26 -19
  149. data/manual/text/rotation.rb +33 -23
  150. data/manual/text/single_usage.rb +8 -9
  151. data/manual/text/text.rb +57 -52
  152. data/manual/text/text_box_excess.rb +20 -17
  153. data/manual/text/text_box_extensions.rb +18 -15
  154. data/manual/text/text_box_overflow.rb +20 -19
  155. data/manual/text/utf8.rb +11 -12
  156. data/manual/text/win_ansi_charset.rb +27 -25
  157. data/prawn.gemspec +41 -34
  158. data/spec/extensions/encoding_helpers.rb +3 -3
  159. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  160. data/spec/prawn/document/column_box_spec.rb +75 -0
  161. data/spec/prawn/document/security_spec.rb +176 -0
  162. data/spec/prawn/document_annotations_spec.rb +76 -0
  163. data/spec/prawn/document_destinations_spec.rb +15 -0
  164. data/spec/prawn/document_grid_spec.rb +99 -0
  165. data/spec/prawn/document_reference_spec.rb +27 -0
  166. data/spec/prawn/document_span_spec.rb +44 -0
  167. data/spec/prawn/document_spec.rb +805 -0
  168. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  169. data/spec/prawn/font_spec.rb +544 -0
  170. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  171. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  172. data/spec/prawn/graphics_spec.rb +872 -0
  173. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  174. data/spec/{image_handler_spec.rb → prawn/image_handler_spec.rb} +14 -14
  175. data/spec/prawn/images/jpg_spec.rb +20 -0
  176. data/spec/prawn/images/png_spec.rb +283 -0
  177. data/spec/prawn/images_spec.rb +229 -0
  178. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  179. data/spec/prawn/outline_spec.rb +512 -0
  180. data/spec/prawn/repeater_spec.rb +166 -0
  181. data/spec/prawn/soft_mask_spec.rb +74 -0
  182. data/spec/prawn/stamp_spec.rb +173 -0
  183. data/spec/prawn/text/box_spec.rb +1110 -0
  184. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  185. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  186. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  187. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  188. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  189. data/spec/prawn/text_draw_text_spec.rb +150 -0
  190. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  191. data/spec/prawn/text_spacing_spec.rb +95 -0
  192. data/spec/prawn/text_spec.rb +603 -0
  193. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  194. data/spec/{transformation_stack_spec.rb → prawn/transformation_stack_spec.rb} +22 -19
  195. data/spec/prawn/view_spec.rb +63 -0
  196. data/spec/prawn_manual_spec.rb +35 -0
  197. data/spec/spec_helper.rb +18 -19
  198. metadata +102 -222
  199. metadata.gz.sig +0 -0
  200. data/data/images/16bit.alpha +0 -0
  201. data/data/images/16bit.color +0 -0
  202. data/data/images/16bit.png +0 -0
  203. data/data/images/arrow.png +0 -0
  204. data/data/images/arrow2.png +0 -0
  205. data/data/images/blend_modes_bottom_layer.jpg +0 -0
  206. data/data/images/blend_modes_top_layer.jpg +0 -0
  207. data/data/images/dice.alpha +0 -0
  208. data/data/images/dice.color +0 -0
  209. data/data/images/dice.png +0 -0
  210. data/data/images/dice_interlaced.png +0 -0
  211. data/data/images/fractal.jpg +0 -0
  212. data/data/images/indexed_color.dat +0 -0
  213. data/data/images/indexed_color.png +0 -0
  214. data/data/images/indexed_transparency.png +0 -0
  215. data/data/images/indexed_transparency_alpha.dat +0 -0
  216. data/data/images/indexed_transparency_color.dat +0 -0
  217. data/data/images/letterhead.jpg +0 -0
  218. data/data/images/license.md +0 -8
  219. data/data/images/page_white_text.alpha +0 -0
  220. data/data/images/page_white_text.color +0 -0
  221. data/data/images/page_white_text.png +0 -0
  222. data/data/images/pigs.jpg +0 -0
  223. data/data/images/prawn.png +0 -0
  224. data/data/images/ruport.png +0 -0
  225. data/data/images/ruport_data.dat +0 -0
  226. data/data/images/ruport_transparent.png +0 -0
  227. data/data/images/ruport_type0.png +0 -0
  228. data/data/images/stef.jpg +0 -0
  229. data/data/images/tru256.bmp +0 -0
  230. data/data/images/web-links.dat +0 -1
  231. data/data/images/web-links.png +0 -0
  232. data/data/pdfs/complex_template.pdf +0 -0
  233. data/data/pdfs/contains_ttf_font.pdf +0 -0
  234. data/data/pdfs/encrypted.pdf +0 -0
  235. data/data/pdfs/form.pdf +1 -819
  236. data/data/pdfs/hexagon.pdf +0 -61
  237. data/data/pdfs/indirect_reference.pdf +0 -86
  238. data/data/pdfs/multipage_template.pdf +0 -127
  239. data/data/pdfs/nested_pages.pdf +0 -118
  240. data/data/pdfs/page_without_mediabox.pdf +0 -193
  241. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  242. data/data/pdfs/two_hexagons.pdf +0 -90
  243. data/data/pdfs/version_1_6.pdf +0 -61
  244. data/data/shift_jis_text.txt +0 -1
  245. data/spec/acceptance/png_spec.rb +0 -35
  246. data/spec/annotations_spec.rb +0 -67
  247. data/spec/blend_mode_spec.rb +0 -71
  248. data/spec/bounding_box_spec.rb +0 -501
  249. data/spec/column_box_spec.rb +0 -59
  250. data/spec/destinations_spec.rb +0 -13
  251. data/spec/document_spec.rb +0 -738
  252. data/spec/font_metric_cache_spec.rb +0 -52
  253. data/spec/font_spec.rb +0 -475
  254. data/spec/formatted_text_arranger_spec.rb +0 -452
  255. data/spec/formatted_text_box_spec.rb +0 -716
  256. data/spec/formatted_text_fragment_spec.rb +0 -299
  257. data/spec/graphics_spec.rb +0 -705
  258. data/spec/grid_spec.rb +0 -95
  259. data/spec/images_spec.rb +0 -167
  260. data/spec/inline_formatted_text_parser_spec.rb +0 -568
  261. data/spec/jpg_spec.rb +0 -23
  262. data/spec/line_wrap_spec.rb +0 -366
  263. data/spec/measurement_units_spec.rb +0 -22
  264. data/spec/outline_spec.rb +0 -409
  265. data/spec/png_spec.rb +0 -257
  266. data/spec/reference_spec.rb +0 -25
  267. data/spec/repeater_spec.rb +0 -154
  268. data/spec/security_spec.rb +0 -151
  269. data/spec/soft_mask_spec.rb +0 -78
  270. data/spec/span_spec.rb +0 -43
  271. data/spec/stamp_spec.rb +0 -179
  272. data/spec/stroke_styles_spec.rb +0 -208
  273. data/spec/text_at_spec.rb +0 -142
  274. data/spec/text_box_spec.rb +0 -1042
  275. data/spec/text_rendering_mode_spec.rb +0 -45
  276. data/spec/text_spacing_spec.rb +0 -93
  277. data/spec/text_spec.rb +0 -543
  278. data/spec/text_with_inline_formatting_spec.rb +0 -35
  279. data/spec/transparency_spec.rb +0 -91
  280. data/spec/view_spec.rb +0 -42
@@ -1,7 +1,7 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require_relative "formatted/wrap"
3
+ require_relative 'formatted/wrap'
4
4
 
5
- require_relative "formatted/box"
6
- require_relative "formatted/parser"
7
- require_relative "formatted/fragment"
5
+ require_relative 'formatted/box'
6
+ require_relative 'formatted/parser'
7
+ require_relative 'formatted/fragment'
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # core/text/formatted/arranger.rb : Implements a data structure for 2-stage
4
4
  # processing of lines of formatted text
@@ -13,6 +13,25 @@ module Prawn
13
13
  # @private
14
14
 
15
15
  class Arranger #:nodoc:
16
+ class NotFinalized < StandardError
17
+ DEFAULT_MESSAGE = 'Lines must be finalized'
18
+ MESSAGE_WITH_METHOD = 'Lines must be finalized before calling #%<method>s'
19
+
20
+ def initialize(message = DEFAULT_MESSAGE, method: nil)
21
+ if method && message == DEFAULT_MESSAGE
22
+ super format(MESSAGE_WITH_METHOD, method: method)
23
+ else
24
+ super message
25
+ end
26
+ end
27
+ end
28
+
29
+ class BadFontFamily < StandardError
30
+ def initialize(message = 'Bad font family')
31
+ super
32
+ end
33
+ end
34
+
16
35
  attr_reader :max_line_height
17
36
  attr_reader :max_descender
18
37
  attr_reader :max_ascender
@@ -33,30 +52,33 @@ module Prawn
33
52
 
34
53
  def space_count
35
54
  unless finalized
36
- fail "Lines must be finalized before calling #space_count"
55
+ raise NotFinalized.new(method: 'space_count')
37
56
  end
38
57
 
39
- @fragments.inject(0) do |sum, fragment|
58
+ @fragments.reduce(0) do |sum, fragment|
40
59
  sum + fragment.space_count
41
60
  end
42
61
  end
43
62
 
44
63
  def line_width
45
64
  unless finalized
46
- fail "Lines must be finalized before calling #line_width"
65
+ raise raise NotFinalized.new(method: 'line_width')
47
66
  end
48
67
 
49
- @fragments.inject(0) do |sum, fragment|
68
+ @fragments.reduce(0) do |sum, fragment|
50
69
  sum + fragment.width
51
70
  end
52
71
  end
53
72
 
54
73
  def line
55
74
  unless finalized
56
- fail "Lines must be finalized before calling #line"
75
+ raise NotFinalized.new(method: 'line')
57
76
  end
58
77
 
59
- @fragments.collect do |fragment|
78
+ @fragments.map do |fragment|
79
+ fragment.text.dup.encode(::Encoding::UTF_8)
80
+ rescue ::Encoding::InvalidByteSequenceError,
81
+ ::Encoding::UndefinedConversionError
60
82
  fragment.text.dup.force_encoding(::Encoding::UTF_8)
61
83
  end.join
62
84
  end
@@ -70,12 +92,14 @@ module Prawn
70
92
  text = hash[:text]
71
93
  format_state = hash.dup
72
94
  format_state.delete(:text)
73
- fragment = Prawn::Text::Formatted::Fragment.new(text,
74
- format_state,
75
- @document)
95
+ fragment = Prawn::Text::Formatted::Fragment.new(
96
+ text,
97
+ format_state,
98
+ @document
99
+ )
76
100
  @fragments << fragment
77
- set_fragment_measurements(fragment)
78
- set_line_measurement_maximums(fragment)
101
+ self.fragment_measurements = fragment
102
+ self.line_measurement_maximums = fragment
79
103
  end
80
104
  end
81
105
 
@@ -84,7 +108,7 @@ module Prawn
84
108
  @unconsumed = []
85
109
  array.each do |hash|
86
110
  hash[:text].scan(/[^\n]+|\n/) do |line|
87
- @unconsumed << hash.merge(:text => line)
111
+ @unconsumed << hash.merge(text: line)
88
112
  end
89
113
  end
90
114
  end
@@ -100,12 +124,12 @@ module Prawn
100
124
  end
101
125
 
102
126
  def finished?
103
- @unconsumed.length == 0
127
+ @unconsumed.empty?
104
128
  end
105
129
 
106
130
  def next_string
107
131
  if finalized
108
- fail "Lines must not be finalized when calling #next_string"
132
+ raise NotFinalized.new(method: 'next_string')
109
133
  end
110
134
 
111
135
  next_unconsumed_hash = @unconsumed.shift
@@ -146,21 +170,23 @@ module Prawn
146
170
  font = current_format_state[:font]
147
171
  size = current_format_state[:size]
148
172
  character_spacing = current_format_state[:character_spacing] ||
149
- @document.character_spacing
173
+ @document.character_spacing
150
174
  styles = current_format_state[:styles]
151
- font_style = font_style(styles)
152
175
  else
153
176
  font = fragment.font
154
177
  size = fragment.size
155
178
  character_spacing = fragment.character_spacing
156
179
  styles = fragment.styles
157
- font_style = font_style(styles)
158
180
  end
181
+ font_style = font_style(styles)
159
182
 
160
183
  @document.character_spacing(character_spacing) do
161
184
  if font || font_style != :normal
162
- fail "Bad font family" unless @document.font.family
163
- @document.font(font || @document.font.family, :style => font_style) do
185
+ raise BadFontFamily unless @document.font.family
186
+
187
+ @document.font(
188
+ font || @document.font.family, style: font_style
189
+ ) do
164
190
  apply_font_size(size, styles, &block)
165
191
  end
166
192
  else
@@ -171,6 +197,7 @@ module Prawn
171
197
 
172
198
  def update_last_string(printed, unprinted, normalized_soft_hyphen = nil)
173
199
  return if printed.nil?
200
+
174
201
  if printed.empty?
175
202
  @consumed.pop
176
203
  else
@@ -181,7 +208,7 @@ module Prawn
181
208
  end
182
209
 
183
210
  unless unprinted.empty?
184
- @unconsumed.unshift(@current_format_state.merge(:text => unprinted))
211
+ @unconsumed.unshift(@current_format_state.merge(text: unprinted))
185
212
  end
186
213
 
187
214
  load_previous_format_state if printed.empty?
@@ -189,7 +216,7 @@ module Prawn
189
216
 
190
217
  def retrieve_fragment
191
218
  unless finalized
192
- fail "Lines must be finalized before fragments can be retrieved"
219
+ raise NotFinalized, 'Lines must be finalized before fragments can be retrieved'
193
220
  end
194
221
 
195
222
  @fragments.shift
@@ -197,17 +224,18 @@ module Prawn
197
224
 
198
225
  def repack_unretrieved
199
226
  new_unconsumed = []
227
+ # rubocop: disable Lint/AssignmentInCondition
200
228
  while fragment = retrieve_fragment
229
+ # rubocop: enable Lint/AssignmentInCondition
201
230
  fragment.include_trailing_white_space!
202
- new_unconsumed << fragment.format_state.merge(:text => fragment.text)
231
+ new_unconsumed << fragment.format_state.merge(text: fragment.text)
203
232
  end
204
233
  @unconsumed = new_unconsumed.concat(@unconsumed)
205
234
  end
206
235
 
207
236
  def font_style(styles)
208
- if styles.nil?
209
- :normal
210
- elsif styles.include?(:bold) && styles.include?(:italic)
237
+ styles = Array(styles)
238
+ if styles.include?(:bold) && styles.include?(:italic)
211
239
  :bold_italic
212
240
  elsif styles.include?(:bold)
213
241
  :bold
@@ -230,19 +258,20 @@ module Prawn
230
258
  end
231
259
  end
232
260
 
233
- def apply_font_size(size, styles)
261
+ def apply_font_size(size, styles, &block)
234
262
  if subscript?(styles) || superscript?(styles)
235
263
  relative_size = 0.583
236
- if size.nil?
237
- size = @document.font_size * relative_size
238
- else
239
- size = size * relative_size
240
- end
264
+ size =
265
+ if size.nil?
266
+ @document.font_size * relative_size
267
+ else
268
+ size * relative_size
269
+ end
241
270
  end
242
271
  if size.nil?
243
272
  yield
244
273
  else
245
- @document.font_size(size) { yield }
274
+ @document.font_size(size, &block)
246
275
  end
247
276
  end
248
277
 
@@ -274,20 +303,31 @@ module Prawn
274
303
  end
275
304
  end
276
305
 
277
- def set_fragment_measurements(fragment)
306
+ def fragment_measurements=(fragment)
278
307
  apply_font_settings(fragment) do
279
- fragment.width = @document.width_of(fragment.text,
280
- :kerning => @kerning)
308
+ fragment.width = @document.width_of(
309
+ fragment.text,
310
+ kerning: @kerning
311
+ )
281
312
  fragment.line_height = @document.font.height
282
313
  fragment.descender = @document.font.descender
283
314
  fragment.ascender = @document.font.ascender
284
315
  end
285
316
  end
286
317
 
287
- def set_line_measurement_maximums(fragment)
288
- @max_line_height = [defined?(@max_line_height) && @max_line_height, fragment.line_height].compact.max
289
- @max_descender = [defined?(@max_descender) && @max_descender, fragment.descender].compact.max
290
- @max_ascender = [defined?(@max_ascender) && @max_ascender, fragment.ascender].compact.max
318
+ def line_measurement_maximums=(fragment)
319
+ @max_line_height = [
320
+ defined?(@max_line_height) && @max_line_height,
321
+ fragment.line_height
322
+ ].compact.max
323
+ @max_descender = [
324
+ defined?(@max_descender) && @max_descender,
325
+ fragment.descender
326
+ ].compact.max
327
+ @max_ascender = [
328
+ defined?(@max_ascender) && @max_ascender,
329
+ fragment.ascender
330
+ ].compact.max
291
331
  end
292
332
  end
293
333
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # text/formatted/rectangle.rb : Implements text boxes with formatted text
4
4
  #
@@ -54,8 +54,8 @@ module Prawn
54
54
  # a file or application to be opened locally. A clickable link will be
55
55
  # created to the provided local file or application. If the file is
56
56
  # another PDF, it will be opened in a new window. Note that you must
57
- # explicitly underline and color using the appropriate tags if you which
58
- # to draw attention to the link
57
+ # explicitly underline and color using the appropriate tags if you
58
+ # which to draw attention to the link
59
59
  # <tt>:draw_text_callback</tt>:
60
60
  # if provided, this Proc will be called instead of #draw_text! once
61
61
  # per fragment for every low-level addition of text to the page.
@@ -83,13 +83,14 @@ module Prawn
83
83
  #
84
84
  # == Exceptions
85
85
  #
86
- # Raises "Bad font family" if no font family is defined for the current font
86
+ # Raises "Bad font family" if no font family is defined for the current
87
+ # font
87
88
  #
88
89
  # Raises <tt>Prawn::Errors::CannotFit</tt> if not wide enough to print
89
90
  # any text
90
91
  #
91
92
  def formatted_text_box(array, options = {})
92
- Text::Formatted::Box.new(array, options.merge(:document => self)).render
93
+ Text::Formatted::Box.new(array, options.merge(document: self)).render
93
94
  end
94
95
 
95
96
  # Generally, one would use the Prawn::Text::Formatted#formatted_text_box
@@ -137,37 +138,38 @@ module Prawn
137
138
  # See Prawn::Text#text_box for valid options
138
139
  #
139
140
  def initialize(formatted_text, options = {})
140
- @inked = false
141
+ @inked = false
141
142
  Prawn.verify_options(valid_options, options)
142
- options = options.dup
143
+ options = options.dup
143
144
 
144
145
  self.class.extensions.reverse_each { |e| extend e }
145
146
 
146
- @overflow = options[:overflow] || :truncate
147
+ @overflow = options[:overflow] || :truncate
147
148
  @disable_wrap_by_char = options[:disable_wrap_by_char]
148
149
 
149
150
  self.original_text = formatted_text
150
- @text = nil
151
-
152
- @document = options[:document]
153
- @direction = options[:direction] || @document.text_direction
154
- @fallback_fonts = options[:fallback_fonts] ||
155
- @document.fallback_fonts
156
- @at = (options[:at] ||
157
- [@document.bounds.left, @document.bounds.top]).dup
158
- @width = options[:width] ||
159
- @document.bounds.right - @at[0]
160
- @height = options[:height] || default_height
161
- @align = options[:align] ||
162
- (@direction == :rtl ? :right : :left)
163
- @vertical_align = options[:valign] || :top
164
- @leading = options[:leading] || @document.default_leading
151
+ @text = nil
152
+
153
+ @document = options[:document]
154
+ @direction = options[:direction] || @document.text_direction
155
+ @fallback_fonts = options[:fallback_fonts] ||
156
+ @document.fallback_fonts
157
+ @at = (
158
+ options[:at] || [@document.bounds.left, @document.bounds.top]
159
+ ).dup
160
+ @width = options[:width] ||
161
+ @document.bounds.right - @at[0]
162
+ @height = options[:height] || default_height
163
+ @align = options[:align] ||
164
+ (@direction == :rtl ? :right : :left)
165
+ @vertical_align = options[:valign] || :top
166
+ @leading = options[:leading] || @document.default_leading
165
167
  @character_spacing = options[:character_spacing] ||
166
- @document.character_spacing
167
- @mode = options[:mode] || @document.text_rendering_mode
168
- @rotate = options[:rotate] || 0
169
- @rotate_around = options[:rotate_around] || :upper_left
170
- @single_line = options[:single_line]
168
+ @document.character_spacing
169
+ @mode = options[:mode] || @document.text_rendering_mode
170
+ @rotate = options[:rotate] || 0
171
+ @rotate_around = options[:rotate_around] || :upper_left
172
+ @single_line = options[:single_line]
171
173
  @draw_text_callback = options[:draw_text_callback]
172
174
 
173
175
  # if the text rendering mode is :unknown, force it back to :fill
@@ -183,25 +185,28 @@ module Prawn
183
185
  @overflow = :truncate
184
186
  end
185
187
  @min_font_size = options[:min_font_size] || 5
186
- if options[:kerning].nil? then
188
+ if options[:kerning].nil?
187
189
  options[:kerning] = @document.default_kerning?
188
190
  end
189
- @options = { :kerning => options[:kerning],
190
- :size => options[:size],
191
- :style => options[:style] }
191
+ @options = {
192
+ kerning: options[:kerning],
193
+ size: options[:size],
194
+ style: options[:style]
195
+ }
192
196
 
193
197
  super(formatted_text, options)
194
198
  end
195
199
 
196
- # Render text to the document based on the settings defined in initialize.
200
+ # Render text to the document based on the settings defined in
201
+ # initialize.
197
202
  #
198
- # In order to facilitate look-ahead calculations, <tt>render</tt> accepts
199
- # a <tt>:dry_run => true</tt> option. If provided, then everything is
200
- # executed as if rendering, with the exception that nothing is drawn on
201
- # the page. Useful for look-ahead computations of height, unprinted text,
202
- # etc.
203
+ # In order to facilitate look-ahead calculations, <tt>render</tt>
204
+ # accepts a <tt>:dry_run => true</tt> option. If provided, then
205
+ # everything is executed as if rendering, with the exception that
206
+ # nothing is drawn on the page. Useful for look-ahead computations of
207
+ # height, unprinted text, etc.
203
208
  #
204
- # Returns any text that did not print under the current settings
209
+ # Returns any text that did not print under the current settings.
205
210
  #
206
211
  def render(flags = {})
207
212
  unprinted_text = []
@@ -217,11 +222,12 @@ module Prawn
217
222
  shrink_to_fit(text) if @overflow == :shrink_to_fit
218
223
  process_vertical_alignment(text)
219
224
  @inked = true unless flags[:dry_run]
220
- if @rotate != 0 && @inked
221
- unprinted_text = render_rotated(text)
222
- else
223
- unprinted_text = wrap(text)
224
- end
225
+ unprinted_text =
226
+ if @rotate != 0 && @inked
227
+ render_rotated(text)
228
+ else
229
+ wrap(text)
230
+ end
225
231
  @inked = false
226
232
  end
227
233
  end
@@ -229,7 +235,7 @@ module Prawn
229
235
  end
230
236
 
231
237
  unprinted_text.map do |e|
232
- e.merge(:text => @document.font.to_utf8(e[:text]))
238
+ e.merge(text: @document.font.to_utf8(e[:text]))
233
239
  end
234
240
  end
235
241
 
@@ -243,13 +249,16 @@ module Prawn
243
249
  #
244
250
  def height
245
251
  return 0 if @baseline_y.nil? || @descender.nil?
252
+
246
253
  (@baseline_y - @descender).abs
247
254
  end
248
255
 
249
256
  # <tt>fragment</tt> is a Prawn::Text::Formatted::Fragment object
250
257
  #
251
- def draw_fragment(fragment, accumulated_width = 0, line_width = 0, word_spacing = 0) #:nodoc:
252
- case(@align)
258
+ def draw_fragment(
259
+ fragment, accumulated_width = 0, line_width = 0, word_spacing = 0
260
+ ) #:nodoc:
261
+ case @align
253
262
  when :left
254
263
  x = @at[0]
255
264
  when :center
@@ -257,11 +266,15 @@ module Prawn
257
266
  when :right
258
267
  x = @at[0] + @width - line_width
259
268
  when :justify
260
- if @direction == :ltr
261
- x = @at[0]
262
- else
263
- x = @at[0] + @width - line_width
264
- end
269
+ x =
270
+ if @direction == :ltr
271
+ @at[0]
272
+ else
273
+ @at[0] + @width - line_width
274
+ end
275
+ else
276
+ raise ArgumentError,
277
+ 'align must be one of :left, :right, :center or :justify symbols'
265
278
  end
266
279
 
267
280
  x += accumulated_width
@@ -276,15 +289,21 @@ module Prawn
276
289
  if @inked
277
290
  draw_fragment_underlays(fragment)
278
291
 
279
- @document.word_spacing(word_spacing) {
292
+ @document.word_spacing(word_spacing) do
280
293
  if @draw_text_callback
281
- @draw_text_callback.call(fragment.text, :at => [x, y],
282
- :kerning => @kerning)
294
+ @draw_text_callback.call(
295
+ fragment.text,
296
+ at: [x, y],
297
+ kerning: @kerning
298
+ )
283
299
  else
284
- @document.draw_text!(fragment.text, :at => [x, y],
285
- :kerning => @kerning)
300
+ @document.draw_text!(
301
+ fragment.text,
302
+ at: [x, y],
303
+ kerning: @kerning
304
+ )
286
305
  end
287
- }
306
+ end
288
307
 
289
308
  draw_fragment_overlays(fragment)
290
309
  end
@@ -325,23 +344,24 @@ module Prawn
325
344
 
326
345
  # @private
327
346
  def self.inherited(base)
347
+ super
328
348
  extensions.each { |e| base.extensions << e }
329
349
  end
330
350
 
331
351
  def valid_options
332
- PDF::Core::Text::VALID_OPTIONS + [
333
- :at,
334
- :height, :width,
335
- :align, :valign,
336
- :rotate, :rotate_around,
337
- :overflow, :min_font_size,
338
- :disable_wrap_by_char,
339
- :leading, :character_spacing,
340
- :mode, :single_line,
341
- :document,
342
- :direction,
343
- :fallback_fonts,
344
- :draw_text_callback
352
+ PDF::Core::Text::VALID_OPTIONS + %i[
353
+ at
354
+ height width
355
+ align valign
356
+ rotate rotate_around
357
+ overflow min_font_size
358
+ disable_wrap_by_char
359
+ leading character_spacing
360
+ mode single_line
361
+ document
362
+ direction
363
+ fallback_fonts
364
+ draw_text_callback
345
365
  ]
346
366
  end
347
367
 
@@ -356,7 +376,7 @@ module Prawn
356
376
  end
357
377
 
358
378
  def original_text
359
- @original_array.collect(&:dup)
379
+ @original_array.map(&:dup)
360
380
  end
361
381
 
362
382
  def original_text=(formatted_text)
@@ -407,10 +427,14 @@ module Prawn
407
427
 
408
428
  @document.save_font do
409
429
  hash[:text].each_char do |char|
410
- font_glyph_pairs << [find_font_for_this_glyph(char,
411
- fragment_font,
412
- fallback_fonts.dup),
413
- char]
430
+ font_glyph_pairs << [
431
+ find_font_for_this_glyph(
432
+ char,
433
+ fragment_font,
434
+ fallback_fonts.dup
435
+ ),
436
+ char
437
+ ]
414
438
  end
415
439
  end
416
440
 
@@ -426,7 +450,7 @@ module Prawn
426
450
 
427
451
  def find_font_for_this_glyph(char, current_font, fallback_fonts)
428
452
  @document.font(current_font)
429
- if fallback_fonts.length == 0 || @document.font.glyph_present?(char)
453
+ if fallback_fonts.empty? || @document.font.glyph_present?(char)
430
454
  current_font
431
455
  else
432
456
  find_font_for_this_glyph(char, fallback_fonts.shift, fallback_fonts)
@@ -439,7 +463,7 @@ module Prawn
439
463
  current_font = nil
440
464
 
441
465
  font_glyph_pairs.each do |font, char|
442
- if font != current_font || fragments.count == 0
466
+ if font != current_font || fragments.count.zero?
443
467
  current_font = font
444
468
  fragment = hash.dup
445
469
  fragment[:text] = char
@@ -454,8 +478,8 @@ module Prawn
454
478
  end
455
479
 
456
480
  def move_baseline_down
457
- if @baseline_y == 0
458
- @baseline_y = -@ascender
481
+ if @baseline_y.zero?
482
+ @baseline_y = -@ascender
459
483
  else
460
484
  @baseline_y -= (@line_height + @leading)
461
485
  end
@@ -479,7 +503,11 @@ module Prawn
479
503
  # we need to wait until render() is called so that the fonts are set
480
504
  # up properly for wrapping. So guard with a boolean to ensure this is
481
505
  # only run once.
482
- return if defined?(@vertical_alignment_processed) && @vertical_alignment_processed
506
+ if defined?(@vertical_alignment_processed) &&
507
+ @vertical_alignment_processed
508
+ return
509
+ end
510
+
483
511
  @vertical_alignment_processed = true
484
512
 
485
513
  return if @vertical_align == :top
@@ -523,7 +551,7 @@ module Prawn
523
551
  # document.process_text_options sets the font
524
552
  @document.process_text_options(@options)
525
553
  @font_size = @options[:size]
526
- @kerning = @options[:kerning]
554
+ @kerning = @options[:kerning]
527
555
  end
528
556
 
529
557
  def render_rotated(text)
@@ -547,7 +575,7 @@ module Prawn
547
575
  y = @at[1]
548
576
  end
549
577
 
550
- @document.rotate(@rotate, :origin => [x, y]) do
578
+ @document.rotate(@rotate, origin: [x, y]) do
551
579
  unprinted_text = wrap(text)
552
580
  end
553
581
  unprinted_text
@@ -571,41 +599,52 @@ module Prawn
571
599
 
572
600
  def draw_fragment_overlay_link(fragment)
573
601
  return unless fragment.link
602
+
574
603
  box = fragment.absolute_bounding_box
575
- @document.link_annotation(box,
576
- :Border => [0, 0, 0],
577
- :A => { :Type => :Action,
578
- :S => :URI,
579
- :URI => PDF::Core::LiteralString.new(fragment.link) })
604
+ @document.link_annotation(
605
+ box,
606
+ Border: [0, 0, 0],
607
+ A: {
608
+ Type: :Action,
609
+ S: :URI,
610
+ URI: PDF::Core::LiteralString.new(fragment.link)
611
+ }
612
+ )
580
613
  end
581
614
 
582
615
  def draw_fragment_overlay_anchor(fragment)
583
616
  return unless fragment.anchor
617
+
584
618
  box = fragment.absolute_bounding_box
585
- @document.link_annotation(box,
586
- :Border => [0, 0, 0],
587
- :Dest => fragment.anchor)
619
+ @document.link_annotation(
620
+ box,
621
+ Border: [0, 0, 0],
622
+ Dest: fragment.anchor
623
+ )
588
624
  end
589
625
 
590
626
  def draw_fragment_overlay_local(fragment)
591
627
  return unless fragment.local
628
+
592
629
  box = fragment.absolute_bounding_box
593
- @document.link_annotation(box,
594
- :Border => [0, 0, 0],
595
- :A => { :Type => :Action,
596
- :S => :Launch,
597
- :F => PDF::Core::LiteralString.new(fragment.local),
598
- :NewWindow => true })
630
+ @document.link_annotation(
631
+ box,
632
+ Border: [0, 0, 0],
633
+ A: {
634
+ Type: :Action,
635
+ S: :Launch,
636
+ F: PDF::Core::LiteralString.new(fragment.local),
637
+ NewWindow: true
638
+ }
639
+ )
599
640
  end
600
641
 
601
642
  def draw_fragment_overlay_styles(fragment)
602
- underline = fragment.styles.include?(:underline)
603
- if underline
643
+ if fragment.styles.include?(:underline)
604
644
  @document.stroke_line(fragment.underline_points)
605
645
  end
606
646
 
607
- strikethrough = fragment.styles.include?(:strikethrough)
608
- if strikethrough
647
+ if fragment.styles.include?(:strikethrough)
609
648
  @document.stroke_line(fragment.strikethrough_points)
610
649
  end
611
650
  end