class HexaPDF::Layout::Line

#height
The height of the item.
implemented:
Otherwise (i.e. a vertical alignment different from :text), the following method must be
#y_max
The maximum y-coordinate of the item.
#y_min
The minimum y-coordinate of the item.
methods:
If an item has a vertical alignment of :text, it additionally has to respond to the following
#draw(canvas, x, y)
Should draw the item onto the canvas at the position (x, y).
#valign
The vertical alignment of the item (see above).
#width
The width of the item.
#x_max
The maximum x-coordinate of the item.
#x_min

The minimum x-coordinate of the item.
Each item of a line fragment has to respond to the following methods:
== Item Requirements
fragments, e.g. graphical representation of characters (think: emoji fonts).
This value may be used by other objects if they should be handled similar to text
line’s #text_y_min and #text_y_max.
on the baseline and its minimum and maximum y-coordinates are used when calculating the
This is a special alignment value for text fragment objects. The text fragment is aligned
:text::
Align the bottom of the box with the bottom of the Line.
:bottom::
Align the top of the box with the top of the Line.
:top::
Align the bottom of the box with the baseline of the Line.
:baseline::
Align the bottom of the box with the bottom of the text of the Line.
:text_bottom::
Align the top of the box with the top of the text of the Line.
:text_top::
baseline. The vertical alignment is determined by the value of the #valign method:
The items of a line fragment are aligned along the x-axis which coincides with the text
A Line describes a line of text and can contain TextFragment objects or InlineBox objects.

def add(item)

Note: The cache is not cleared!

attributes, they are combined.
If both the item and the last item in the item list are TextFragment objects with the same

Adds the given item at the end of the item list.
def add(item)
  last = @items.last
  if last.instance_of?(item.class) && item.kind_of?(TextFragment) &&
      last.attributes_hash == item.attributes_hash
    if last.items.frozen?
      @items[-1] = last = last.dup
      last.items = last.items.dup
    end
    last.items[last.items.length, 0] = item.items
    last.clear_cache
  else
    @items << item
  end
  self
end

def calculate_y_dimensions

example, it depends on the order of the calculations in part 3.
In certain cases there is no unique solution to the values of #y_min and #y_max, for

:bottom added to #y_min, or the temporary #y_max, whichever is larger.
Calculate the final #y_max by using either the maximum height of all items with valign

:top subtracted from the temporary #y_min, or the temporary #y_min, whichever is smaller.
3. Calculate the final #y_min by using either the maximum height of all items with valign

:baseline, or #text_y_max, whichever is larger.
:text_bottom added to #text_y_min, or the maximum height of all items with valign
For the temporary #y_max, use either the maximum height of all items with valign equal to

valign :text_top subtraced from #text_y_max, or #text_y_min, whichever is smaller.
2. Calculate the temporary #y_min by using either the maximum height of all items with

1. Calculate #text_y_min and #text_y_max by using only the items with valign :text.

The following algorithm is used for the calculations:

Calculates all y-values and returns them as array.

line.calculate_y_dimensions -> [y_min, y_max, text_y_min, text_y_max]
:call-seq:
def calculate_y_dimensions
  @y_min, @y_max, @text_y_min, @text_y_max = HeightCalculator.new(@items).result
end

def clear_cache

This method needs to be called if the line's items are changed!

Clears all cached values.

line.clear_cache -> line
:call-seq:
def clear_cache
  @x_max = @y_min = @y_max = @text_y_min = @text_y_max = @width = nil
  self
end

def each

baseline.
Yields each item together with its horizontal offset from 0 and vertical offset from the

line.each {|item, x, y| block }
:call-seq:
def each
  x = 0
  @items.each do |item|
    y = case item.valign
        when :text, :baseline then 0
        when :top then y_max - item.height
        when :text_top then text_y_max - item.height
        when :text_bottom then text_y_min
        when :bottom then y_min
        else
          raise HexaPDF::Error, "Unknown inline box alignment #{item.valign}"
        end
    yield(item, x, y)
    x += item.width
  end
end

def height

The height of the line fragment.
def height
  y_max - y_min
end

def ignore_justification!

Specifies that this line should not be justified if line justification is used.
def ignore_justification!
  @ignore_justification = true
end

def ignore_justification?

Returns +true+ if justification should be ignored for this line.
def ignore_justification?
  defined?(@ignore_justification) && @ignore_justification
end

def initialize(items = [])

Creates a new Line object, adding all given items to it.
def initialize(items = [])
  @items = []
  items.each {|i| add(i) }
  @x_offset = 0
  @y_offset = 0
end

def text_y_max

The maximum y-coordinate of any TextFragment item of the line.
def text_y_max
  @text_y_max ||= calculate_y_dimensions[3]
end

def text_y_min

The minimum y-coordinate of any TextFragment item of the line.
def text_y_min
  @text_y_min ||= calculate_y_dimensions[2]
end

def width

The width of the line fragment.
def width
  @width ||= @items.sum(&:width)
end

def x_max

The maximum x-coordinate of the whole line.
def x_max
  @x_max ||= width + (items[-1].x_max - items[-1].width)
end

def x_min

The minimum x-coordinate of the whole line.
def x_min
  @items[0].x_min
end

def y_max

It is always greater than or equal to zero.

The maximum y-coordinate of any item of the line.
def y_max
  @y_max ||= calculate_y_dimensions[1]
end

def y_min

It is always lower than or equal to zero.

The minimum y-coordinate of any item of the line.
def y_min
  @y_min ||= calculate_y_dimensions[0]
end