Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
fpdf2
https://py-pdf.github.io/fpdf2/
Admin
fpdf2 is a library for simple and fast PDF document generation in Python.
Tokens:
463,400
Snippets:
2,748
Trust Score:
9.7
Update:
1 month ago
Context
Chat
Benchmark
80.46
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Install dependencies for Pandas examples Source: https://py-pdf.github.io/fpdf2/CombineWithChartingLibs.html Install fpdf2, matplotlib, and pandas using pip before running the Pandas examples. ```bash pip install fpdf2 matplotlib pandas ``` -------------------------------- ### Install dependencies for Matplotlib example Source: https://py-pdf.github.io/fpdf2/CombineWithChartingLibs.html Install fpdf2 and matplotlib using pip before running the Matplotlib examples. ```bash pip install fpdf2 matplotlib ``` -------------------------------- ### Install Plotly dependencies for SVG example Source: https://py-pdf.github.io/fpdf2/CombineWithChartingLibs.html Install the required packages for the SVG embedding example: fpdf2, plotly, kaleido, and pandas. ```bash pip install fpdf2 plotly kaleido pandas ``` -------------------------------- ### Add a page with label parameters using add_page() Source: https://py-pdf.github.io/fpdf2/PageLabels.html Shows how to specify label_style, label_prefix, and label_start when adding a new page. The example uses lowercase Roman numerals with a prefix 'Preface-' and start value 1. ```python from fpdf import FPDF pdf = FPDF() # Add a page with specific label parameters pdf.add_page( label_style="r", # Lowercase Roman numerals label_prefix="Preface-", # Prefix for the label label_start=1 # Start numbering at 1 ) pdf.output("document_with_labels.pdf") ``` -------------------------------- ### Install mistletoe Source: https://py-pdf.github.io/fpdf2/CombineWithMarkdown.html Install the mistletoe library, which follows the CommonMark specification, before using it to convert Markdown to HTML for fpdf2. ```bash pip install mistletoe ``` -------------------------------- ### Install fpdf2 from PyPI Source: https://py-pdf.github.io/fpdf2/index.html Install the latest stable release of fpdf2 from PyPI. ```bash pip install fpdf2 ``` -------------------------------- ### Enum Usage Examples Source: https://py-pdf.github.io/fpdf2/fpdf/enums.html General examples demonstrating how to define and access Python enumerations. ```python >>> class Color(Enum): ... RED = 1 ... BLUE = 2 ... GREEN = 3 ``` ```python >>> Color.RED ``` ```python >>> Color(1) ``` ```python >>> Color['RED'] ``` ```python >>> len(Color) 3 ``` ```python >>> list(Color) [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>] ``` -------------------------------- ### Install and set up pre-commit hooks Source: https://py-pdf.github.io/fpdf2/Development.html Installs pre-commit and sets up the git hooks configured in .pre-commit-config.yaml. The hooks abort commits if pylint finds issues or black detects non-properly formatted code; black will auto-format and you can re-commit with git commit -a. ```bash pip install pre-commit pre-commit install ``` -------------------------------- ### Install fpdf2 from local git repository Source: https://py-pdf.github.io/fpdf2/Development.html Installs fpdf2 from a local git repository in editable mode, linking the installed package to the repository location so code changes are reflected directly in the environment. ```bash pip install --editable $path/to/fpdf/repo ``` -------------------------------- ### Install dev dependencies and run mypy and pyright Source: https://py-pdf.github.io/fpdf2/Development.html Installs development dependencies and runs mypy and pyright for strict static typing checks. Use # type: ignore[...] sparingly, prefer real types over Any, and keep casts to unavoidable spots. ```bash pip install fpdf2[dev] mypy pyright ``` -------------------------------- ### Install fpdf2 with pip Source: https://py-pdf.github.io/fpdf2/notebook.html Installs the fpdf2 library using pip in a Jupyter notebook. ```python !pip install fpdf2 ``` -------------------------------- ### Install Rough.js and xmldom dependencies Source: https://py-pdf.github.io/fpdf2/CombineWithRoughJS.html Install the required dependencies for generating SVG with Rough.js. Requires Node.js and npm. ```bash npm install roughjs xmldom ``` -------------------------------- ### Install pdfrw fork with PR #216 patch Source: https://py-pdf.github.io/fpdf2/CombineWithPdfrw.html Installs a forked version of pdfrw that includes the patch from PR #216, required for the examples on this page. Run this command before using the pdfrw features shown above. ```bash pip install git+https://github.com/PyFPDF/pdfrw.git@addpage_at_index ``` -------------------------------- ### Install and run pylint for linting Source: https://py-pdf.github.io/fpdf2/Development.html Installs pylint and runs it on the fpdf/ and test/ directories to detect potential issues. False positives can be disabled locally with #pylint disable=XXX comments or globally via .pylintrc. ```bash pip install pylint pylint fpdf/ test/ ``` -------------------------------- ### Install fpdf2 development version from GitHub Source: https://py-pdf.github.io/fpdf2/index.html Install the latest unreleased development version directly from the master branch of the fpdf2 repository. ```bash pip install git+https://github.com/py-pdf/fpdf2.git@master ``` -------------------------------- ### PDFPage methods for index, dimensions, labels, and text substitutions Source: https://py-pdf.github.io/fpdf2/fpdf/output.html Provides methods to get and set page index, dimensions, page labels, and text substitution fragments. Includes logic for handling page label inheritance and default start values. ```python def index(self) -> int: return self._index def set_index(self, i: int) -> None: self._index = i def dimensions(self) -> tuple[float, float]: "Return a pair (width, height) in the unit specified to FPDF constructor" if self._width_pt is None or self._height_pt is None: raise ValueError("Page dimensions are null") return self._width_pt, self._height_pt def set_dimensions(self, width_pt: float, height_pt: float) -> None: "Accepts a pair (width, height) in the unit specified to FPDF constructor" self._width_pt, self._height_pt = width_pt, height_pt def set_page_label( self, previous_page_label: Optional[PDFPageLabel], page_label: Optional[PDFPageLabel], ) -> None: if ( previous_page_label and page_label and page_label.get_style() == previous_page_label.get_style() and page_label.get_prefix() == previous_page_label.get_prefix() and not page_label.st ): page_label.st = previous_page_label.get_start() + 1 if page_label: if page_label.st is None or page_label.st == 0: page_label.st = 1 if previous_page_label and not page_label: page_label = PDFPageLabel( previous_page_label.get_style(), previous_page_label.get_prefix(), previous_page_label.get_start() + 1, ) self._page_label = page_label def get_page_label(self) -> Optional[PDFPageLabel]: return self._page_label def get_label(self) -> str: return str(self.index()) if not self._page_label else str(self._page_label) def get_text_substitutions(self) -> Sequence[TotalPagesSubstitutionFragment]: return self._text_substitution_fragments def add_text_substitution(self, fragment: TotalPagesSubstitutionFragment) -> None: self._text_substitution_fragments.append(fragment) ``` -------------------------------- ### Install and run black for code auto-formatting Source: https://py-pdf.github.io/fpdf2/Development.html Installs the black code formatter and runs it on the fpdf2 root directory to auto-format source code before committing. ```bash pip install black black . # inside fpdf2 root directory ``` -------------------------------- ### PDFPage page label methods Source: https://py-pdf.github.io/fpdf2/fpdf/output.html Manages page labels, including setting, getting, and computing the label string. The set_page_label method adjusts the start value based on previous label style and prefix. ```python def set_page_label( self, previous_page_label: Optional[PDFPageLabel], page_label: Optional[PDFPageLabel], ) -> None: if ( previous_page_label and page_label and page_label.get_style() == previous_page_label.get_style() and page_label.get_prefix() == previous_page_label.get_prefix() and not page_label.st ): page_label.st = previous_page_label.get_start() + 1 if page_label: if page_label.st is None or page_label.st == 0: page_label.st = 1 if previous_page_label and not page_label: page_label = PDFPageLabel( previous_page_label.get_style(), previous_page_label.get_prefix(), previous_page_label.get_start() + 1, ) self._page_label = page_label def get_page_label(self) -> Optional[PDFPageLabel]: return self._page_label def get_label(self) -> str: return str(self.index()) if not self._page_label else str(self._page_label) ``` -------------------------------- ### Install Ibis dependencies Source: https://py-pdf.github.io/fpdf2/CombineWithChartingLibs.html Install the required packages for using Ibis with fpdf2: ibis-framework with DuckDB backend, fpdf2, and pandas. ```bash pip install "ibis-framework[duckdb]" fpdf2 pandas ``` -------------------------------- ### FPDF constructor with explicit parameters Source: https://py-pdf.github.io/fpdf2/Tutorial.html Shows how to specify orientation, unit, and format explicitly. Equivalent to the default constructor used in the minimal example. ```python pdf = FPDF(orientation="P", unit="mm", format="A4") ``` -------------------------------- ### PDFPage index and dimensions methods Source: https://py-pdf.github.io/fpdf2/fpdf/output.html Provides methods to get and set the page index and dimensions. The dimensions method raises ValueError if dimensions are null. ```python def index(self) -> int: return self._index def set_index(self, i: int) -> None: self._index = i def dimensions(self) -> tuple[float, float]: "Return a pair (width, height) in the unit specified to FPDF constructor" if self._width_pt is None or self._height_pt is None: raise ValueError("Page dimensions are null") return self._width_pt, self._height_pt def set_dimensions(self, width_pt: float, height_pt: float) -> None: "Accepts a pair (width, height) in the unit specified to FPDF constructor" self._width_pt, self._height_pt = width_pt, height_pt ``` -------------------------------- ### Preview documentation with mkdocs serve Source: https://py-pdf.github.io/fpdf2/Development.html Launches a local rendering server for the main documentation. Run from the project root. ```bash mkdocs serve --open ``` -------------------------------- ### Minimal example: create PDF with 'Hello World!' Source: https://py-pdf.github.io/fpdf2/Tutorial.html Creates a PDF with a single page and a cell containing 'Hello World!'. Uses default A4 portrait format and millimeter units. The font is set to Helvetica bold 16. Outputs to 'tuto1.pdf'. ```python from fpdf import FPDF pdf = FPDF() pdf.add_page() pdf.set_font("helvetica", style="B", size=16) pdf.cell(40, 10, "Hello World!") pdf.output("tuto1.pdf") ``` -------------------------------- ### PDFOutputProducer.bufferize() method implementation Source: https://py-pdf.github.io/fpdf2/fpdf/output.html This method alters the target FPDF instance by assigning IDs to all PDF objects and other properties. It handles encryption setup, adds all PDF objects (header, pages, catalog, annotations, embedded files, etc.), and returns the final bytearray. ```python def bufferize(self) -> bytearray: """ This method alters the target FPDF instance by assigning IDs to all PDF objects, plus a few other properties on PDFPage instances """ fpdf = self.fpdf # 1. setup - Insert all PDF objects # and assign unique consecutive numeric IDs to all of them if fpdf._security_handler is not None: # get the file_id and generate passwords needed to encrypt streams and strings file_id: Optional[str | Literal[-1]] = fpdf.file_id() if file_id == -1: # no custom file id - use default file id so encryption passwords can be generated file_id = fpdf._default_file_id(bytearray(0x00)) fpdf._security_handler.generate_passwords(str(file_id)) pdf_version = fpdf.pdf_version if ( fpdf.viewer_preferences and fpdf.viewer_preferences._min_pdf_version > pdf_version ): pdf_version = fpdf.viewer_preferences._min_pdf_version self.pdf_objs.append(PDFHeader(pdf_version)) pages_root_obj = self._add_pages_root() catalog_obj = self._add_catalog() page_objs = self._add_pages() sig_annotation_obj = self._add_annotations_as_objects() self._add_annotation_appearance_streams() for embedded_file in fpdf.embedded_files: self._add_pdf_obj(embedded_file, "embedded_files") self._add_pdf_obj(embedded_file.file_spec(), "file_spec") self._add_optional_content_groups(catalog_obj) self._insert_resources(page_objs) struct_tree_root_obj = self._add_structure_tree() outline_dict_obj, outline_items = self._add_document_outline() xmp_metadata_obj = self._add_xmp_metadata() info_obj = None if not fpdf._compliance: info_obj = self._add_info() encryption_obj = self._add_encryption() xref = PDFXrefAndTrailer(self) self.pdf_objs.append(xref) ``` -------------------------------- ### Preview API documentation with pdoc Source: https://py-pdf.github.io/fpdf2/Development.html Launches a local rendering server for the API documentation generated by pdoc3. Uses the template directory docs/pdoc. ```bash pdoc --html -o public/ fpdf --template-dir docs/pdoc --http : ``` -------------------------------- ### Create a simple PDF with fpdf2 Source: https://py-pdf.github.io/fpdf2/index.html Minimal example to generate a PDF with 'Hello world!' using fpdf2. Requires the fpdf package. The output file is 'hello_world.pdf'. ```python from fpdf import FPDF pdf = FPDF() pdf.add_page() pdf.set_font('Helvetica', size=12) pdf.cell(text="Hello world!") pdf.output("hello_world.pdf") ``` -------------------------------- ### GTK/cairo missing library error on Windows Source: https://py-pdf.github.io/fpdf2/SVG.html Example error output when cairosvg is used on Windows without GTK installed. The error indicates missing cairo libraries; install GTK from the GTK-for-Windows-Runtime-Environment-Installer and restart the editor to resolve it. ```text OSError: no library called "cairo-2" was found no library called "cairo" was found no library called "libcairo-2" was found cannot load library 'libcairo.so.2': error 0x7e cannot load library 'libcairo.2.dylib': error 0x7e cannot load library 'libcairo-2.dll': error 0x7e ``` -------------------------------- ### Convert Markdown to PDF with Python-Markdown and FPDF Source: https://py-pdf.github.io/fpdf2/CombineWithMarkdown.html Install the Python-Markdown library, then convert a Markdown string to HTML and render it to a PDF using FPDF's write_html(). The example uses extensions for definition lists, sane lists, and tables. ```bash pip install markdown ``` ```python from markdown import markdown html = markdown( """ # Top title (ATX) Subtitle (setext) ----------------- ### An even lower heading (ATX) **Text in bold** _Text in italics_ [This is a link](https://github.com/PyFPDF/fpdf2) <https://py-pdf.github.io/fpdf2/> This is an unordered list: * an item * another item This is an ordered list: 1. first item 2. second item 3. third item with an unordered sublist: * an item * another item Inline `code span` A table: Foo | Bar | Baz --- | --- | --- Foo | Bar | Baz Definition list: Term : Definition Actual HTML: <dl> <dt>Term1</dt><dd>Definition1</dd> <dt>Term2</dt><dd>Definition2</dd> </dl> Some horizontal thematic breaks: *** --- ___  """, extensions=["def_list", "sane_lists", "tables"], ) from fpdf import FPDF pdf = FPDF() pdf.add_page() pdf.write_html(html) pdf.output("pdf-from-markdown-with-markdown.pdf") ``` -------------------------------- ### OutputIntentDictionary.__init__ Source: https://py-pdf.github.io/fpdf2/fpdf/output.html Initializes an OutputIntentDictionary instance with the given parameters, setting up the PDF output intent dictionary structure. ```APIDOC ## OutputIntentDictionary.__init__ ### Description Initializes an OutputIntentDictionary instance, setting the type to 'OutputIntent' and storing the provided parameters as PDF objects. ### Method Constructor ### Signature ```python def __init__( self, subtype: "OutputIntentSubType | str", output_condition_identifier: Optional[str], output_condition: Optional[str] = None, registry_name: Optional[str] = None, dest_output_profile: Optional[PDFICCProfile] = None, info: Optional[str] = None, ) -> None ``` ### Parameters - **subtype** (OutputIntentSubType | str) - Required - The subtype of the output intent: PDFA, PDFX, or ISOPDF. - **output_condition_identifier** (str) - Required - The name identifying the output condition, as per the color.org registry. - **output_condition** (str) - Optional - The definition of the output condition, as per the color.org registry. - **registry_name** (str) - Optional - The registry name, typically "https://www.color.org". - **dest_output_profile** (PDFICCProfile) - Optional - The destination ICC profile; required if output_condition_identifier does not specify a standard production condition. - **info** (str) - Optional - Human-readable description of the profile; required if dest_output_profile is provided. ### Returns None ``` -------------------------------- ### Basic FlexTemplate usage with multiple pages Source: https://py-pdf.github.io/fpdf2/Templates.html Shows how to create a FlexTemplate, set text values, render it on a page, and combine with other PDF content. Templates reset after rendering, so they can be reused on subsequent pages. ```python from fpdf import FlexTemplate, FPDF pdf = FPDF() pdf.add_page() # One template for the first page fp_tmpl = FlexTemplate(pdf, elements=fp_elements) fp_tmpl["item_key_01"] = "Text 01" fp_tmpl["item_key_02"] = "Text 02" ... fp_tmpl.render() # add template items to first page # add some more non-template content to the first page pdf.polyline(point_list, fill=False, polygon=False) # second page pdf.add_page() # header for the second page h_tmpl = FlexTemplate(pdf, elements=h_elements) h_tmpl["item_key_HA"] = "Text 2A" h_tmpl["item_key_HB"] = "Text 2B" ... h_tmpl.render() # add header items to second page # footer for the second page f_tmpl = FlexTemplate(pdf, elements=f_elements) f_tmpl["item_key_FC"] = "Text 2C" f_tmpl["item_key_FD"] = "Text 2D" ... f_tmpl.render() # add footer items to second page # other content on the second page pdf.set_dash_pattern(dash=1, gap=1) pdf.line(x1, y1, x2, y2): pdf.set_dash_pattern() # third page pdf.add_page() # header for the third page, just reuse the same template instance after render() h_tmpl["item_key_HA"] = "Text 3A" h_tmpl["item_key_HB"] = "Text 3B" ... h_tmpl.render() # add header items to third page # footer for the third page f_tmpl["item_key_FC"] = "Text 3C" f_tmpl["item_key_FD"] = "Text 3D" ... f_tmpl.render() # add footer items to third page # other content on the third page pdf.rect(x, y, w, h, style=None) # possibly more pages pdf.add_page() ... ... # finally write everything to a file pdf.output("example.pdf") ``` -------------------------------- ### OutputIntent.__init__ Source: https://py-pdf.github.io/fpdf2/fpdf/output.html Constructor for the OutputIntent class. Initializes an output intent object with the given subtype and optional parameters for color management. ```APIDOC ## OutputIntent.__init__ ### Description Initializes an OutputIntent object with the specified subtype and optional parameters for output condition, registry, and ICC profile. ### Method Constructor ### Parameters #### Required Parameters - **subtype** (OutputIntentSubType | str) - Required - PDFA, PDFX, or ISOPDF - **output_condition_identifier** (str) - Required - see the Name in https://www.color.org/registry.xalter #### Optional Parameters - **output_condition** (str) - Optional - see the Definition in https://www.color.org/registry.xalter - **registry_name** (str) - Optional - "https://www.color.org" - **dest_output_profile** (PDFICCProfile) - Required/Optional - PDFICCProfile | None (required if output_condition_identifier does not specify a standard production condition; optional otherwise) - **info** (str) - Required/Optional - human readable description of profile (required if dest_output_profile is provided) ### Request Example ```python OutputIntent( subtype="PDFA", output_condition_identifier="sRGB IEC61966-2.1", output_condition="sRGB", registry_name="https://www.color.org", dest_output_profile=profile, info="sRGB profile" ) ``` ### Response No return value. The object is initialized with the provided parameters. ``` -------------------------------- ### row_range method definition on RowSpanLayoutInfo Source: https://py-pdf.github.io/fpdf2/fpdf/table.html Returns a range spanning from the start row through start plus length rows. ```Python def row_range(self) -> range: return range(self.start, self.start + self.length) ``` -------------------------------- ### bufferize() method implementation for linearized PDF output Source: https://py-pdf.github.io/fpdf2/fpdf/linearization.html This is the full implementation of the bufferize() method from the OutputProducer class. It performs the three main steps: setting up PDF objects, serializing them to the buffer, and substituting linearization property placeholders. It also signs the buffer if a signing key is configured. ```python def bufferize(self) -> bytearray: fpdf = self.fpdf # 1. Setup - Insert all PDF objects # (in the order required to build a linearized PDF), # and assign unique consecutive numeric IDs to all of them # 2. Plumbing - Inject all PDF object references required: linearization_obj.o = page_objs[0].id # type: ignore[assignment] pages_root_obj.kids = PDFArray(page_objs) self._finalize_catalog( catalog_obj, pages_root_obj=pages_root_obj, first_page_obj=page_objs[0], sig_annotation_obj=sig_annotation_obj, xmp_metadata_obj=xmp_metadata_obj, struct_tree_root_obj=struct_tree_root_obj, outline_dict_obj=outline_dict_obj, ) dests: list[DestinationXYZ] = [] for page_obj in page_objs: page_obj.parent = pages_root_obj page_obj.resources = resources_dict_obj assert page_obj.annots is not None for annot in page_obj.annots: if annot.dest: dests.append(annot.dest) if annot.a and hasattr(annot.a, "dest"): dests.append(annot.a.dest) if not page_obj.annots: # Avoid serializing an empty PDFArray: page_obj.annots = None for outline_item in outline_items: if outline_item.dest is not None: dests.append(outline_item.dest) # Assigning the .page_ref property of all Destination objects: for dest in dests: dest.page_ref = pdf_ref( # pyright: ignore[reportAttributeAccessIssue] page_objs[ dest.page_number - 1 # pyright: ignore[reportAttributeAccessIssue] ].id ) for struct_elem in fpdf.struct_builder.doc_struct_elem.k: struct_elem.pg = page_objs[struct_elem.page_number() - 1] main_xref.first_xref = first_xref first_xref.main_xref = main_xref for xref in [main_xref, first_xref]: xref.catalog_obj = catalog_obj xref.info_obj = info_obj # 3. Serializing - Append all PDF objects to the buffer: assert ( not self.buffer ), f"Nothing should have been appended to the .buffer at this stage: {self.buffer}" assert ( not self.offsets ), f"No offset should have been set at this stage: {len(self.offsets)}" for pdf_obj in self.pdf_objs: if isinstance(pdf_obj, ContentWithoutID): # top header, xref table & trailer: trace_label = None else: self.offsets[pdf_obj.id] = len(self.buffer) trace_label = self.trace_labels_per_obj_id.get(pdf_obj.id) if trace_label: with self._trace_size(trace_label): self._out(pdf_obj.serialize()) else: self._out(pdf_obj.serialize()) self._log_final_sections_sizes() # Now that the file size & all the offsets are known, # substitute the values of the Linearization properties: hs1_offset = self.offsets[hint_stream_obj.id] hs1_length = len(hint_stream_obj.serialize()) self.buffer = buffer_subst( self.buffer, HINT_STREAM_OFFSET_LENGTH_PLACEHOLDER, f"[{hs1_offset: 12d} {hs1_length: 12d}]", ) self.buffer = buffer_subst( self.buffer, FIRST_PAGE_END_OFFSET_PLACEHOLDER, f"{self.offsets[page_objs[0].id + 1]: 12d}", ) self.buffer = buffer_subst( self.buffer, MAIN_XREF_1ST_ENTRY_OFFSET_PLACEHOLDER, f"{self.offsets[main_xref.start_obj_id]: 12d}", ) self.buffer = buffer_subst( self.buffer, FILE_LENGTH_PLACEHOLDER, f"{len(self.buffer): 12d}", ) if fpdf._sign_key: # pyright: ignore[reportPrivateUsage] self.buffer = sign_content( signer, # pyright: ignore[reportArgumentType] self.buffer, fpdf._sign_key, # pyright: ignore[reportPrivateUsage] fpdf._sign_cert, # pyright: ignore[reportPrivateUsage] fpdf._sign_extra_certs, # pyright: ignore[reportPrivateUsage] fpdf._sign_hashalgo, # pyright: ignore[reportPrivateUsage] fpdf._sign_time, # pyright: ignore[reportPrivateUsage] ) return self.buffer ``` -------------------------------- ### Generate a PDF with fpdf2 Source: https://py-pdf.github.io/fpdf2/notebook.html Creates a PDF with the text 'hello world' using fpdf2 and outputs it as bytes. ```python from fpdf import FPDF pdf = FPDF() pdf.add_page() pdf.set_font('helvetica', size=48) pdf.cell(text="hello world") pdf_bytes = pdf.output() ``` -------------------------------- ### DeviceRGB.__init__ Source: https://py-pdf.github.io/fpdf2/fpdf/drawing_primitives.html Constructor for DeviceRGB, initializes red, green, blue, and optional alpha components, normalizing values to floats and validating ranges. ```APIDOC ## DeviceRGB.__init__ ### Description Initializes a DeviceRGB color instance with red, green, blue, and optional alpha components. Values are normalized to floats and validated to be in range. ### Method Constructor ### Signature `DeviceRGB(r: int | float | decimal.Decimal, g: int | float | decimal.Decimal, b: int | float | decimal.Decimal, a: int | float | decimal.Decimal | None = None)` ### Parameters - **r** (int | float | decimal.Decimal) - Required - Red component, must be in range 0-1. - **g** (int | float | decimal.Decimal) - Required - Green component, must be in range 0-1. - **b** (int | float | decimal.Decimal) - Required - Blue component, must be in range 0-1. - **a** (int | float | decimal.Decimal | None) - Optional - Alpha (opacity) component, must be in range 0-1 if provided. Defaults to None. ### Example ```python color = DeviceRGB(1.0, 0.5, 0.0) ``` ``` -------------------------------- ### Generic Protocol class example Source: https://py-pdf.github.io/fpdf2/fpdf/syntax.html Example of a generic Protocol class definition. It uses a type parameter T for the method return type. ```python class GenProto[T](Protocol): def meth(self) -> T: ... ``` -------------------------------- ### Create template with Python dict elements Source: https://py-pdf.github.io/fpdf2/Templates.html Define a template directly as a Python dictionary of elements, then instantiate a Template, fill fields by key, and render to a PDF. Each element line lists properties in the order name, type, x1, y1, x2, y2, font, size, bold, italic, underline, foreground, background, align, text, priority, multiline, rotate, wrapmode, keep_aspect_ratio; most fields may be left empty, and barcode types may omit x2. ```python from fpdf import Template #this will define the ELEMENTS that will compose the template. elements = [ { 'name': 'company_logo', 'type': 'I', 'x1': 20.0, 'y1': 17.0, 'x2': 78.0, 'y2': 30.0, 'font': None, 'size': 0.0, 'bold': 0, 'italic': 0, 'underline': 0, 'align': 'C', 'text': 'logo', 'priority': 2, 'multiline': False}, { 'name': 'company_name', 'type': 'T', 'x1': 17.0, 'y1': 32.5, 'x2': 115.0, 'y2': 37.5, 'font': 'helvetica', 'size': 12.0, 'bold': 1, 'italic': 0, 'underline': 0,'align': 'C', 'text': '', 'priority': 2, 'multiline': False}, { 'name': 'multiline_text', 'type': 'T', 'x1': 20, 'y1': 100, 'x2': 40, 'y2': 105, 'font': 'helvetica', 'size': 12, 'bold': 0, 'italic': 0, 'underline': 0, 'background': 0x88ff00, 'align': 'C', 'text': 'Lorem ipsum dolor sit amet, consectetur adipisici elit', 'priority': 2, 'multiline': True, 'wrapmode': 'WORD'}, { 'name': 'box', 'type': 'B', 'x1': 15.0, 'y1': 15.0, 'x2': 185.0, 'y2': 260.0, 'font': 'helvetica', 'size': 0.0, 'bold': 0, 'italic': 0, 'underline': 0, 'align': 'C', 'text': None, 'priority': 0, 'multiline': False}, { 'name': 'box_x', 'type': 'B', 'x1': 95.0, 'y1': 15.0, 'x2': 105.0, 'y2': 25.0, 'font': 'helvetica', 'size': 0.0, 'bold': 1, 'italic': 0, 'underline': 0, 'align': 'C', 'text': None, 'priority': 2, 'multiline': False}, { 'name': 'line1', 'type': 'L', 'x1': 100.0, 'y1': 25.0, 'x2': 100.0, 'y2': 57.0, 'font': 'helvetica', 'size': 0, 'bold': 0, 'italic': 0, 'underline': 0, 'align': 'C', 'text': None, 'priority': 3, 'multiline': False}, { 'name': 'barcode', 'type': 'BC', 'x1': 20.0, 'y1': 246.5, 'x2': 140.0, 'y2': 254.0, 'font': 'Interleaved 2of5 NT', 'size': 0.75, 'bold': 0, 'italic': 0, 'underline': 0, 'align': 'C', 'text': '200000000001000159053338016581200810081', 'priority': 3, 'multiline': False}, ] #here we instantiate the template f = Template(format="A4", elements=elements, title="Sample Invoice") f.add_page() #we FILL some of the fields of the template with the information we want #note we access the elements treating the template instance as a "dict" f["company_name"] = "Sample Company" f["company_logo"] = "docs/fpdf2-logo.png" #and now we render the page f.render("./template.pdf") ``` -------------------------------- ### Protocol class example Source: https://py-pdf.github.io/fpdf2/fpdf/syntax.html Example of a Protocol class definition as shown in the documentation for protocol classes. It declares a method meth returning an int. ```python class Proto(Protocol): def meth(self) -> int: ... ``` -------------------------------- ### GraphicsStateMixin usage example Source: https://py-pdf.github.io/fpdf2/Internals.html Shows how to push and pop graphics states using the GraphicsStateMixin. After pushing the initial state, set font_size_pt and underline, then pop to restore the previous state. The output confirms that the restored state has font_size_pt=0 and underline=False. ```python 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 ``` -------------------------------- ### Install Plotly dependencies Source: https://py-pdf.github.io/fpdf2/CombineWithChartingLibs.html Install the required packages for using Plotly with fpdf2: fpdf2, plotly, kaleido, and numpy. kaleido is used for static image generation. ```bash pip install fpdf2 plotly kaleido numpy ``` -------------------------------- ### Install uharfbuzz for text shaping Source: https://py-pdf.github.io/fpdf2/TextShaping.html Install the uharfbuzz package, which is required for text shaping. Text shaping is disabled by default to keep backwards compatibility and reduce resource requirements. ```bash pip install uharfbuzz ``` -------------------------------- ### Using Template class to create and render a PDF Source: https://py-pdf.github.io/fpdf2/Templates.html Shows the traditional approach: create a Template with elements, add pages, set item values using dict-like keys, and render to a PDF file. The Template manages its own FPDF instance. ```python tmpl = Template(elements=elements) # first page and content tmpl.add_page() tmpl[item_key_01] = "Text 01" tmpl[item_key_02] = "Text 02" ... # second page and content tmpl.add_page() tmpl[item_key_01] = "Text 11" tmpl[item_key_02] = "Text 12" ... # possibly more pages ... # finalize document and write to file tmpl.render(outfile="example.pdf") ``` -------------------------------- ### Structural subtyping example with Protocol Source: https://py-pdf.github.io/fpdf2/fpdf/syntax.html Example demonstrating structural subtyping with a Protocol. A class C that implements the required method is passed to a function expecting the Protocol, and the static type check passes. ```python class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check ``` -------------------------------- ### line_width property Source: https://py-pdf.github.io/fpdf2/fpdf/graphics_state.html Gets or sets the line width. ```APIDOC ## line_width property ### Description Gets or sets the line width. ### Method property getter/setter ### Parameters (setter) - **v** (float) - Required - Line width value. ### Returns (getter) - **float** - The current line width. ``` -------------------------------- ### Padding.new Source: https://py-pdf.github.io/fpdf2/fpdf/util.html Create a Padding instance from a number or a sequence of 2, 3, or 4 numbers according to CSS rules. ```APIDOC ## Padding.new ### Description Return a 4-tuple of padding values from a single value or a 2, 3, or 4-tuple according to CSS rules. Accepts an int, float, Decimal, a sequence of numbers, or an existing Padding instance. ### Method Static method ### Signature `new(padding: int | float | decimal.Decimal | Sequence[int | float | decimal.Decimal] | Padding) -> Padding` ### Parameters - **padding** (Union[Number, Sequence[Number], Padding]) - Required - Input padding value(s) to be normalized. ### Returns - **Padding** - A 4-tuple with top, right, bottom, left values. ### Example ```python p = Padding.new(10) # (10, 10, 10, 10) p = Padding.new([10, 20]) # (10, 20, 10, 20) p = Padding.new([10, 20, 30]) # (10, 20, 30, 20) p = Padding.new([10, 20, 30, 40]) # (10, 20, 30, 40) ``` ``` -------------------------------- ### Bottle route returning a PDF (app.py) Source: https://py-pdf.github.io/fpdf2/UsageInWebAPI.html Save as 'app.py' and run with `python3 app.py`. The route generates a PDF, sets the response headers, and returns the bytes. The server starts on localhost:8080 with debug enabled. ```python from bottle import route, run, response from fpdf import FPDF @route('/') def hello(): pdf = FPDF() pdf.add_page() pdf.set_font("Helvetica", size=24) pdf.cell(text="hello world") pdf_bytes = bytes(pdf.output()) response.set_header('Content-Type', 'application/pdf') response.status = 200 response.content_length = len(pdf_bytes) return pdf_bytes if __name__ == '__main__': run(host='localhost', port=8080, debug=True) ``` -------------------------------- ### Complete example: multiple sections with different page label styles Source: https://py-pdf.github.io/fpdf2/PageLabels.html Demonstrates adding three pages with different label styles and prefixes: lowercase Roman numerals for front matter, decimal with 'Chapter-' prefix for main content, and uppercase letters with 'Appendix-' prefix for an appendix. ```python from fpdf import FPDF pdf = FPDF() # Adding front matter with lowercase Roman numerals pdf.add_page(label_style="r", label_start=1) # Starts with "i", "ii", "iii", etc. # Adding main content with decimal numbers and a prefix pdf.add_page(label_style="D", label_prefix="Chapter-", label_start=1) # "Chapter-1", "Chapter-2", etc. # Adding an appendix section with uppercase letters pdf.add_page(label_style="A", label_prefix="Appendix-", label_start=1) # "Appendix-A", "Appendix-B", etc. pdf.output("labeled_document.pdf") ``` -------------------------------- ### sub_lift property Source: https://py-pdf.github.io/fpdf2/fpdf/graphics_state.html Gets the lift factor for subscript text. ```APIDOC ## sub_lift property ### Description Gets the lift factor for subscript text. ### Method property getter ### Returns - **float** - The current subscript lift factor. ``` -------------------------------- ### text_mode property Source: https://py-pdf.github.io/fpdf2/fpdf/graphics_state.html Gets or sets the text rendering mode. ```APIDOC ## text_mode property ### Description Gets or sets the text rendering mode. ### Method property getter/setter ### Parameters (setter) - **v** (TextMode | str | int) - Required - Text mode value. ### Returns (getter) - **TextMode** - The current text mode. ``` -------------------------------- ### dash_pattern property Source: https://py-pdf.github.io/fpdf2/fpdf/graphics_state.html Gets or sets the dash pattern for lines. ```APIDOC ## dash_pattern property ### Description Gets or sets the dash pattern for lines. ### Method property getter/setter ### Parameters (setter) - **v** (dict[str, float]) - Required - Dash pattern dictionary. ### Returns (getter) - **dict[str, float]** - The current dash pattern. ``` -------------------------------- ### CherryPy class exposing a PDF response (app.py) Source: https://py-pdf.github.io/fpdf2/UsageInWebAPI.html Save as 'app.py' and launch with `python3 app.py`. The exposed method sets the title 'content-type' and status, then returns the PDF bytes. The server runs via cherrypy.quickstart. ```python import cherrypy from fpdf import FPDF class HelloWorld(object): @cherrypy.expose def index(self): pdf = FPDF() pdf.add_page() pdf.set_font("Helvetica", size=24) pdf.cell(text="hello world") pdf_bytes = bytes(pdf.output()) cherrypy.response.headers['content-type'] = 'application/pdf' cherrypy.response.status = 200 return pdf_bytes if __name__ == "__main__": cherrypy.quickstart(HelloWorld()) ```