libXp provides public APIs to allow client applications to render
to non-display devices.

When an application wishes to print, it makes a
display connection to the X print server and asks to see the list of
printers available with an XpGetPrinterList() request. Once the application
has selected a printer, it creates and sets a print context using XpCreateContext()
and XpSetContext().
The Print Context represents the embodiment of the printer selected. It
is initialized by the Xprint server at XpCreateContext() time to contain
a printer's default capabilities, as well as, the description of its overall
capabilties, and to maintain the state of settings on the printer, the
state of rendering against the printer, and the rendered output.

The
Print Context affects how the DDX driver generates its page description
language (PDL) and how the PDL is submitted to a spooler. The print context
may also affect fonts and other elements in the dix layer of the X Print
Server. The print contexts can be shared among processes. Applications can
enlist the help of secondary processes to manipulate print options in
the Print context rather than taking on the task directly.

Once an application
has set options within the print context, it makes calls such as XpStartJob()
to delineate jobs, documents, and pages within a sequence of normal X
calls.

A job is a collection of documents, where each document is in turn
a collection of pages. When XpEndJob() is called, the resulting PDL is
either sent to a print spooler or can be retrieved by the application
itself.

The developer basically has to make changes to the X application
to make use of the X Print Service.

A simple X application supplemented
with some of the libXp routines might look like this: