Skip to content

fpdf2 internals

FPDF.pages

FPDF is designed to add content progressively to the document generated, page by page.

Each page is an entry in the .pages attribute of FPDF instances. Indices start at 1 (the first page) and values are PDFPage instances.

PDFPage instances have a .contents attribute that is a bytearray and contains the Content Stream for this page (bytearray makes things a lot faster).

Going back to a previously generated page to add content is possible, using the .page attribute, but may result in unexpected behavior, because .add_page() takes special care to ensure the page's content stream matches FPDF's instance attributes.

syntax.py & objects serialization

The syntax.py package contains classes representing core elements of the PDF syntax.

Classes inherit from the PDFObject class, that has the following properties:

  • every PDF object has an .id, that is assigned during the document serialization by the OutputProducer
  • the .serialize() method renders the PDF object as an obj<>endobj text block. It can be overridden by child classes.
  • the .content_stream() method must return non empty bytes if the PDF Object has a content stream

Other notable core classes are:

GraphicsStateMixin

This mixin class, inherited by the FPDF class, allows to manage a stack of graphics state variables:

The main methods of this API are:

Thanks to this mixin, we can use the following semantics:

from fpdf.graphics_state import GraphicsStateMixin

f = GraphicsStateMixin()
# Push initial state in stack: gs0
gs0 = f._push_local_stack()
# Step 1 - set some graphic styles: gs1
f.font_size_pt = 16
f.underline = True
gs1 = f._get_current_graphics_state()
# Step 2 - restore gs0
f._pop_local_stack()
print(f"{f.font_size_pt=} {f.underline=}")
# -> f.font_size_pt=0 f.underline=False

The graphics states used in the code above can be depicted by this diagram:

stateDiagram-v2
  direction LR
  state gs0 {
    initial1 : Base state
  }
  state gs1 {
    initial2 : Base state
    font_size_pt2 : font_size_pt=16
    underline2 : underline=True
    font_size_pt2 --> initial2
    underline2 --> font_size_pt2
  }
  gs0 --> gs1: Step 1
  state "gs0" as stack2 {
    initial3 : Base state
  }
  gs1 --> stack2: Step 2

OutputProducer

In fpdf2, the FPDF class is used to store the document definition, its state as it is progressively built. Most attributes and internal data is mutable.

Once it's done, when the FPDF.output() method is called, the actual PDF file creation is delegated to the OutputProducer class.

It performs the serialization of the PDF document, including the generation of the cross-reference table & file trailer. This class uses the FPDF instance as immutable input: it does not perform any modification on it.