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 anobj<>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:
- docstring: fpdf.graphics_state.GraphicsStateMixin
- source file: graphics_state.py
The main methods of this API are:
- _push_local_stack(): Push a graphics state on the stack
- _pop_local_stack(): Pop the last graphics state on the stack
- _get_current_graphics_state(): Retrieve the current graphics state
- _is_current_graphics_state_nested(): Indicate if the stack contains items (else it is empty)
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.