giga-fast-kit 0.0.1

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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/giga-fast-kit.gemspec +12 -0
  3. data/prawn-2.5.0/COPYING +2 -0
  4. data/prawn-2.5.0/GPLv2 +339 -0
  5. data/prawn-2.5.0/GPLv3 +674 -0
  6. data/prawn-2.5.0/LICENSE +56 -0
  7. data/prawn-2.5.0/data/fonts/Courier-Bold.afm +342 -0
  8. data/prawn-2.5.0/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/prawn-2.5.0/data/fonts/Courier-Oblique.afm +342 -0
  10. data/prawn-2.5.0/data/fonts/Courier.afm +342 -0
  11. data/prawn-2.5.0/data/fonts/Helvetica-Bold.afm +2827 -0
  12. data/prawn-2.5.0/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  13. data/prawn-2.5.0/data/fonts/Helvetica-Oblique.afm +3051 -0
  14. data/prawn-2.5.0/data/fonts/Helvetica.afm +3051 -0
  15. data/prawn-2.5.0/data/fonts/MustRead.html +19 -0
  16. data/prawn-2.5.0/data/fonts/Symbol.afm +213 -0
  17. data/prawn-2.5.0/data/fonts/Times-Bold.afm +2588 -0
  18. data/prawn-2.5.0/data/fonts/Times-BoldItalic.afm +2384 -0
  19. data/prawn-2.5.0/data/fonts/Times-Italic.afm +2667 -0
  20. data/prawn-2.5.0/data/fonts/Times-Roman.afm +2419 -0
  21. data/prawn-2.5.0/data/fonts/ZapfDingbats.afm +225 -0
  22. data/prawn-2.5.0/lib/prawn/document/bounding_box.rb +625 -0
  23. data/prawn-2.5.0/lib/prawn/document/column_box.rb +177 -0
  24. data/prawn-2.5.0/lib/prawn/document/internals.rb +76 -0
  25. data/prawn-2.5.0/lib/prawn/document/span.rb +65 -0
  26. data/prawn-2.5.0/lib/prawn/document.rb +846 -0
  27. data/prawn-2.5.0/lib/prawn/encoding.rb +85 -0
  28. data/prawn-2.5.0/lib/prawn/errors.rb +73 -0
  29. data/prawn-2.5.0/lib/prawn/font.rb +567 -0
  30. data/prawn-2.5.0/lib/prawn/font_metric_cache.rb +50 -0
  31. data/prawn-2.5.0/lib/prawn/fonts/afm.rb +332 -0
  32. data/prawn-2.5.0/lib/prawn/fonts/dfont.rb +42 -0
  33. data/prawn-2.5.0/lib/prawn/fonts/otf.rb +14 -0
  34. data/prawn-2.5.0/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  35. data/prawn-2.5.0/lib/prawn/fonts/ttc.rb +41 -0
  36. data/prawn-2.5.0/lib/prawn/fonts/ttf.rb +615 -0
  37. data/prawn-2.5.0/lib/prawn/fonts.rb +14 -0
  38. data/prawn-2.5.0/lib/prawn/graphics/blend_mode.rb +62 -0
  39. data/prawn-2.5.0/lib/prawn/graphics/cap_style.rb +44 -0
  40. data/prawn-2.5.0/lib/prawn/graphics/color.rb +257 -0
  41. data/prawn-2.5.0/lib/prawn/graphics/dash.rb +123 -0
  42. data/prawn-2.5.0/lib/prawn/graphics/join_style.rb +60 -0
  43. data/prawn-2.5.0/lib/prawn/graphics/patterns.rb +389 -0
  44. data/prawn-2.5.0/lib/prawn/graphics/transformation.rb +172 -0
  45. data/prawn-2.5.0/lib/prawn/graphics/transparency.rb +79 -0
  46. data/prawn-2.5.0/lib/prawn/graphics.rb +791 -0
  47. data/prawn-2.5.0/lib/prawn/grid.rb +449 -0
  48. data/prawn-2.5.0/lib/prawn/image_handler.rb +61 -0
  49. data/prawn-2.5.0/lib/prawn/images/image.rb +48 -0
  50. data/prawn-2.5.0/lib/prawn/images/jpg.rb +121 -0
  51. data/prawn-2.5.0/lib/prawn/images/png.rb +383 -0
  52. data/prawn-2.5.0/lib/prawn/images.rb +195 -0
  53. data/prawn-2.5.0/lib/prawn/measurement_extensions.rb +82 -0
  54. data/prawn-2.5.0/lib/prawn/measurements.rb +129 -0
  55. data/prawn-2.5.0/lib/prawn/outline.rb +316 -0
  56. data/prawn-2.5.0/lib/prawn/repeater.rb +140 -0
  57. data/prawn-2.5.0/lib/prawn/security/arcfour.rb +54 -0
  58. data/prawn-2.5.0/lib/prawn/security.rb +308 -0
  59. data/prawn-2.5.0/lib/prawn/soft_mask.rb +105 -0
  60. data/prawn-2.5.0/lib/prawn/stamp.rb +147 -0
  61. data/prawn-2.5.0/lib/prawn/text/box.rb +192 -0
  62. data/prawn-2.5.0/lib/prawn/text/formatted/arranger.rb +396 -0
  63. data/prawn-2.5.0/lib/prawn/text/formatted/box.rb +725 -0
  64. data/prawn-2.5.0/lib/prawn/text/formatted/fragment.rb +373 -0
  65. data/prawn-2.5.0/lib/prawn/text/formatted/line_wrap.rb +335 -0
  66. data/prawn-2.5.0/lib/prawn/text/formatted/parser.rb +284 -0
  67. data/prawn-2.5.0/lib/prawn/text/formatted/wrap.rb +166 -0
  68. data/prawn-2.5.0/lib/prawn/text/formatted.rb +82 -0
  69. data/prawn-2.5.0/lib/prawn/text.rb +701 -0
  70. data/prawn-2.5.0/lib/prawn/transformation_stack.rb +63 -0
  71. data/prawn-2.5.0/lib/prawn/utilities.rb +34 -0
  72. data/prawn-2.5.0/lib/prawn/version.rb +6 -0
  73. data/prawn-2.5.0/lib/prawn/view.rb +116 -0
  74. data/prawn-2.5.0/lib/prawn.rb +83 -0
  75. metadata +114 -0
