Class: Prawn::Text::Formatted::Box

Inherits:
Object
  • Object
show all
Defined in:
lib/prawn/text/formatted/box.rb

Overview

Formatted text box.

Generally, one would use the #formatted_text_box convenience method. However, using Text::Formatted::Box.new in conjunction with #render(dry_run: true) enables one to do calculations prior to placing text on the page, or to determine how much vertical space was consumed by the printed text

Direct Known Subclasses

Box

Experimental API collapse

Experimental API collapse

Extension API collapse

Constructor Details

#initialize(formatted_text, options = {}) ⇒ Box

See Prawn::Text#text_box for valid options

Parameters:

  • formatted_text (Array<Hash{Symbol => any}>)

    Formatted text is an array of hashes, where each hash defines text and format information. The following hash options are supported:

    • :text — the text to format according to the other hash options.
    • :styles — an array of styles to apply to this text. Available styles include :bold, :italic, :underline, :strikethrough, :subscript, and :superscript.
    • :size —a number denoting the font size to apply to this text.
    • :character_spacing — a number denoting how much to increase or decrease the default spacing between characters.
    • :font — the name of a font. The name must be an AFM font with the desired faces or must be a font that is already registered using Document#font_families.
    • :color — anything compatible with Graphics::Color#fill_color and Graphics::Color#stroke_color.
    • :link` — a URL to which to create a link. A clickable link will be created to that URL. Note that you must explicitly underline and color using the appropriate tags if you which to draw attention to the link.
    • :anchor — a destination that has already been or will be registered using PDF::Core::Destinations#add_dest. A clickable link will be created to that destination. Note that you must explicitly underline and color using the appropriate tags if you which to draw attention to the link.
    • :local — a file or application to be opened locally. A clickable link will be created to the provided local file or application. If the file is another PDF, it will be opened in a new window. Note that you must explicitly underline and color using the appropriate options if you which to draw attention to the link.
    • :draw_text_callback — if provided, this Proc will be called instead of Document#draw_text! once per fragment for every low-level addition of text to the page.
    • :callback — an object (or array of such objects) with two methods: render_behind and render_in_front, which are called immediately prior to and immediately after rendering the text fragment and which are passed the fragment as an argument.
  • options (Hash{Symbol => any}) (defaults to: {})
  • option (Hash)

    a customizable set of options

Options Hash (options):

  • :document (Prawn::Document)

    Owning document.

  • :kerning (Boolean) — default: value of document.default_kerning?

    Whether or not to use kerning (if it is available with the current font).

  • :size (Number) — default: current font size

    The font size to use.

  • :character_spacing (Number) — default: 0

    The amount of space to add to or remove from the default character spacing.

  • :disable_wrap_by_char (Boolean) — default: false

    Whether or not to prevent mid-word breaks when text does not fit in box.

  • :mode (Symbol) — default: :fill

    The text rendering mode. See documentation for Document#text_rendering_mode for a list of valid options.

  • :width (Number) — default: bounds.right - at[0]

    The width of the box.

  • :height (Number) — default: default_height()

    The height of the box.

  • :direction (:ltr, :rtl) — default: value of document.text_direction

    Direction of the text (left-to-right or right-to-left).

  • :fallback_fonts (Array<String>)

    An array of font names. Each name must be the name of an AFM font or the name that was used to register a family of external fonts (see Document#font_families). If present, then each glyph will be rendered using the first font that includes the glyph, starting with the current font and then moving through :fallback_fonts.

  • :align (:left, :center, :right, :justify) — default: :left if direction is :ltr, :right if direction is :rtl

    Alignment within the bounding box.

  • :valign (:top, :center, :bottom) — default: :top

    Vertical alignment within the bounding box.

  • :rotate (Number)

    The angle to rotate the text.

  • :rotate_around (Object)

    [:center, :upper_left, :upper_right, :lower_right, :lower_left] (:upper_left) The point around which to rotate the text.

  • :leading (Number) — default: value of document.default_leading

    Additional space between lines.

  • :single_line (Boolean) — default: false

    If true, then only the first line will be drawn.

  • :overflow (:truncate, :shrink_to_fit, :expand) — default: :truncate

    This controls the behavior when the amount of text exceeds the available space.

  • :min_font_size (Number) — default: 5

    The minimum font size to use when :overflow is set to :shrink_to_fit (that is the font size will not be reduced to less than this value, even if it means that some text will be cut off).

Source Code
lib/prawn/text/formatted/box.rb, line 173
173
def initialize(formatted_text, options = {})
174
  @inked = false
175
  Prawn.verify_options(valid_options, options)
176
  options = options.dup
177
178
  self.class.extensions.reverse_each { |e| extend(e) }
179
180
  @overflow = options[:overflow] || :truncate
181
  @disable_wrap_by_char = options[:disable_wrap_by_char]
182
183
  self.original_text = formatted_text
184
  @text = nil
185
186
  @document = options[:document]
187
  @direction = options[:direction] || @document.text_direction
188
  @fallback_fonts = options[:fallback_fonts] ||
189
    @document.fallback_fonts
190
  @at = (
191
    options[:at] || [@document.bounds.left, @document.bounds.top]
192
  ).dup
193
  @width = options[:width] ||
194
    (@document.bounds.right - @at[0])
195
  @height = options[:height] || default_height
196
  @align = options[:align] ||
197
    (@direction == :rtl ? :right : :left)
198
  @vertical_align = options[:valign] || :top
199
  @leading = options[:leading] || @document.default_leading
200
  @character_spacing = options[:character_spacing] ||
201
    @document.character_spacing
202
  @mode = options[:mode] || @document.text_rendering_mode
203
  @rotate = options[:rotate] || 0
204
  @rotate_around = options[:rotate_around] || :upper_left
205
  @single_line = options[:single_line]
206
  @draw_text_callback = options[:draw_text_callback]
207
208
  # if the text rendering mode is :unknown, force it back to :fill
209
  if @mode == :unknown
210
    @mode = :fill
211
  end
212
213
  if @overflow == :expand
214
    # if set to expand, then we simply set the bottom
215
    # as the bottom of the document bounds, since that
216
    # is the maximum we should expand to
217
    @height = default_height
218
    @overflow = :truncate
219
  end
220
  @min_font_size = options[:min_font_size] || 5
221
  if options[:kerning].nil?
222
    options[:kerning] = @document.default_kerning?
223
  end
224
  @options = {
225
    kerning: options[:kerning],
226
    size: options[:size],
227
    style: options[:style],
228
  }
229
230
  super(formatted_text, options)
231
end

Instance Attribute Details

#ascenderNumber (readonly)

The height of the ascender of the last line printed.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 56
56
def ascender
57
  @ascender
58
end

#atArray(Number, Number) (readonly)

The upper left corner of the text box.

Returns:

  • (Array(Number, Number))
Source Code
lib/prawn/text/formatted/box.rb, line 48
48
def at
49
  @at
50
end

#descenderNumber (readonly)

The height of the descender of the last line printed.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 60
60
def descender
61
  @descender
62
end

#leadingNumber (readonly)

The leading used during printing.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 64
64
def leading
65
  @leading
66
end

#line_heightNumber (readonly)

The line height of the last line printed.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 52
52
def line_height
53
  @line_height
54
end

#textArray<Hash> (readonly)

The text that was successfully printed (or, if :dry_run was used, the text that would have been successfully printed).

Returns:

  • (Array<Hash>)
Source Code
lib/prawn/text/formatted/box.rb, line 28
28
def text
29
  @text
30
end

Class Method Details

.extensionsArray<Module>

Text box extensions.

Example:

module MyWrap
  def wrap(array)
    initialize_wrap([{ text: 'all your base are belong to us' }])
    @line_wrap.wrap_line(
      document: @document,
      kerning: @kerning,
      width: 10000,
      arranger: @arranger
    )
    fragment = @arranger.retrieve_fragment
    format_and_draw_fragment(fragment, 0, @line_wrap.width, 0)
    []
  end
end

Prawn::Text::Formatted::Box.extensions << MyWrap

box = Prawn::Text::Formatted::Box.new('hello world')
box.render("why can't I print anything other than" +
           '"all your base are belong to us"?')

See Wrap for what is required of the wrap method if you want to override the default wrapping algorithm.

Returns:

  • (Array<Module>)
Source Code
lib/prawn/text/formatted/box.rb, line 391
391
def self.extensions
392
  @extensions ||= []
393
end

Instance Method Details

#available_widthNumber

The width available at this point in the box.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 285
285
def available_width
286
  @width
287
end

#everything_printed?Boolean

True if everything printed (or, if :dry_run was used, everything would have been successfully printed).

Returns:

  • (Boolean)
Source Code
lib/prawn/text/formatted/box.rb, line 42
42
def everything_printed?
43
  @everything_printed
44
end

#heightNumber

The height actually used during the previous #render.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 292
292
def height
293
  return 0 if @baseline_y.nil? || @descender.nil?
294
295
  (@baseline_y - @descender).abs
296
end

#line_gapNumber

Gap between adjacent lines of text.

Returns:

  • (Number)
Source Code
lib/prawn/text/formatted/box.rb, line 69
69
def line_gap
70
  line_height - (ascender + descender)
71
end

#nothing_printed?Boolean

True if nothing printed (or, if :dry_run was used, nothing would have been successfully printed).

Returns:

  • (Boolean)
Source Code
lib/prawn/text/formatted/box.rb, line 34
34
def nothing_printed?
35
  @nothing_printed
36
end

#render(flags = {}) ⇒ Array<Hash>

Render text to the document based on the settings defined in constructor.

In order to facilitate look-ahead calculations, this method accepts a dry_run: true option. If provided, then everything is executed as if rendering, with the exception that nothing is drawn on the page. Useful for look-ahead computations of height, unprinted text, etc.

Parameters:

  • flags (Hash{Symbol => any}) (defaults to: {})

Options Hash (flags):

  • :dry_run (Boolean) — default: false

    Do not draw the text. Everything else is done.

Returns:

  • (Array<Hash>)

    A formatted text array representing any text that did not print under the current settings.

Raises:

  • (Prawn::Text::Formatted::Arranger::BadFontFamily)

    If no font family is defined for the current font.

  • (Prawn::Errors::CannotFit)

    If not wide enough to print any text.

Source Code
lib/prawn/text/formatted/box.rb, line 251
251
def render(flags = {})
252
  unprinted_text = []
253
254
  @document.save_font do
255
    @document.character_spacing(@character_spacing) do
256
      @document.text_rendering_mode(@mode) do
257
        process_options
258
259
        text = normalized_text(flags)
260
261
        @document.font_size(@font_size) do
262
          shrink_to_fit(text) if @overflow == :shrink_to_fit
263
          process_vertical_alignment(text)
264
          @inked = true unless flags[:dry_run]
265
          unprinted_text =
266
            if @rotate != 0 && @inked
267
              render_rotated(text)
268
            else
269
              wrap(text)
270
            end
271
          @inked = false
272
        end
273
      end
274
    end
275
  end
276
277
  unprinted_text.map do |e|
278
    e.merge(text: @document.font.to_utf8(e[:text]))
279
  end
280
end