Class: HexaPDF::Layout::TextBox

Inherits:
Box
  • Object
show all
Defined in:
lib/hexapdf/layout/text_box.rb

Overview

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.

Instance Attribute Summary

Attributes inherited from Box

#height, #properties, #style, #width

Instance Method Summary collapse

Methods inherited from Box

#content_height, #content_width, create, #draw, #split_box?

Constructor Details

#initialize(items:, **kwargs) ⇒ TextBox

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



50
51
52
53
54
55
# File 'lib/hexapdf/layout/text_box.rb', line 50

def initialize(items:, **kwargs)
  super(**kwargs)
  @tl = TextLayouter.new(style)
  @items = items
  @result = nil
end

Instance Method Details

#empty?Boolean

:nodoc:

Returns:

  • (Boolean)


127
128
129
# File 'lib/hexapdf/layout/text_box.rb', line 127

def empty?
  super && (!@result || @result.lines.empty?)
end

#fit(available_width, available_height, frame) ⇒ Object

Fits the text box into the Frame.

Depending on the ‘position’ style property, the text is either fit into the current region of the frame using available_width and available_height, or fit to the shape of the frame starting from the top (when ‘position’ is set to :flow).

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.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/hexapdf/layout/text_box.rb', line 78

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.shape.bbox.height,
                      apply_first_text_indent: !split_box?, frame: frame)
            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, apply_first_text_indent: !split_box?, frame: frame)
            end
  @width += if @initial_width > 0 || style.text_align == :center || style.text_align == :right
              width
            else
              @result.lines.max_by(&:width)&.width || 0
            end
  @height += if @initial_height > 0 || style.text_valign == :center || style.text_valign == :bottom
               height
             else
               @result.height
             end
  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) ⇒ Object

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



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/hexapdf/layout/text_box.rb', line 111

def split(available_width, available_height, frame)
  fit(available_width, available_height, frame) unless @result

  if style.position != :flow && (float_compare(@width, available_width) > 0 ||
                                 float_compare(@height, available_height) > 0)
    [nil, self]
  elsif @result.remaining_items.empty?
    [self]
  elsif @result.lines.empty?
    [nil, self]
  else
    [self, create_box_for_remaining_items]
  end
end

#supports_position_flow?Boolean

Returns true as the ‘position’ style property value :flow is supported.

Returns:

  • (Boolean)


65
66
67
# File 'lib/hexapdf/layout/text_box.rb', line 65

def supports_position_flow?
  true
end

#textObject

Returns the text that will be drawn.

This will ignore any inline boxes or kerning values.



60
61
62
# File 'lib/hexapdf/layout/text_box.rb', line 60

def text
  @items.map {|item| item.kind_of?(TextFragment) ? item.text : '' }.join
end