class HexaPDF::Layout::TextLayouter::SimpleLineWrapping


Implementation of a simple line wrapping algorithm.

The algorithm arranges the given items so that the maximum number is put onto each line, taking the differences of Box, Glue and Penalty items into account. It is not as advanced as say Knuth’s line wrapping algorithm in that it doesn’t optimize paragraphs.

Public Class Methods

call(items, width_block, frame = nil) {|line, item| block } → rest

Arranges the items into lines.

The optional frame argument needs to be a Frame object that is used when fitting inline boxes. If not provided, a custom Frame object is used. However, if the items contain inline boxes that need to access a frame’s context object, it is mandatory to provide an appropriate Frame object.

The width_block argument has to be a callable object that returns the width of the line:

  • If the line width doesn’t depend on the height or the vertical position of the line (i.e. fixed line width), the width_block should have an arity of zero. However, this doesn’t mean that the block is called only once; it is actually called before each new line (e.g. for varying line widths that don’t depend on the line height; one common case is the indentation of the first line). This is the general case.

  • However, if lines should have varying widths (e.g. for flowing text around shapes), the width_block argument should be an object responding to call(line_like) where line_like is a Line-like object responding to y_min, y_max and height holding the values for the currently layed out line. The caller is responsible for tracking the height of the already layed out lines. This method involves more work and is therefore slower.

Regardless of whether varying line widths are used or not, each time a line is finished, it is yielded to the caller. The second argument item is the item that caused the line break (e.g. a Box, Glue or Penalty). The return value should be truthy if line wrapping should continue, or falsy if it should stop. If the yielded line is empty and the yielded item is a box item, this single item didn’t fit into the available width; the caller has to handle this situation, e.g. by stopping.

In case of varying widths, the width_block may also return nil in which case the algorithm should revert back to a stored item index and then start as if beginning a new line. Which index to use is told the algorithm through the special return value :store_start_of_line of the yielded-to block. When this return value is used, the current start of the line index should be stored for later use.

After the algorithm is finished, it returns the unused items.

new(items, width_block, frame)

Creates a new line wrapping object that arranges the items on lines with the given width.

Public Instance Methods

fixed_width_wrapping() { |create_line, item| ... }

Peforms line wrapping with a fixed width per line, with line height playing no role.

variable_width_wrapping() { |create_line, item| ... }

Performs the line wrapping with variable widths.