class HexaPDF::Layout::TextBox

A TextBox is used for drawing text, either inside a rectangular box or by flowing it around objects of a Frame.

This class uses TextLayouter behind the scenes to do the hard work.

Public Class Methods

new(items, **kwargs) click to toggle source

Creates a new TextBox object with the given inline items (e.g. TextFragment and InlineBox objects).

Calls superclass method HexaPDF::Layout::Box::new
# File lib/hexapdf/layout/text_box.rb, line 49
def initialize(items, **kwargs)
  super(**kwargs)
  @tl = TextLayouter.new(style)
  @items = items
  @result = nil
end

Public Instance Methods

fit(available_width, available_height, frame) click to toggle source

Fits the text box into the Frame.

Depending on the 'position' style property, the text is either fit into the rectangular area given by available_width and available_height, or fit to the outline of the frame starting from the top.

The spacing after the last line can be controlled via the style property last_line_gap.

Also see TextLayouter#style for other style properties taken into account.

# File lib/hexapdf/layout/text_box.rb, line 65
def fit(available_width, available_height, frame)
  return false if (@initial_width > 0 && @initial_width > available_width) ||
    (@initial_height > 0 && @initial_height > available_height)

  @width = @height = 0
  @result = if style.position == :flow
              @tl.fit(@items, frame.width_specification, frame.contour_line.bbox.height)
            else
              @width = reserved_width
              @height = reserved_height
              width = (@initial_width > 0 ? @initial_width : available_width) - @width
              height = (@initial_height > 0 ? @initial_height : available_height) - @height
              @tl.fit(@items, width, height)
            end
  @width += (@initial_width > 0 ? width : @result.lines.max_by(&:width)&.width || 0)
  @height += (@initial_height > 0 ? height : @result.height)
  if style.last_line_gap && @result.lines.last
    @height += style.line_spacing.gap(@result.lines.last, @result.lines.last)
  end

  @result.status == :success
end
split(available_width, available_height, frame) click to toggle source

Splits the text box into two boxes if necessary and possible.

# File lib/hexapdf/layout/text_box.rb, line 89
def split(available_width, available_height, frame)
  fit(available_width, available_height, frame) unless @result
  if @width > available_width || @height > available_height
    [nil, self]
  elsif @result.remaining_items.empty?
    [self]
  elsif @result.lines.empty?
    [nil, self]
  else
    box = clone
    box.instance_variable_set(:@result, nil)
    box.instance_variable_set(:@items, @result.remaining_items)
    [self, box]
  end
end