class HexaPDF::Composer


The composer class can be used to create PDF documents from scratch. It uses Frame and Box objects underneath.


First, a new Composer objects needs to be created, either using ::new or the utility method ::create.

On creation a HexaPDF::Document object is created as well the first page and an accompanying HexaPDF::Layout::Frame object. The frame is used by the various methods for general document layout tasks, like positioning of text, images, and so on. By default, it covers the whole page except the margin area. How the frame gets created can be customized by overriding the create_frame method.

Once the Composer object is created, its methods can be used to draw text, images, … on the page. Behind the scenes HexaPDF::Layout::Box (and subclass) objects are created and drawn on the page via the frame.

The base style that is used by all these boxes can be defined using the base_style method which returns a HexaPDF::Layout::Style object. The only style property that is set by default is the font (Times) because otherwise there would be problems with text drawing operations (font is the only style property that has no valid default value).

If the frame of a page is full and a box doesn't fit anymore, a new page is automatically created. The box is either split into two boxes where one fits on the first page and the other on the new page, or it is drawn completely on the new page. A new page can also be created by calling the new_page method.

The x and y methods provide the point where the next box would be drawn if it fits the available space. This information can be used, for example, for custom drawing operations through canvas which provides direct access to the HexaPDF::Content::Canvas object of the current page.

When using canvas and modifying the graphics state, care has to be taken to avoid problems with later box drawing operations since the graphics state cannot completely be reset (e.g. transformations of the canvas cannot always be undone). So it is best to save the graphics state before and restore it afterwards.


HexaPDF::Composer.create('output.pdf', margin: 36) do |pdf|
  pdf.text("Hello World", valign: :center)



The base style which is used when no explicit style is provided to methods (e.g. to text).


The Content::Canvas of the current page. Can be used to perform arbitrary drawing operations.


The PDF document that is created.


The Layout::Frame for automatic box placement.


The current page (a HexaPDF::Type::Page object).

Public Class Methods

create(output, **options, &block)

Creates a new PDF document and writes it to output. The options are passed to ::new.


HexaPDF::Composer.create('output.pdf', margin: 36) do |pdf|
new(page_size: :A4, page_orientation: :portrait, margin: 36) { |composer| ... }

Creates a new Composer object and optionally yields it to the given block.


Can be any valid predefined page size (see Type::Page::PAPER_SIZE) or an array [llx, lly, urx, ury] specifying a custom page size.


Specifies the orientation of the page, either :portrait or :landscape. Only used if page_size is one of the predefined page sizes.


The margin to use. See Layout::Style::Quad#set for possible values.

Public Instance Methods


Draws the given Layout::Box.

The box is drawn into the current frame if possible. If it doesn't fit, the box is split. If it still doesn't fit, a new region of the frame is determined and then the process starts again.

If none or only some parts of the box fit into the current frame, one or more new pages are created for the rest of the box.

formatted_text(data, width: 0, height: 0, style: nil, **options)

Draws text like text but where parts of it can be formatted differently.

The argument data needs to be an array of String or Hash objects:

  • A String object is treated like {text: data}.

  • Hashes can contain any style properties and the following special keys:


    The text to be formatted.


    A URL that should be linked to. If no text is provided but a link, the link is used as text.


    A Layout::Style object to use as basis instead of the style created from the style and options arguments.

    If any style properties are set, the used style is copied and the additional properties applied.


composer.formatted_text(["Some string"])   # The same as #text
composer.formatted_text(["Some ", {text: "string", fill_color: 128}]
composer.formatted_text(["Some ", {link: "", text: "Example"}])
composer.formatted_text(["Some ", {text: "string", style: my_style}])
image(file, width: 0, height: 0, style: nil, **options)

Draws the given image file at the current position.

See text for details on width, height, style and options.

new_page(page_size: nil, page_orientation: nil, margin: nil)

Creates a new page, making it the current one.

If any of page_size, page_orientation or margin are set, they will be used instead of the default values and will become the default values.


composer.new_page  # uses the default values
composer.new_page(page_size: :A5, margin: [72, 36])
text(str, width: 0, height: 0, style: nil, **options)

Draws the given text at the current position into the current frame.

This method is the main method for displaying text on a PDF page. It uses a Layout::TextBox behind the scenes to do the actual work.

The text will be positioned at the current position if possible. Otherwise the next best position is used. If the text doesn't fit onto the current page or only partially, new pages are created automatically.

The arguments width and height are used as constraints and are respected when fitting the box.

The text is styled using the given style object (see Layout::Style) or, if no style object is specified, the base style (see base_style). If any additional style options are specified, the used style is copied and the additional styles are applied.

See HexaPDF::Layout::TextBox for details.

write(output, optimize: true, **options)

Writes the PDF document to the given output.

See Document#write for details.


The x-position of the cursor inside the current frame.


The y-position of the cursor inside the current frame.