class HexaPDF::Layout::Frame

Included Modules

A Frame describes the available space for placing boxes and provides additional methods for calculating the needed information for the actual placement.


After a Frame object is initialized, it is ready for fitting boxes in it and drawing them.

The explicit way of drawing a box follows these steps:

  • Call fit with the box to see if the box can fit into the currently selected region of available space. If fitting is successful, the box can be drawn using draw.

    The method fit is also called for absolutely positioned boxes but since these boxes are not subject to the normal constraints, the provided available width and height are the width and height inside the frame to the right and top of the bottom-left corner of the box.

  • If the box didn’t fit, call find_next_region to determine the next region for placing the box. If a new region was found, start over with fit. Otherwise the frame has no more space for placing boxes.

  • Alternatively to calling find_next_region it is also possible to call split. This method tries to split the box into two so that the first part fits into the current region. If splitting is successful, the first box can be drawn (Make sure that the second box is handled correctly). Otherwise, start over with find_next_region.

Used Box Properties

The style properties ‘position’, ‘align’, ‘valign’, ‘margin’ and ‘mask_mode’ are taken into account when fitting, splitting or drawing a box. Note that the margin is ignored if a box’s side coincides with the frame’s original boundary.

Frame Shape

A frame’s shape is used to determine the available space for laying out boxes.

Initially, a frame has a rectangular shape. However, once boxes are added and the frame’s available area gets reduced, a frame may have a polygon set consisting of arbitrary rectilinear polygons as shape.

It is also possible to provide a different initial shape on initialization.



The available height of the current region for placing a box.

Also see the note in the x documentation for further information.


The available width of the current region for placing a box.

Also see the note in the x documentation for further information.


The y-coordinate of the bottom-left corner.


The context object (a HexaPDF::Type::Page or HexaPDF::Type::Form) for which this frame should be used.


The height of the frame.


The x-coordinate of the bottom-left corner.


An array of box objects representing the parent boxes.

The immediate parent is the last array entry, the top-most parent the first one. All boxes that are fitted into this frame have to be child boxes of the immediate parent box.


The shape of the frame, either a Geom2D::Rectangle in the simple case or a Geom2D::PolygonSet consisting of rectilinear polygons in the more complex case.


The width of the frame.


The x-coordinate where the next box will be placed.

Note: Since the algorithm for drawing takes the margin of a box into account, the actual x-coordinate (and y-coordinate, available width and available height) might be different.


The y-coordinate where the next box will be placed.

Also see the note in the x documentation for further information.

Public Class Methods

new(left, bottom, width, height, shape: nil, context: nil, parent_boxes: [])

Creates a new Frame object for the given rectangular area.

Public Instance Methods

child_frame(*init_args, shape: nil, box: nil)

Creates a new Frame object based on this one.

If the init_args arguments are provided, a new Frame is created using the constructor. The optional shape argument is then also passed to the constructor.

Otherwise, this frame is duplicated. This kind of invocation is only useful if the box argument is provided (because otherwise there would be no difference to this frame).

The box argument can be used to add the appropriate parent box to the list of parent_boxes for the newly created frame.


Returns the HexaPDF::Document instance (through context) that is associated with this Frame object or nil if no context object has been set.

draw(canvas, fit_result)

Draws the box of the given Box::FitResult onto the canvas at the fitted position.

After a box is successfully drawn, the frame’s shape is adjusted to remove the occupied area.


Finds the next region for placing boxes. Returns false if no useful region was found.

This method should be called after fitting or drawing a box was not successful. It finds a different region on each invocation. So if a box doesn’t fit into the first region, this method should be called again to find another region and to try again.

The first tried region starts at the top-most, left-most vertex of the polygon and uses the maximum width. The next tried region uses the maximum height. If both don’t work, part of the frame’s shape is removed to try again.


Fits the given box into the current region of available space and returns the associated Box::FitResult object.

Fitting a box takes the style properties ‘position’, ‘align’, ‘valign’, ‘margin’, and ‘mask_mode’ into account.

Use the Box::FitResult#success? method to determine whether fitting was successful.


Returns true if the frame has no more space left.


Removes the given rectilinear polygon from the frame’s shape.


Tries to split the box of the given Box::FitResult into two parts and returns both parts.

See Box#split for further details.

width_specification(offset = 0)

Returns a width specification for the frame’s shape that can be used, for example, with TextLayouter.

Since not all text may start at the top of the frame, the offset argument can be used to specify a vertical offset from the top of the frame where layouting should start.

To be compatible with TextLayouter, the top-left corner of the bounding box of the frame’s shape is the origin of the coordinate system for the width specification, with positive x-values to the right and positive y-values downwards.

Depending on the complexity of the frame, the result may be any of the allowed width specifications of TextLayouter#fit.