Generally, one would use the text_box convenience method. However, using ::new in conjunction with render() enables one to do look-ahead calculations prior to placing text on the page, or to determine how much vertical space was consumed by the printed text
The height of the ascender of the last line printed
The upper left corner of the text box
The height of the descender of the last line printed
The leading used during printing
The line height of the last line printed
The text that was successfully printed (or, if dry_run
was
used, the test that would have been successfully printed)
See Prawn::Text#text_box for valid options
# File lib/prawn/text/box.rb, line 127 def initialize(string, options={}) @inked = false Prawn.verify_options(VALID_OPTIONS, options) options = options.dup @overflow = options[:overflow] || :truncate @original_string = string @text = nil @document = options[:document] @at = options[:at] || [@document.bounds.left, @document.bounds.top] @width = options[:width] || @document.bounds.right - @at[0] @height = options[:height] || @at[1] - @document.bounds.bottom @align = options[:align] || :left @vertical_align = options[:valign] || :top @leading = options[:leading] || 0 @rotate = options[:rotate] || 0 @rotate_around = options[:rotate_around] || :upper_left @single_line = options[:single_line] @skip_encoding = options[:skip_encoding] || @document.skip_encoding if @overflow == :expand # if set to expand, then we simply set the bottom # as the bottom of the document bounds, since that # is the maximum we should expand to @height = @at[1] - @document.bounds.bottom @overflow = :truncate end @min_font_size = options[:min_font_size] || 5 @line_wrap = options [:line_wrap] || @document.default_line_wrap @options = @document.text_options.merge(:kerning => options[:kerning], :size => options[:size], :style => options[:style]) end
The height actually used during the previous render
# File lib/prawn/text/box.rb, line 202 def height return 0 if @baseline_y.nil? || @descender.nil? # baseline is already pushed down one line below the current # line, so we need to subtract line line_height and leading, # but we need to add in the descender since baseline is # above the descender @baseline_y.abs + @descender - @line_height - @leading end
Render text to the document based on the settings defined in initialize.
In order to facilitate look-ahead calculations, render
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.
Returns any text that did not print under the current settings
# File lib/prawn/text/box.rb, line 174 def render(flags={}) # dup because normalize_encoding changes the string string = @original_string.dup unprinted_text = '' @document.save_font do process_options unless @skip_encoding @document.font.normalize_encoding!(string) end @document.font_size(@font_size) do shrink_to_fit(string) if @overflow == :shrink_to_fit process_vertical_alignment(string) @inked = true unless flags[:dry_run] if @rotate != 0 && @inked unprinted_text = render_rotated(string) else unprinted_text = _render(string) end @inked = false end end unprinted_text end
# File lib/prawn/text/box.rb, line 270 def _render(remaining_text) @line_height = @document.font.height @descender = @document.font.descender @ascender = @document.font.ascender @baseline_y = -@ascender printed_text = [] while remaining_text && remaining_text.length > 0 && @baseline_y.abs + @descender <= @height line_to_print = @line_wrap.wrap_line(remaining_text.first_line, :document => @document, :kerning => @kerning, :size => @font_size, :width => @width) if line_to_print.empty? && remaining_text.length > 0 raise Errors::CannotFit end remaining_text = remaining_text.slice(line_to_print.length.. remaining_text.length) print_ellipses = (@overflow == :ellipses && last_line? && remaining_text.length > 0) printed_text << print_line(line_to_print, print_ellipses) @baseline_y -= (@line_height + @leading) break if @single_line end @text = printed_text.join("\n") if @inked remaining_text end
# File lib/prawn/text/box.rb, line 337 def insert_ellipses(line_to_print) if @document.width_of(line_to_print + "...", :kerning => @kerning) < @width line_to_print.insert(-1, "...") else line_to_print[-3..-1] = "..." if line_to_print.length > 3 end end
# File lib/prawn/text/box.rb, line 333 def last_line? @baseline_y.abs + @descender > @height - @line_height end
# File lib/prawn/text/box.rb, line 305 def print_line(line_to_print, print_ellipses) # strip so that trailing and preceding white space don't # interfere with alignment line_to_print.strip! insert_ellipses(line_to_print) if print_ellipses case(@align) when :left x = @at[0] when :center line_width = @document.width_of(line_to_print, :kerning => @kerning) x = @at[0] + @width * 0.5 - line_width * 0.5 when :right line_width = @document.width_of(line_to_print, :kerning => @kerning) x = @at[0] + @width - line_width end y = @at[1] + @baseline_y if @inked @document.draw_text!(line_to_print, :at => [x, y], :size => @font_size, :kerning => @kerning) end line_to_print end
# File lib/prawn/text/box.rb, line 235 def process_options # must be performed within a save_font bock because # document.process_text_options sets the font @document.process_text_options(@options) @font_size = @options[:size] @kerning = @options[:kerning] end
# File lib/prawn/text/box.rb, line 213 def process_vertical_alignment(string) return if @vertical_align == :top _render(string) case @vertical_align when :center @at[1] = @at[1] - (@height - height) * 0.5 when :bottom @at[1] = @at[1] - (@height - height) end @height = height end
# File lib/prawn/text/box.rb, line 243 def render_rotated(string) unprinted_text = '' case @rotate_around when :center x = @at[0] + @width * 0.5 y = @at[1] - @height * 0.5 when :upper_right x = @at[0] + @width y = @at[1] when :lower_right x = @at[0] + @width y = @at[1] - @height when :lower_left x = @at[0] y = @at[1] - @height else x = @at[0] y = @at[1] end @document.rotate(@rotate, :origin => [x, y]) do unprinted_text = _render(string) end unprinted_text end
Decrease the font size until the text fits or the min font size is reached
# File lib/prawn/text/box.rb, line 227 def shrink_to_fit(string) while (unprinted_text = _render(string)).length > 0 && @font_size > @min_font_size @font_size -= 0.5 @document.font_size = @font_size end end