class HexaPDF::Layout::TextLayouter


Arranges text and inline objects into lines according to a specified width and height as well as other options.


  • Existing line breaking characters inside of TextFragment objects are respected when fitting text. If this is not wanted, they have to be removed beforehand.

  • The first line of each paragraph may be indented by setting Style#text_indent which may also be negative.

  • Text can be fitted into arbitrarily shaped areas, even containing holes.

Layouting Algorithm

Laying out text consists of three phases:

  1. The items are broken into pieces which are wrapped into Box, Glue or Penalty objects. Additional Penalty objects marking line breaking opportunities are inserted where needed. This step is done by the SimpleTextSegmentation module.

  2. The pieces are arranged into lines using a very simple algorithm that just puts the maximum number of consecutive pieces into each line. This step is done by the SimpleLineWrapping module.

  3. The lines of step two may actually not be whole lines but line fragments if the area has holes or other discontinuities. The fit method deals with those so that the line wrapping algorithm can be separate.



A dummy line class for use with variable width wrapping, and Style#line_spacing methods in case a line actually consists of multiple line fragments.


Public Class Methods

new(style =

Creates a new TextLayouter object with the given style.

The style argument can either be a Style object or a hash of style options. See style for the properties that are used by the layouter.

Public Instance Methods

fit(items, width, height, apply_first_text_indent: true) → result

Fits the items into the given area and returns a Result object with all the information.

The height argument is just a number specifying the maximum height that can be used.

The width argument can be one of the following:

**a number**

In this case the layed out lines have this number as maximum width. This is the standard case and means that the area in which the text is layed out is a rectangle.

**an array with an even number of numbers**

The array has to be of the form [offset, width, offset, width, …], so the even indices specify offsets (relative to the current position, not absolute offsets from the left), the odd indices widths. This allows laying out lines containing holes in them.

A simple example: [15, 100, 30, 40]. This means that a space of 15 on the left is never used, then comes text with a maximum width of 100, starting at the absolute offset 15, followed by a hole with a width of 30 and then text again with a width of 40, starting at the absolute offset 145 (=15 + 100 + 30).

**an object responding to call(height, line_height)**

The provided argument height is the bottom of last line (or 0 in case of the first line) and line_height is the height of the line to be layed out. The return value has to be of one of the forms above (i.e. a single number or an array of numbers) and should describe the area given these height restrictions.

This allows laying out text inside complex, arbitrarily formed shapes and can be used, for example, for flowing text around objects.

The text segmentation algorithm specified via style is applied to the items in case they are not already in segmented form. This also means that Result#remaining_items always contains segmented items.

Optional arguments:


Specifies whether style.text_indent should be applied to the first line. This should be set to false if the items start with a continuation of a paragraph instead of starting a new paragraph (e.g. after a page break).


If used with the document layout functionality, this should be the frame into which the text is laid out.