@@ -0,0 +1,701 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zlib'
4
+
5
+ require_relative 'text/formatted'
6
+ require_relative 'text/box'
7
+
8
+ module Prawn
9
+ # PDF text primitives.
10
+ module Text
11
+ include PDF::Core::Text
12
+ include Prawn::Text::Formatted
13
+
14
+ # No-Break Space
15
+ NBSP = "\u00A0"
16
+
17
+ # Zero Width Space (indicate word boundaries without a space)
18
+ ZWSP = "\u200B"
19
+
20
+ # Soft Hyphen (invisible, except when causing a line break)
21
+ SHY = "\u00AD"
22
+
23
+ # @group Stable API
24
+
25
+ # Draws text on the page.
26
+ #
27
+ # If you want text to flow onto a new page or between columns, this is the
28
+ # method to use. If, instead, you want to place bounded text outside of the
29
+ # flow of a document (for captions, labels, charts, etc.), use {Text::Box}
30
+ # or its convenience method {text_box}.
31
+ #
32
+ # Prawn attempts to wrap the text to fit within your current bounding box
33
+ # (or `margin_box` if no bounding box is being used). Text will flow onto
34
+ # the next page when it reaches the bottom of the bounding box. Text wrap in
35
+ # Prawn does not re-flow line breaks, so if you want fully automated text
36
+ # wrapping, be sure to remove newlines before attempting to draw your
37
+ # string.
38
+ #
39
+ # #### Examples
40
+ #
41
+ # ```ruby
42
+ # pdf.text "Will be wrapped when it hits the edge of your bounding box"
43
+ # pdf.text "This will be centered", align: :center
44
+ # pdf.text "This will be right aligned", align: :right
45
+ # pdf.text "This <i>includes <b>inline</b></i> <font size='24'>formatting</font>", inline_format: true
46
+ # ```
47
+ #
48
+ # If your font contains kerning pair data that Prawn can parse, the text
49
+ # will be kerned by default. You can disable kerning by including a `false`
50
+ # `:kerning` option. If you want to disable kerning on an entire document,
51
+ # set `default_kerning = false` for that document.
52
+ #
53
+ # #### Text Positioning Details
54
+ #
55
+ # The text is positioned at `font.ascender` below the baseline, making it
56
+ # easy to use this method within bounding boxes and spans.
57
+ #
58
+ # #### Encoding
59
+ #
60
+ # Note that strings passed to this function should be encoded as UTF-8. If
61
+ # you get unexpected characters appearing in your rendered document, check
62
+ # this.
63
+ #
64
+ # If the current font is a built-in one, although the string must be encoded
65
+ # as UTF-8, only characters that are available in WinAnsi are allowed.
66
+ #
67
+ # If an empty box is rendered to your PDF instead of the character you
68
+ # wanted it usually means the current font doesn't include that character.
69
+ #
70
+ # @param string [String]
71
+ # @param options [Hash{Symbol => any}]
72
+ # @option options :inline_format [Boolean]
73
+ # If `true`, then the string parameter is interpreted as a HTML-esque
74
+ # string that recognizes the following tags (assuming the default text
75
+ # formatter is used):
76
+ # - `<b></b>`{:.language-html} --- bold style.
77
+ # - `<i></i>`{:.language-html} --- italic style.
78
+ # - `<u></u>`{:.language-html} --- underline.
79
+ # - `<strikethrough></strikethrough>`{:.language-html} --- strikethrough.
80
+ # - `<sub></sub>`{:.language-html} --- subscript.
81
+ # - `<sup></sup>`{:.language-html} --- superscript.
82
+ # - `<font></font>`{:.language-html} --- with the following attributes
83
+ # (using double or single quotes):
84
+ # - `name="Helvetica"`{:.language-html} --- the font. The font name must
85
+ # be an AFM font with the desired faces or must be a font that is
86
+ # already registered using {Prawn::Document#font_families}.
87
+ # - `size="24"`{:.language-html} --- attribute for setting size.
88
+ # - `character_spacing="2.5"`{:.language-html} --- character spacing.
89
+ # - `<color></color>`{:.language-html} --- text color
90
+ # - `rgb="ffffff"`{:.language-html} or `rgb="#ffffff"`{:.language-html}
91
+ # --- RGB color
92
+ # - `c="100" m="100" y="100" k="100"`{:.language-html} --- CMYK color
93
+ # - `<link></link>`{:.language-html} - link, with the following
94
+ # attributes:
95
+ # - `href="http://example.com"`{:.language-html} --- an external link.
96
+ # Note that you must explicitly underline and color using the
97
+ # appropriate tags if you which to draw attention to the link.
98
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
99
+ # Whether or not to use kerning (if it is available with the current
100
+ # font).
101
+ # @option options :size [Number] (current ofnt size) The font size to use.
102
+ # @option options :color [Color]
103
+ # @option options :character_spacing [Number] (0)
104
+ # The amount of space to add to or remove from the default character
105
+ # spacing.
106
+ # @option options :style [Symbol] (current style)
107
+ # The style to use. The requested style must be part of the current font
108
+ # family.
109
+ # @option options :indent_paragraphs [Number]
110
+ # The amount to indent the first line of each paragraph. Omit this option
111
+ # if you do not want indenting.
112
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
113
+ # Direction of the text.
114
+ # @option options :fallback_fonts [Array<String>]
115
+ # An array of font names. Each name must be the name of an AFM font or the
116
+ # name that was used to register a family of TTF fonts (see
117
+ # {Prawn::Document#font_families}). If present, then each glyph will be
118
+ # rendered using the first font that includes the glyph, starting with the
119
+ # current font and then moving through `:fallback_fonts`.
120
+ # @option option :align [:left, :center, :right, :justify]
121
+ # (:left if direction is :ltr, :right if direction is :rtl)
122
+ # Alignment within the bounding box.
123
+ # @option options :valign [:top, :center, :bottom] (:top)
124
+ # Vertical alignment within the bounding box.
125
+ # @option options :leading (Number) (value of document.default_leading)
126
+ # Additional space between lines.
127
+ # @option options :final_gap [Boolean] (true)
128
+ # If `true`, then the space between each line is included below the last
129
+ # line; otherwise, {Document.y} is placed just below the descender of the
130
+ # last line printed.
131
+ # @option options :mode [Symbol] (:fill)
132
+ # The text rendering mode to use. Use this to specify if the text should
133
+ # render with the fill color, stroke color or both.
134
+ # * `:fill` - fill text (default)
135
+ # * `:stroke` - stroke text
136
+ # * `:fill_stroke` - fill, then stroke text
137
+ # * `:invisible` - invisible text
138
+ # * `:fill_clip` - fill text then add to path for clipping
139
+ # * `:stroke_clip` - stroke text then add to path for clipping
140
+ # * `:fill_stroke_clip` - fill then stroke text, then add to path for
141
+ # clipping
142
+ # * `:clip` - add text to path for clipping
143
+ #
144
+ # @return [void]
145
+ #
146
+ # @raise [ArgumentError] if `:at` option included
147
+ # @raise [Prawn::Errrors::CannotFit] if not wide enough to print any text
148
+ #
149
+ # @see PDF::Core::Text#text_rendering_mode()
150
+ # for a list of valid text rendering modes.
151
+ def text(string, options = {})
152
+ return false if string.nil?
153
+
154
+ # we modify the options. don't change the user's hash
155
+ options = options.dup
156
+
157
+ p = options[:inline_format]
158
+ if p
159
+ p = [] unless p.is_a?(Array)
160
+ options.delete(:inline_format)
161
+ array = text_formatter.format(string, *p)
162
+ else
163
+ array = [{ text: string }]
164
+ end
165
+
166
+ formatted_text(array, options)
167
+ end
168
+
169
+ # Draws formatted text to the page.
170
+ #
171
+ # Formatted text is an array of hashes, where each hash defines text and
172
+ # format information.
173
+ #
174
+ # @example
175
+ # text([{ :text => "hello" },
176
+ # { :text => "world",
177
+ # :size => 24,
178
+ # :styles => [:bold, :italic] }])
179
+ #
180
+ # @param array [Array<Hash>] array of text fragments. See
181
+ # {Text::Formatted#formatted_text_box} for more information on the
182
+ # structure of this array.
183
+ # @param options [Hash{Symbol => any}]
184
+ # @option options :inline_format [Boolean]
185
+ # If `true`, then the string parameter is interpreted as a HTML-esque
186
+ # string that recognizes the following tags (assuming the default text
187
+ # formatter is used):
188
+ # - `<b></b>`{:.language-html} --- bold style.
189
+ # - `<i></i>`{:.language-html} --- italic style.
190
+ # - `<u></u>`{:.language-html} --- underline.
191
+ # - `<strikethrough></strikethrough>`{:.language-html} --- strikethrough.
192
+ # - `<sub></sub>`{:.language-html} --- subscript.
193
+ # - `<sup></sup>`{:.language-html} --- superscript.
194
+ # - `<font></font>`{:.language-html} --- with the following attributes
195
+ # (using double or single quotes):
196
+ # - `name="Helvetica"`{:.language-html} --- the font. The font name must
197
+ # be an AFM font with the desired faces or must be a font that is
198
+ # already registered using {Prawn::Document#font_families}.
199
+ # - `size="24"`{:.language-html} --- attribute for setting size.
200
+ # - `character_spacing="2.5"`{:.language-html} --- character spacing.
201
+ # - `<color></color>`{:.language-html} --- text color
202
+ # - `rgb="ffffff"`{:.language-html} or `rgb="#ffffff"`{:.language-html}
203
+ # --- RGB color
204
+ # - `c="100" m="100" y="100" k="100"`{:.language-html} --- CMYK color
205
+ # - `<link></link>`{:.language-html} - link, with the following
206
+ # attributes:
207
+ # - `href="http://example.com"`{:.language-html} --- an external link.
208
+ # Note that you must explicitly underline and color using the
209
+ # appropriate tags if you which to draw attention to the link.
210
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
211
+ # Whether or not to use kerning (if it is available with the current
212
+ # font).
213
+ # @option options :size [Number] (current ofnt size) The font size to use.
214
+ # @option options :color [Color]
215
+ # @option options :character_spacing [Number] (0)
216
+ # The amount of space to add to or remove from the default character
217
+ # spacing.
218
+ # @option options :style [Symbol] (current style)
219
+ # The style to use. The requested style must be part of the current font
220
+ # family.
221
+ # @option options :indent_paragraphs [Number]
222
+ # The amount to indent the first line of each paragraph. Omit this option
223
+ # if you do not want indenting.
224
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
225
+ # Direction of the text.
226
+ # @option options :fallback_fonts [Array<String>]
227
+ # An array of font names. Each name must be the name of an AFM font or the
228
+ # name that was used to register a family of TTF fonts (see
229
+ # {Prawn::Document#font_families}). If present, then each glyph will be
230
+ # rendered using the first font that includes the glyph, starting with the
231
+ # current font and then moving through `:fallback_fonts`.
232
+ # @option option :align [:left, :center, :right, :justify]
233
+ # (:left if direction is :ltr, :right if direction is :rtl)
234
+ # Alignment within the bounding box.
235
+ # @option options :valign [:top, :center, :bottom] (:top)
236
+ # Vertical alignment within the bounding box.
237
+ # @option options :leading (Number) (value of document.default_leading)
238
+ # Additional space between lines.
239
+ # @option options :final_gap [Boolean] (true)
240
+ # If `true`, then the space between each line is included below the last
241
+ # line; otherwise, {Document.y} is placed just below the descender of the
242
+ # last line printed.
243
+ # @option options :mode [Symbol] (:fill)
244
+ # The text rendering mode to use. Use this to specify if the text should
245
+ # render with the fill color, stroke color or both.
246
+ # * `:fill` - fill text (default)
247
+ # * `:stroke` - stroke text
248
+ # * `:fill_stroke` - fill, then stroke text
249
+ # * `:invisible` - invisible text
250
+ # * `:fill_clip` - fill text then add to path for clipping
251
+ # * `:stroke_clip` - stroke text then add to path for clipping
252
+ # * `:fill_stroke_clip` - fill then stroke text, then add to path for
253
+ # clipping
254
+ # * `:clip` - add text to path for clipping
255
+ #
256
+ # @return [void]
257
+ #
258
+ # @raise [ArgumentError] if `:at` option included
259
+ # @raise [Prawn::Errrors::CannotFit] if not wide enough to print any text
260
+ #
261
+ # @see PDF::Core::Text#text_rendering_mode()
262
+ # for a list of valid text rendering modes.
263
+ def formatted_text(array, options = {})
264
+ options = inspect_options_for_text(options.dup)
265
+
266
+ color = options.delete(:color)
267
+ if color
268
+ array =
269
+ array.map { |fragment|
270
+ fragment[:color] ? fragment : fragment.merge(color: color)
271
+ }
272
+ end
273
+
274
+ if @indent_paragraphs
275
+ text_formatter.array_paragraphs(array).each do |paragraph|
276
+ remaining_text = draw_indented_formatted_line(paragraph, options)
277
+
278
+ if @no_text_printed && !@all_text_printed
279
+ @bounding_box.move_past_bottom
280
+ remaining_text = draw_indented_formatted_line(paragraph, options)
281
+ end
282
+
283
+ unless @all_text_printed
284
+ remaining_text = fill_formatted_text_box(remaining_text, options)
285
+ draw_remaining_formatted_text_on_new_pages(remaining_text, options)
286
+ end
287
+ end
288
+ else
289
+ remaining_text = fill_formatted_text_box(array, options)
290
+ draw_remaining_formatted_text_on_new_pages(remaining_text, options)
291
+ end
292
+ end
293
+
294
+ # Draws text on the page, beginning at the point specified by the `:at`
295
+ # option the string is assumed to be pre-formatted to properly fit the page.
296
+ #
297
+ # ```ruby
298
+ # pdf.draw_text "Hello World", at: [100, 100]
299
+ # pdf.draw_text "Goodbye World", at: [50,50], size: 16
300
+ # ```
301
+ #
302
+ # If your font contains kerning pair data that Prawn can parse, the
303
+ # text will be kerned by default. You can disable kerning by including
304
+ # a `false` `:kerning` option. If you want to disable kerning on an
305
+ # entire document, set `default_kerning = false` for that document
306
+ #
307
+ # #### Text Positioning Details
308
+ #
309
+ # Prawn will position your text by the left-most edge of its baseline, and
310
+ # flow along a single line. (This means that `:align` will not work)
311
+ #
312
+ # #### Rotation
313
+ #
314
+ # Text can be rotated before it is placed on the canvas by specifying the
315
+ # `:rotate` option with a given angle. Rotation occurs counter-clockwise.
316
+ #
317
+ # #### Encoding
318
+ #
319
+ # Note that strings passed to this function should be encoded as UTF-8. If
320
+ # you get unexpected characters appearing in your rendered document, check
321
+ # this.
322
+ #
323
+ # If the current font is a built-in one, although the string must be encoded
324
+ # as UTF-8, only characters that are available in WinAnsi are allowed.
325
+ #
326
+ # If an empty box is rendered to your PDF instead of the character you
327
+ # wanted it usually means the current font doesn't include that character.
328
+ #
329
+ # @param text [String]
330
+ # @param options [Hash{Symbol => any}]
331
+ # @option options :at [Array(Number, Number)] **Required**.
332
+ # The position at which to start the text.
333
+ # @option options :kerning [Boolean] (value of default_kerning?)
334
+ # Whether or not to use kerning (if it is available with the current
335
+ # font).
336
+ # @option options :size [Number] (current font size)
337
+ # The font size to use.
338
+ # @option options :style [Symbol] (current style)
339
+ # The style to use. The requested style must be part of the current font
340
+ # family.
341
+ # @option options :rotate [Number] The angle to which to rotate text.
342
+ # @return [void]
343
+ # @raise [ArgumentError]
344
+ # If `:at` option is omitted or `:align</tt> option is included.
345
+ def draw_text(text, options)
346
+ options = inspect_options_for_draw_text(options.dup)
347
+
348
+ # dup because normalize_encoding changes the string
349
+ text = text.to_s.dup
350
+ save_font do
351
+ process_text_options(options)
352
+ text = font.normalize_encoding(text)
353
+ font_size(options[:size]) { draw_text!(text, options) }
354
+ end
355
+ end
356
+
357
+ # Low level text placement method.
358
+ #
359
+ # All font and size alterations should already be set.
360
+ #
361
+ # @param text [String]
362
+ # @param options [Hash{Symbol => any}]
363
+ # @option options :at [Array(Number, Number)]
364
+ # The position at which to start the text.
365
+ # @option options :kerning [Boolean]
366
+ # Whether or not to use kerning (if it is available with the current
367
+ # font).
368
+ # @option options :size [Number]
369
+ # The font size to use.
370
+ # @option options :style [Symbol]
371
+ # The style to use. The requested style must be part of the current font
372
+ # family.
373
+ # @option options :rotate [Number] The angle to which to rotate text.
374
+ # @return [void]
375
+ def draw_text!(text, options)
376
+ unless font.unicode? || font.class.hide_m17n_warning || text.ascii_only?
377
+ warn(
378
+ "PDF's built-in fonts have very limited support for " \
379
+ "internationalized text.\nIf you need full UTF-8 support, " \
380
+ "consider using an external font instead.\n\nTo disable this " \
381
+ "warning, add the following line to your code:\n" \
382
+ "Prawn::Fonts::AFM.hide_m17n_warning = true\n",
383
+ )
384
+
385
+ font.class.hide_m17n_warning = true
386
+ end
387
+
388
+ x, y = map_to_absolute(options[:at])
389
+ add_text_content(text, x, y, options)
390
+ end
391
+
392
+ # Gets height of text in PDF points.
393
+ #
394
+ # @note This method takes the same options as {#text}, _except_
395
+ # `:indent_paragraphs`.
396
+ #
397
+ # @example
398
+ # text_height = height_of("hello\nworld")
399
+ #
400
+ # @param string [String]
401
+ # @param options [Hash{Symbol => any}]
402
+ # @option options :inline_format [Boolean]
403
+ # If `true`, then the string parameter is interpreted as a HTML-esque
404
+ # string that recognizes the following tags (assuming the default text
405
+ # formatter is used):
406
+ # - `<b></b>`{:.language-html} --- bold style.
407
+ # - `<i></i>`{:.language-html} --- italic style.
408
+ # - `<u></u>`{:.language-html} --- underline.
409
+ # - `<strikethrough></strikethrough>`{:.language-html} --- strikethrough.
410
+ # - `<sub></sub>`{:.language-html} --- subscript.
411
+ # - `<sup></sup>`{:.language-html} --- superscript.
412
+ # - `<font></font>`{:.language-html} --- with the following attributes
413
+ # (using double or single quotes):
414
+ # - `name="Helvetica"`{:.language-html} --- the font. The font name must
415
+ # be an AFM font with the desired faces or must be a font that is
416
+ # already registered using {Prawn::Document#font_families}.
417
+ # - `size="24"`{:.language-html} --- attribute for setting size.
418
+ # - `character_spacing="2.5"`{:.language-html} --- character spacing.
419
+ # - `<color></color>`{:.language-html} --- text color
420
+ # - `rgb="ffffff"`{:.language-html} or `rgb="#ffffff"`{:.language-html}
421
+ # --- RGB color
422
+ # - `c="100" m="100" y="100" k="100"`{:.language-html} --- CMYK color
423
+ # - `<link></link>`{:.language-html} - link, with the following
424
+ # attributes:
425
+ # - `href="http://example.com"`{:.language-html} --- an external link.
426
+ # Note that you must explicitly underline and color using the
427
+ # appropriate tags if you which to draw attention to the link.
428
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
429
+ # Whether or not to use kerning (if it is available with the current
430
+ # font).
431
+ # @option options :size [Number] (current ofnt size) The font size to use.
432
+ # @option options :color [Color]
433
+ # @option options :character_spacing [Number] (0)
434
+ # The amount of space to add to or remove from the default character
435
+ # spacing.
436
+ # @option options :style [Symbol] (current style)
437
+ # The style to use. The requested style must be part of the current font
438
+ # family.
439
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
440
+ # Direction of the text.
441
+ # @option options :fallback_fonts [Array<String>]
442
+ # An array of font names. Each name must be the name of an AFM font or the
443
+ # name that was used to register a family of TTF fonts (see
444
+ # {Prawn::Document#font_families}). If present, then each glyph will be
445
+ # rendered using the first font that includes the glyph, starting with the
446
+ # current font and then moving through `:fallback_fonts`.
447
+ # @option option :align [:left, :center, :right, :justify]
448
+ # (:left if direction is :ltr, :right if direction is :rtl)
449
+ # Alignment within the bounding box.
450
+ # @option options :valign [:top, :center, :bottom] (:top)
451
+ # Vertical alignment within the bounding box.
452
+ # @option options :leading (Number) (value of document.default_leading)
453
+ # Additional space between lines.
454
+ # @option options :final_gap [Boolean] (true)
455
+ # If `true`, then the space between each line is included below the last
456
+ # line; otherwise, {Document.y} is placed just below the descender of the
457
+ # last line printed.
458
+ # @option options :mode [Symbol] (:fill)
459
+ # The text rendering mode to use. Use this to specify if the text should
460
+ # render with the fill color, stroke color or both.
461
+ # * `:fill` - fill text (default)
462
+ # * `:stroke` - stroke text
463
+ # * `:fill_stroke` - fill, then stroke text
464
+ # * `:invisible` - invisible text
465
+ # * `:fill_clip` - fill text then add to path for clipping
466
+ # * `:stroke_clip` - stroke text then add to path for clipping
467
+ # * `:fill_stroke_clip` - fill then stroke text, then add to path for
468
+ # clipping
469
+ # * `:clip` - add text to path for clipping
470
+ #
471
+ # @return [void]
472
+ #
473
+ # @raise [ArgumentError] if `:at` option included
474
+ # @raise [Prawn::Errrors::CannotFit] if not wide enough to print any text
475
+ # @raise [NotImplementedError] if `:indent_paragraphs` option included.
476
+ #
477
+ # @see PDF::Core::Text#text_rendering_mode()
478
+ # for a list of valid text rendering modes.
479
+ # @see height_of_formatted
480
+ def height_of(string, options = {})
481
+ height_of_formatted([{ text: string }], options)
482
+ end
483
+
484
+ # Gets height of formatted text in PDF points.
485
+ #
486
+ # @note This method takes the same options as {#text}, _except_
487
+ # `:indent_paragraphs`.
488
+ #
489
+ # @example
490
+ # height_of_formatted([{ :text => "hello" },
491
+ # { :text => "world",
492
+ # :size => 24,
493
+ # :styles => [:bold, :italic] }])
494
+ #
495
+ # @param array [Array<Hash>] text fragments.
496
+ # @param options [Hash{Symbol => any}]
497
+ # @option options :inline_format [Boolean]
498
+ # If `true`, then the string parameter is interpreted as a HTML-esque
499
+ # string that recognizes the following tags (assuming the default text
500
+ # formatter is used):
501
+ # - `<b></b>`{:.language-html} --- bold style.
502
+ # - `<i></i>`{:.language-html} --- italic style.
503
+ # - `<u></u>`{:.language-html} --- underline.
504
+ # - `<strikethrough></strikethrough>`{:.language-html} --- strikethrough.
505
+ # - `<sub></sub>`{:.language-html} --- subscript.
506
+ # - `<sup></sup>`{:.language-html} --- superscript.
507
+ # - `<font></font>`{:.language-html} --- with the following attributes
508
+ # (using double or single quotes):
509
+ # - `name="Helvetica"`{:.language-html} --- the font. The font name must
510
+ # be an AFM font with the desired faces or must be a font that is
511
+ # already registered using {Prawn::Document#font_families}.
512
+ # - `size="24"`{:.language-html} --- attribute for setting size.
513
+ # - `character_spacing="2.5"`{:.language-html} --- character spacing.
514
+ # - `<color></color>`{:.language-html} --- text color
515
+ # - `rgb="ffffff"`{:.language-html} or `rgb="#ffffff"`{:.language-html}
516
+ # --- RGB color
517
+ # - `c="100" m="100" y="100" k="100"`{:.language-html} --- CMYK color
518
+ # - `<link></link>`{:.language-html} - link, with the following
519
+ # attributes:
520
+ # - `href="http://example.com"`{:.language-html} --- an external link.
521
+ # Note that you must explicitly underline and color using the
522
+ # appropriate tags if you which to draw attention to the link.
523
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
524
+ # Whether or not to use kerning (if it is available with the current
525
+ # font).
526
+ # @option options :size [Number] (current ofnt size) The font size to use.
527
+ # @option options :color [Color]
528
+ # @option options :character_spacing [Number] (0)
529
+ # The amount of space to add to or remove from the default character
530
+ # spacing.
531
+ # @option options :style [Symbol] (current style)
532
+ # The style to use. The requested style must be part of the current font
533
+ # family.
534
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
535
+ # Direction of the text.
536
+ # @option options :fallback_fonts [Array<String>]
537
+ # An array of font names. Each name must be the name of an AFM font or the
538
+ # name that was used to register a family of TTF fonts (see
539
+ # {Prawn::Document#font_families}). If present, then each glyph will be
540
+ # rendered using the first font that includes the glyph, starting with the
541
+ # current font and then moving through `:fallback_fonts`.
542
+ # @option option :align [:left, :center, :right, :justify]
543
+ # (:left if direction is :ltr, :right if direction is :rtl)
544
+ # Alignment within the bounding box.
545
+ # @option options :valign [:top, :center, :bottom] (:top)
546
+ # Vertical alignment within the bounding box.
547
+ # @option options :leading (Number) (value of document.default_leading)
548
+ # Additional space between lines.
549
+ # @option options :final_gap [Boolean] (true)
550
+ # If `true`, then the space between each line is included below the last
551
+ # line; otherwise, {Document.y} is placed just below the descender of the
552
+ # last line printed.
553
+ # @option options :mode [Symbol] (:fill)
554
+ # The text rendering mode to use. Use this to specify if the text should
555
+ # render with the fill color, stroke color or both.
556
+ # * `:fill` - fill text (default)
557
+ # * `:stroke` - stroke text
558
+ # * `:fill_stroke` - fill, then stroke text
559
+ # * `:invisible` - invisible text
560
+ # * `:fill_clip` - fill text then add to path for clipping
561
+ # * `:stroke_clip` - stroke text then add to path for clipping
562
+ # * `:fill_stroke_clip` - fill then stroke text, then add to path for
563
+ # clipping
564
+ # * `:clip` - add text to path for clipping
565
+ #
566
+ # @return [void]
567
+ #
568
+ # @raise [ArgumentError] if `:at` option included
569
+ # @raise [Prawn::Errrors::CannotFit] if not wide enough to print any text
570
+ # @raise [NotImplementedError] if `:indent_paragraphs` option included.
571
+ #
572
+ # @see PDF::Core::Text#text_rendering_mode()
573
+ # for a list of valid text rendering modes.
574
+ # @see height_of
575
+ def height_of_formatted(array, options = {})
576
+ if options[:indent_paragraphs]
577
+ raise NotImplementedError,
578
+ ':indent_paragraphs option not available with height_of'
579
+ end
580
+ process_final_gap_option(options)
581
+ box = Text::Formatted::Box.new(
582
+ array,
583
+ options.merge(height: 100_000_000, document: self),
584
+ )
585
+ box.render(dry_run: true)
586
+
587
+ height = box.height
588
+ height += box.line_gap + box.leading if @final_gap
589
+ height
590
+ end
591
+
592
+ private
593
+
594
+ def draw_remaining_formatted_text_on_new_pages(remaining_text, options)
595
+ until remaining_text.empty?
596
+ @bounding_box.move_past_bottom
597
+ previous_remaining_text = remaining_text
598
+ remaining_text = fill_formatted_text_box(remaining_text, options)
599
+ break if remaining_text == previous_remaining_text
600
+ end
601
+ end
602
+
603
+ def draw_indented_formatted_line(string, options)
604
+ gap =
605
+ if options.fetch(:direction, text_direction) == :ltr
606
+ [@indent_paragraphs, 0]
607
+ else
608
+ [0, @indent_paragraphs]
609
+ end
610
+
611
+ indent(*gap) do
612
+ fill_formatted_text_box(string, options.dup.merge(single_line: true))
613
+ end
614
+ end
615
+
616
+ def fill_formatted_text_box(text, options)
617
+ merge_text_box_positioning_options(options)
618
+ box = Text::Formatted::Box.new(text, options)
619
+ remaining_text = box.render
620
+ @no_text_printed = box.nothing_printed?
621
+ @all_text_printed = box.everything_printed?
622
+
623
+ self.y -= box.height
624
+
625
+ # If there's no remaining_text we don't really want to treat this line
626
+ # in a special way, we printed everything we wanted so the special
627
+ # single_line logic should not be triggered here.
628
+ if @final_gap || (options[:single_line] && !@all_text_printed)
629
+ self.y -= box.line_gap + box.leading
630
+ end
631
+
632
+ remaining_text
633
+ end
634
+
635
+ def merge_text_box_positioning_options(options)
636
+ bottom =
637
+ if @bounding_box.stretchy?
638
+ @margin_box.absolute_bottom
639
+ else
640
+ @bounding_box.absolute_bottom
641
+ end
642
+
643
+ options[:height] = y - bottom
644
+ options[:width] = bounds.width
645
+ options[:at] = [
646
+ @bounding_box.left_side - @bounding_box.absolute_left,
647
+ y - @bounding_box.absolute_bottom,
648
+ ]
649
+ end
650
+
651
+ def inspect_options_for_draw_text(options)
652
+ if options[:at].nil?
653
+ raise ArgumentError, 'The :at option is required for draw_text'
654
+ elsif options[:align]
655
+ raise ArgumentError, 'The :align option does not work with draw_text'
656
+ end
657
+
658
+ if options[:kerning].nil?
659
+ options[:kerning] = default_kerning?
660
+ end
661
+ valid_options = PDF::Core::Text::VALID_OPTIONS + %i[at rotate]
662
+ Prawn.verify_options(valid_options, options)
663
+ options
664
+ end
665
+
666
+ def inspect_options_for_text(options)
667
+ if options[:at]
668
+ raise ArgumentError,
669
+ ':at is no longer a valid option with text.' \
670
+ 'use draw_text or text_box instead'
671
+ end
672
+ process_final_gap_option(options)
673
+ process_indent_paragraphs_option(options)
674
+ options[:document] = self
675
+ options
676
+ end
677
+
678
+ def process_final_gap_option(options)
679
+ @final_gap = options[:final_gap].nil? || options[:final_gap]
680
+ options.delete(:final_gap)
681
+ end
682
+
683
+ def process_indent_paragraphs_option(options)
684
+ @indent_paragraphs = options[:indent_paragraphs]
685
+ options.delete(:indent_paragraphs)
686
+ end
687
+
688
+ def move_text_position(amount)
689
+ bottom =
690
+ if @bounding_box.stretchy?
691
+ @margin_box.absolute_bottom
692
+ else
693
+ @bounding_box.absolute_bottom
694
+ end
695
+
696
+ @bounding_box.move_past_bottom if (y - amount) < bottom
697
+
698
+ self.y -= amount
699
+ end
700
+ end
701
+ end