All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning, and PEP 440.
DeprecationWarning messages are not displayed by Python by default.
Hence, every time you use a newer version of fpdf2, we strongly encourage you to execute your scripts
with the -Wd option (cf. documentation)
in order to get warned about deprecated features used in your code.
This can also be enabled programmatically with warnings.simplefilter('default', DeprecationWarning).
- support for SVG
<linearGradient>and<radialGradient>elements - cf. issue #1580 - thanks to @Ani07-05
- the
A5value that could be specified as pageformatto theFPDFconstructor was slightly incorrect, and the corresponding page dimensions have been fixed. This could lead to a minor change in your documents dimensions if you used thisA5page format. - cf. issue #1699 - a bug when rendering empty tables with
INTERNALlayout, that caused an extra border to be rendered due to an erroneous use oflist.index()- cf. issue #1669
- improved performance when rendering paths, SVGs, and opaque raster images with an alpha channel - cf. PR #1675
- documentation on how to combine
fpdf2with Bottle, CherryPy & Plone: link to documentation - thanks to @tanmayc07 and @Vidushi2709 - basic support for SVG
currentColorcolor value - cf. PR #1531 - thanks to @dlespiau - Porter–Duff compositing operations and bounding box support to the drawing API - cf. PR #1532
- support gradients as fill or stroke colors in the drawing API - cf. PR #1539: link to documentation
- support for gradient spread methods (PAD, reflect and repeat)
- support for sweep (mesh) gradients
- support for dashed lines in FlexTemplate elements - cf. issue #1503 - thanks to @dabell-cc
- support for rendering color font glyphs in different formats (SBIX, CBDT/CBLC, SVG, COLRv0 and COLRv1) - cf. PR #1305
- support for linking to named destinations - cf. issue #1545 - thanks to @RamBelitkar: link to documentation
- native support for PDF/A compliance verification - including PDF/A-1B, 2B, 2U, 3B, 3U, 4, 4E and 4F: link to documentation. Accessible PDF/A documents (PDF/A 1A, 2A and 3A) are not yet supported.
unicode_rangeparameter foradd_font()to restrict which unicode characters a font covers - cf. issue #1586 - thanks to @Malay-devvariationsparameter added inadd_font()to allow the use of variable fonts - cf. issue #1544: link to documentation - thanks to @Rapteon- support for color font palette selection via a new
paletteparameter inadd_font(), allowing users to choose alternate color palettes from color fonts (COLR/CPAL) and enabling different color schemes without embedding the font multiple times - cf. issue #1578, PR #1621 : link to documentation - added Ukrainian translation of the tutorial: українська - thanks to @ystepanoff
- Python 3.14 is now officially supported
- preserving font table
fvarto keep compatibility with variable fonts - cf. issue #1528 - issue with Markdown when fallback fonts containing non-alphanumeric characters are used - cf. issue #1535
- a bug with merging fragments of different types - cf. PR #1567 - thanks to @woopzz
- updated destination page numbers of internal links when the ToC renderer spans multiple pages - cf. PR #1566 - thanks to @woopzz
- GoTo action and add test for GoTo named destinations - cf. issue #1545
- TableOfContents class missing cell clearance on spacing calculation - cf. issue #1582
- rendering of round rectangles that caused visual distortions and incorrect filling - thanks to @Ai-Chetan - PR #1634
libtiffdetection logic to maintain compatibility with pillow v12.
- support for Python 3.9, that reached end-of-life in October 2025
- the deprecated
uniparameter fromfpdf.add_font() - the deprecated
destparameter fromfpdf.output()
- documentation on internal linking with variable page numbers
- documentation on using the Ibis library
- clarified docstring for
arc()method to documentxandyarguments (#1473) - made
numpyan optional dependency to improve the performance ofpack_codes_into_bytes()- cf. issue #1380 - macOS is now included in the GitHub Actions CI pipeline to ensure cross-platform test coverage
FPDF.write_html(): Fixed custom styling of<p>& tables - issue #1453- an
IndexErrorwas raised in some cases when rendering HTML with nested lists - cf. issue #1358 - an
IndexErrorwas raised in some cases when using text_columns() with text shaping enabled - cf. issue #1439 - handled case of a smaller last column when using text_columns() - cf. issue #1442
- minor regular-expression optimization in the SVG parsing module, nullifying any risk of ReDOS attack
- a performance issue when using
FPDF.offset_rendering()orFPDF.unbreakable()with large fonts - cf. issue #1444 - slightly invalid PDF files were produced since v2.8.3, due to path construction commands being inserted inside
BT/ETcontexts when using underline or strikethrough text - cf. issue #1456 multi_cell()text clipping bug - issue #1471- HTML lists bullets are now properly displayed when using unicode fonts - cf. issue #1496
- clarified documentation in Maths.md regarding DataFrame string conversion for PDF rendering
- children of
<a>tags in SVGs are now correctly rendered - cf. PR #1522
accept_page_breakis now only called once per page break - cf. issue #1489
- support for Python 3.8, that reached end-of-life in 2024
- added tutorial "tuto7" (in English and German) with documentation to create PDF/A files with fpdf2 - thanks to @lka
- support for Output Intents on document level - thanks to @lka
- support for shading patterns (gradients) - thanks to @andersonhc - PR #1334
- support for setting a minimal row height in tables
- support for
v_alignat the row level in tables - new optional
reset_page_indicesparameter forinsert_toc_placeholder() - support for
strikethrough text - support for
first_line_indentintext_region.Paragraph - new ViewerPreferences.print_scaling
- documentation on
fpdf2internals - documentation on generating Aztec Codes
- added Slovenian translation of the tutorial: Vodič - thanks to @DeepBlackHole
- support for adding TrueType fonts that are missing the
.notdefglyph - issue #1161 - thanks to @spacegaori - improved SVG image parsing speed by 50% to 70% - thanks to @petri-lipponen-movesense - PR #1350
TableBordersLayoutis now a non-enum class that supports customizable layouts. The members of the old enum class are now static members of the class and thus can be used as standard options using the same syntax as previously - cf. PR #957
FPDF.write_html(): Fixed rendering of content following<a>tags; now correctly resets emphasis style post</a>tag: hyperlink styling contained within the tag authority. - issue #1311- FPDF.footer() does not "leak" its text style to the table of contents anymore
FPDF.table(): Fixed heading styles containing underline failing to render.FPDF.ln(): the method now allows a value of0to be provided forh.- font optimization: only include fonts effectively used in the final PDF document. Fonts added via
set_font()oradd_page()but not actually used in the document are no longer included in the final output. This reduces file size and improves performance, especially for documents with many fallback fonts. - issue #1382 - a
KeyErrorwas raised in some specific cases when auto-downscaling images - issue #1409
- heading rows of tables are never rendered "alone" on a page anymore
- new optional parameter
borderfor table cells: users can define specific borders (left, right, top, bottom) for individual cells - thanks to @Kaustbh - issue #1192 FPDF.write_html(): now parses<title>tags to set the document title. By default, it is added as PDF metadata, but not rendered in the document body. However, this can be enabled by passingrender_title_tag=TruetoFPDF.write_html().- support for LZWDecode compression - thanks to @opposss - issue #1271
- Python 3.13 is now officially supported
- support for page labels and created a reference table of contents implementation - thanks to @andersonhc - PR #1188
- documentation on how to: render spreadsheets as PDF tables
- support for passing
Alignvalues (along with string values like'C','L','R') inl_marginofTextStyleto horizontally align text - issue #1282
- support for
align=inFPDF.table(). Due to this correction, tables are now properly horizontally aligned on the page by default. This was always specified in the documentation, but was not in effect until now. You can revert to have left-aligned tables by passingalign="LEFT"toFPDF.table(). - issue #1306 FPDF.set_text_shaping(False)was broken since version 2.7.8 and is now working properly - issue #1287- fixed bug where cells with
rowspan,colspan> 1 and null text were not displayed properly - issue #1293 CreationDatemetadata used a wrong timezone offset for UTC - issue #1261insert_toc_placeholder()did not properly set the page orientation, which caused a bug when the last page of the document was in a different orientation - issue #1312
- improved logic for handling text substitution of the total number of pages, ensuring compatibility with text shaping - issue #1090
- all
AnnotationDictproperties can now be passed toFPDF.text_annotation(),FPDF.free_text_annotation(),FPDF.add_action(),FPDF.add_text_markup_annotation()&FPDF.ink_annotation(). This includestitle,color,border_width...
- reminder : since release
2.8.1,fpdf2does not support Python 3.7, that reached end-of-life in 2023
- support for quadratic and cubic Bézier curves with
FPDF.bezier()- thanks to @awmc000 - support for escape character for markers in markdown text issue #1215
- Wrapping words on spaces now considers all common space symbols in addition to regular spaces (' '), addressing issues with word-wrapping for languages like Thai, as per #1190 and #1191.
Templatescan now be also defined in JSON files.- support to optionally set
wrapmodein templates (default"WORD"can optionally be set to"CHAR"to support wrapping on characters for scripts like Chinese or Japanese) - cf. #1159 - thanks to @carlhiggs - documentation on how to use
fpdf2with Rough.js: link to docs - documentation on how to use
fpdf2with gunicorn: link to docs - new translation of the tutorial in Türkçe, thanks to @natgho: Türkçe
- feature to identify the Unicode script of the input text and break it into fragments when different scripts are used, improving text shaping results
FPDF.image(): now handleskeep_aspect_ratioin combination with an enum value provided toxFPDF.write_html(): now supports CSS page breaks properties : documentationFPDF.write_html(): new optionalfont_familyparameter to set the default font familyFPDF.write_html(): spacing before lists can now be adjusted via thetag_stylesattribute - thanks to @lcgeneralprojects- file names are mentioned in errors when
fpdf2fails to parse a SVG image
FPDF.local_context()used to leak styling during page breaks, when renderingfooter()&header()- MR: #1207fpdf.drawing.DeviceCMYKobjects can now be passed toFPDF.set_draw_color(),FPDF.set_fill_color()andFPDF.set_text_color()without raising aValueError: documentation.FPDF.write_html(): fixing rendering of<hr>tags, that do not trigger a page break anymoreFPDF.write_html(): fixed automatic page break when an image does not have enough vertical space to be rendered on a page- individual
/Resourcesdirectories are now properly created for each document page. This change ensures better compliance with the PDF specification but results in a slight increase in the size of PDF documents. You can still use the old behavior by settingFPDF().single_resources_object = True - line size calculation for fragments when text shaping is used
FPDF.write_html(): fixed incoherent indentation of long<ul>list entries - cf. issue #1073 - thanks to @lcgeneralprojects- default values for
top_marginandbottom_margininHTML2FPDF._new_paragraph()calls are now correctly converted into chosen document units. - In text_columns(), paragraph top/bottom margins didn't correctly trigger column breaks; issue #1214
fpdf.drawing.color_from_hex_stringdid not test or mention accepting lowercase hex values.- handling of bidirectional text on
FPDF.get_string_width()[issue #1231] - new translation of the tutorial in Indonesian - thanks to @odhyp
RecursionErrorin some cases when callingFPDF.write_html()insideFPDF.footer()- issue #1222
- support for Python 3.7, that reached end-of-life in 2023
- an obscure and undocumented feature of
FPDF.write_html(), which used to magically pass instance attributes as arguments.
fpdf.TitleStylehas been renamed intofpdf.TextStyleFPDF.write_html():tag_indentsintroduced in the last version - Now the indentation can be provided through thetag_stylesparameter, using the.l_marginofTextStyleinstances
FPDF.local_context()used to treatfont_sizeas a value in points. Now this is the role offont_size_pt, whereasfont_sizeallows to set the font size into chosen document units (specified withFPDF(unit=)) - MR: #1207FPDF.circle(): the previousrparameter, that in fact defined the diameter, has been replaced by a newradiusparameter. Thex&yparameters now define the circle center, instead of its top-left corner as it used to be - issue #1245FPDF.table()now raises an error when a single row is too high to be rendered on a single pageFPDF.write_html(): indentation of HTML elements can now be non-integer (float), and is now independent of font size and bullet strings.- improved performance of font glyph selection by using functools cache
- Clarified usage of the
styleattribute inFPDF.add_font()
This version was only uploaded a few minutes on Pypi, and then deleted manually by a maintainer, erroneously fearing a regression.
Version 2.8.1 is exactly similar.
- new optional parameter
repeat_headingsforFPDF.table()that indicates whether to print table headings on every page - support for overriding paragraph direction on bidirectional text
- new optional
li_prefix_colorparameter forFPDF.write_html() - support for
start&typeattributes of<ol>tags, andtypeattribute of<ul>tags, when usingFPDF.write_html() FPDF.write_html()now accepts atag_stylesparameter to control the font, color & size of HTML elements:<a>,<blockquote>,<li>...FPDF.write_html()now accepts atag_indentsparameter to control, for example, the indent of<blockquote>elementsFPDF.write_html()now honorsline-heightattributes on<ol>&<li>elements, or the same CSS property instyleattributes on those tags- allow to define custom
cell_fill_modelogic for tables: Set cells background - documentation section. Also added 2 new values:TableCellFillMode.EVEN_ROWS&TableCellFillMode.EVEN_COLUMNS: documentation
- a bug when rendering vector images with dashed lines that caused a warning message in Adobe Acrobat Reader
- ordering RTL fragments on bidirectional texts
- fixed type hint of member
levelin classOutlineSectionfromstrtoint. - SVG clipping paths being incorrectly painted - cf. issue #1147
- new translation of the tutorial in Polski - thanks to @DarekRepos
- improved the performance of
FPDF.start_section()- thanks to @dmail00 - cf. issue #1092
- The
dd_tag_indent&li_tag_indentparameters ofFPDF.write_html()are replaced by the newtag_indentsgeneric parameter. - The
heading_sizes&pre_code_fontparameters ofFPDF.write_html()are replaced by the newtag_stylesgeneric parameter.
- support for
<path>elements in SVG<clipPath>elements - support for
bidirectionaltext shaping - thanks to @andersonhc - documentation on how to combine
fpdf2with mistletoe in order to generate PDF documents from Markdown (link) - support for
Tablecells that span multiple rows via therowspanattribute, which can be combined withcolspan- thanks to @mjasperse TableSpan.COLandTableSpan.ROWenums that can be used as placeholder table entries to identify span extents - thanks to @mjasperse- support for SVG
<text>elements
- when adding a link on a table cell, an extra link was added erroneously on the left. Moreover, now
FPDF._disable_writing()properly disable link writing. FPDF.write_html()now handles linking directly to other pages - thanks to @mjasperse- non-bold
TitleStyleis now rendered as non-bold even when the current font is bold - calling
.table()inside therender_toc_function - using
.set_text_shaping(True)&.offset_rendering() - fixed gutter handing when a pagebreak occurs within a table with header rows - thanks to @mjasperse
- fixed handling of
border=0in HTML table - thanks to @mjasperse FPDF.write_html()now properly honorsalign=attributes in<th>tags- fixed problem using bold italic standard fonts in markdown - thanks to @Alan-Collins
- refactored
FPDF.multi_cell()to generate fewer PDF component objects - thanks to @mjasperse - outer table borders are now drawn continuously for nonzero
gutter_width/gutter_height, with spacing applied inside the border similar to HTML tables - thanks to @mjasperse - cf. #1071 - removed the requirement that all rows in a
Tablehave the same number of columns - thanks to @mjasperse
- font aliases (
Arial→Helvetica,CourierNew→Courier,TimesNewRoman→Times). They will be removed in a later release.
- Basic support for
<image>elements in SVG vector graphics inserted - SVG importing now supports clipping paths, and
<defs>tags anywhere in the SVG file - thanks to @afriedman412 - cf. #968 FPDF.fonts.FontFace: Now has a staticcombinemethod that allows overriding a default FontFace (e.g. for specific cells in a table). Unspecified properties of the override FontFace retain the values of the default - thanks to @TedBrookings - cf. #979TextColumns()can now have images inserted (both raster and vector) - thanks to @gmischlerTextColumns()can now advance to the next column with the newnew_column()method or a FORM_FEED character (\u000c) in the text - thanks to @gmischler- Added support for Free Text annotations: documentation - thanks to @MarekT0v - cf. #1039
- Tutorial in Dutch: Handleiding - thanks to @Polderrider
- Python 3.12 is now officially supported
- Links over text in tables were broken in release 2.7.6, this is now fixed
FPDF.set_font_color()raised aTypeErrorwhen used in tablesFPDF.image(x=Align.C)used to fail for SVG images - fixed thanks to @gmischler - cf. #1003- Previously set dash patterns were not transferred correctly to new pages - fixed thanks to @gmischler - cf. #993
- Inserted Vector images used to ignore the
keep_aspect_ratioargument. FPDF.write_html()now properly honor the current text font color when styling table cellsFPDF.write_html()delays unescaping data so as not to confuse entity names as nested tagsFPDF.multi_cell()has improved handling ofnew_xandnew_ywhenpaddingis non-zero.FPDF.multi_cell(fill=True)now avoids overlapping multiline strings whenpaddingis non-zero.
- the public
.images,.icc_profiles&.image_filterattributes ofFPDFinstances have been moved inside a nestedFPDF.image_cacheattribute. Similarly, theFPDF.preload_image()is now a function in thefpdf.image_parsingmodule: documentation - the
fpdf.svgmodule now producesWARNINGlog messages for unsupported SVG tags & attributes. If those logs annoy you, you can suppress them:logging.getLogger("fpdf.svg").propagate = False FPDF.table(): If cell styles are provided for cells in heading rows, combine the cell style as an override with the overall heading style.
This release is the first performed from the @py-pdf GitHub org, where fpdf2 migrated.
This release also marks the arrival of two new maintainers: Georg Mischler (@gmischler) and Anderson Herzogenrath da Costa (@andersonhc).
- The new experimental method
text_columns()allows to render text within a single or multiple columns, including height balancing: documentation - thanks to @gmischler FPDF.table(): Now supports padding in cells : documentation - thanks to @RubendeBruinFPDF.table(): Now supports vertical alignment in cells : documentation - thanks to @RubendeBruinFPDF.table(): Now supports outer border width for rendering the outer border of the table with a different line-width - thanks to @RubendeBruinFPDF.table(): Now supports multiple heading rows : documentation - thanks to @SandraFerFPDF.write_html()now supports heading colors defined as attributes (e.g.<h2 color="#00ff00">...) - thanks to @Lucas-C- documentation on how to use
livereloadto enable a "watch" mode while performing PDF generation: Combine with livereload - thanks to @Lucas-C
FPDF.write_html(): the formatting output has changed in some aspects. Vertical spacing around headings and paragraphs may be slightly different, and elements at the top of the page don't have any extra spacing above anymore.FPDF.table(): If the height of a row is governed by an image, then the default vertical alignment of the other cells is "center". This was "top".- variable-width non-breaking space (NBSP) support issue #834 This change was made for consistency between row-height governed by text or images. The old behaviour can be enforced using the new vertical alignment parameter.
FPDF.table()&FPDF.multi_cell(): when some horizontal padding was set, the text was not given quite enough space - thanks to @gmischlerFPDF.write_html()can now handle formatting tags within paragraphs without adding extra line breaks (except in table cells for now) - thanks to @gmischlerFPDF.write_html(): the font size in HTML<pre>and<code>tags is not fixed to 11 pica anymore, but adapts to the preceding text - thanks to @gmischlerFPDF.ln(), when called before any text has been written, will now use the current font height instead of doing nothing - thanks to @gmischler - cf. issue #937FPDF.image(), when provided aBytesIOinstance, does not close it anymore - cf. issue #881 - thanks to @Lucas-C- Invalid characters were being generated when a string contains parentheses - thanks to @andersonhc - cf. issue #884
- Frozen Glyph dataclass was causing problems for FPDFRecorder with TTF fonts - thanks to @andersonhc - cf. issue #890
- Edge case when parsing a Markdown link followed by a newline - cf. issue #916, and when bold/italics/underline markers are repeated
- Zoom not set correctly when a numeric value was set in
set_display_mode()- cf. issue #926 FPDF.table(): images no longer overlap with cell borders - thanks to @RubendeBruin - cf. issue #892- Encryption of strings containing non-latin characters - thanks to @andersonhc - cf. issue #933
- Handling of fragments with zero-length - thanks to @SaiHarshaK - cf. issue #902
- to improve naming consistency, the
txtparameters ofFPDF.cell(),FPDF.multi_cell(),FPDF.text()&FPDF.write()have been renamed totext
FPDF.set_text_shaping(): new method to perform text shaping using Harfbuzz - documentation - thanks to @andersonhc in PR #820FPDF.mirror()- New method: documentation page - Contributed by @sebastiantiaFPDF.table(): new optional parametersgutter_height,gutter_widthandwrapmode. Links can also be added to cells by passing alinkparameter toRow.cell()FPDF.multi_cell(): has a new optionalcenterparameter to position the cell horizontally at the center of the page- New AES-256 encryption: documentation - thanks to @andersonhc in PR #872
- Added tutorial in Khmer language: ភាសខ្មែរ - thanks to @kuth-chi
- Added tutorial in 日本語 - thanks to @alcnaka
- Better documentation & errors when facing HTML rendering limitations for
<table>tags: https://py-pdf.github.io/fpdf2/HTML.html
FPDF.table(): thecolspansetting has been fixed - documentationFPDF.image(): allowing images path starting withdatato be passed as input- text overflow is better handled by
FPDF.write()&FPDF.write_html()- cf. issue #847 - the initial text color is preserved when using
FPDF.write_html()- cf. issue #846 - PDF metadata not encrypted - cf. issue #865
- handle superscript and subscript correctly when rendering
TextLine- thanks to @Tolker-KU - cf. Pull Request #862 - make sure warnings always point to the users code - cf. Pull request #869
- the
centeroptional parameter ofFPDF.cell()is no more deprecated, as it allows for horizontal positioning, which is different from text alignment control withalign="C"
FPDF.image(): CMYK images can now be inserted directly by passing them into the image method. Contributed by @devdev29- documentation on how to embed
graphsandchartsgenerated usingPygallib: documentation section - thanks to @ssavi-ict - documentation on how to use
fpdf2with FastAPI: https://py-pdf.github.io/fpdf2/UsageInWebAPI.html#FastAPI - thanks to @KamarulAdha FPDF.write_html():<table>elements can now be aligned left or right on the page usingalign=FPDF.write_html(): a custom font can now be specified for<code>&<pre>elements, using the new optional parameterpre_code_font
FPDF.table(): images no more overflow cellsFPDF.table(): text overflow in the last cell of the header row is now properly handledFPDF.table(): whenalign="RIGHT"is provided, the page right margin is now properly taken in consideration
FPDF.write_html()does not render the top row as a header, in bold with a line below, when no<th>are used, in order to be more backward-compatible with earlier versions offpdf2- cf. #740
- the
split_onlyoptional parameter ofFPDF.multi_cell(), which is replaced by two new distincts optional parameters:dry_run&output
- removed a debug
print()statement left inoutput.py:OutputProducer._add_fonts()🤦♂️ - A rule was also added to.pre-commit-config.yamlto avoid this to happen again.
- custom fonts can be used with
FPDF.table()without triggering aTypeError: cannot pickle 'dict_keys' object- thanks @aeris07 for the bug report - the SVG parser now accepts
<rect>withwidth/heightdefined as percents
- documentation on how to generate Code128 barcodes using the
python-barcodelib: documentation section
- renamed
fonts.FontStyletofonts.FontFace, andFPDF.use_font_styletoFPDF.use_font_face, to avoid confusions withFPDF.font_style - new translation of the tutorial in বাংলা - thanks to @ssavi-ict
- new method
FPDF.table(): documentation FPDF.image()has a newkeep_aspect_ratiooptional boolean parameter, to fit it inside a given rectangle: documentationFPDF.multi_cell()andFPDF.write()now accept awrapmodeargument for word or character based line wrapping ("WORD"/"CHAR"), thanks to @gmischler- new method
FPDF.set_fallback_fonts()allow alternative fonts to be provided if a character on the text is not available on the currently set font - thanks to @andersonhc - for inserted images that have an ICC Profile, this profile is now extracted and embedded; they should now be honored by PDF viewers - thanks to @eroux
- new methods:
FPDF.preload_image()&FPDF.use_font_style() - new translation of the tutorial in 简体中文 - thanks to @Bubbu0129
- documentation on how to embed static Plotly charts: link to docs
- additional linter / static code analyser in GitHub Actions CI pipeline: semgrep
- outlines & hyperlinks were not working on encrypted files - thanks to @andersonhc
- a bug was introduced in the previous release (2.6.1):
FPDF.set_link()could not update links generated withadd_link() - unicode (non limited to ASCII) text can now be provided as metadata #685
- all
TitleStyleconstructor parameters are now effectively optional - memory usage was reduced by 10 MiB in some cases, thanks to a small optimization in using
fonttools
FPDF.write_html()now uses the newFPDF.table()method to render<table>tags. As a consequence, vertical space before<table>tags has sometimes been reduced.
- vector images parsing is now more robust:
fpdf2can now embed SVG files withoutviewPortor noheight/width - bitonal images are now encoded using
CCITTFaxDecode, reducing their size in the PDF document - thanks to @eroux - when possible, JPG and group4 encoded TIFFs are now embedded directly without recompression - thanks to @eroux
FPDF.write_html()now uses the newFPDF.table()method to render<table>tags. As a consequence, it does not support theheightattribute defined on<td>/<th>tags anymore, norheight/widthattributes defined on<img>tags inside cells, norwidthattributes defined on<thead>/<tfoot>tags.
- support for PDF encryption (RC4 and AES-128): documentation page - thanks to @andersonhc
FPDF.skew()- New method: documentation page - thanks to @erap129- ensured support for Python 3.11
FPDF.image(): thexparameter now accepts a value of"C"/Align.C/"R"/Align.Rto horizontally position the image centered or aligned rightFPDF.image(): dimensions can now be provided to set the intrinsic image width & height before storing it in the PDFFPDF.cell()&FPDF.multi_cell(): support for[]()hyperlinks whenmarkdown=TrueFPDF.write_html(): support forline-heightattribute of paragraph (<p>) - thanks to @Bubbu0129- documentation on useful tools to manipulate PDFs
- show a warning if the font being used doesn't have all the necessary glyphs for the text - thanks to @andersonhc
FPDF.add_link()creates a link to the current page by default, and now accepts optional parameters:x,y,page&zoom. Hence callingset_link()is not needed anymore after creating a link withadd_link().FPDF.write_html()now generates warnings for unclosed HTML tags, unlesswarn_on_tags_not_matching=Falseis set
FPDF.write_html(): aValueError: Incoherent hierarchycould be raised with some headings hierarchyFPDF.write_html():<img>withoutheightattribute overlaps with the following content #632 - thanks to @Bubbu0129FPDF.image(): performance issue with adding large images withFlateDecodeimage filter #644 - thanks to @Markovvn1FPDF.add_font(): fix support for upper case font file name #638 - thanks to @CY-Qiu
- demonstration Jupyter notebook: tutorial/notebook.ipynb
- new
.default_page_dimensionsproperty onFPDFinstances - support for description list (
<dl>), description titles (<dt>), description details (<dd>) and code blocks (<code>) inwrite_html()- thanks to @yk-jp & @seanpmulholland - support for monochromatic images (PIL
image.mode == '1') thanks to @GerardoAllende - the 1000+ unit tests suite is now executed under Linux and Windows, with extra timing & memory usage checks ensuring we control
fpdf2resource usage - new translation of the tutorial in עברית, thanks to @TzviGreenfeld
- new documentation for using PyPDF2 with
fpdf2, added by @devdev29: https://py-pdf.github.io/fpdf2/CombineWithPyPDF2.html - new documentation for using Jinja with
fpdf2: https://py-pdf.github.io/fpdf2/TemplatingWithJinja.html
HTMLMixinis deprecated, and not needed anymore: thewrite_html()method is now natively available in theFPDFclass - thanks to @yk-jp
open()&close()methods, that were only used internally and should never have been called by end-user codeFPDF.state, which was an instance of theDocumentStateenum, and has been replaced by moving the final rendering logic into a newfpdf.outputmodule
- after an "empty"
cell(),ln()applied a line height of zero #601 - when using
multi_cell()withmax_line_heightto render multiline text, the last line is now rendered like all the others - templates don't leak graphics state changes to their surroundings anymore; #570
- automatic page break is never performed on an empty page (when the Y position is at the top margin)
- fixed
insert_toc_placeholder()usage withfooter()and{{nb}}; #548 - the SVG parser now accepts
stroke-widthattribute values with an explicit unit, thanks to @gmischler; #526 - the SVG parser now accepts absolute units for
widthandheightattributes, thanks to @darioackermann; #555 write_html()method now correctly handles whitespace when parsing HTML.<pre></pre>blocks still maintain spaces, tabs and line breaks.
- the first parameter of
FPDF.add_font()is now optional: if it is not provided, the base name of thefnamefont path is used to define the font family. Hencepdf.add_font(fname="fonts/NotoSansArabic.ttf")will define a font namedNotoSansArabic. - the output of
embed_file()is now aPDFEmbeddedFile, not a string, but the internal file name can be retrieved through its.basenameproperty - forbid use of
get_y()&local_context()insideunbreakable()as it is currently not supported; #557 - fontTools minimal version requirement set to 4.34.0; #524
- support for subscript, superscript, nominator and denominator char positioning as well as
<sub>and<sup>HTML tags, thanks to @gmischler: link to documentation set_page_background(): new method added by @semaeostomea: link to documentationembed_file()&file_attachment_annotation(): new methods to add file attachments - link to documentation- a new method
set_char_spacing()allows to increase the spacing between individual characters, thanks to @gmischler: link to documentation - workaround by @semaeostomea to support arabic and right-to-left scripts: link to documentation
- documentation on shapes styling: link to documentation
- documentation on sharing the images cache among FPDF instances: link to documentation
- HTML headings are now rendered with an additional leading of 20% the font size above and below them; #520
fpdf2now uses fontTools to read and embed fonts in the PDF, thanks to @gmischler and @RedShy- since the fonttools library offers similar functionality, the dependency to "svg.path" is gone again, thanks to @gmischler; #525
- text following a HTML heading can't overlap with that heading anymore, thanks to @gmischler
arc()not longer renders artefacts at intersection point, thanks to @Jmillan-Dev; #488write_html():- the
CreationDateof PDFs & embedded files now includes the system timezone
- new methods to allow signing PDF documents: link to docs
- support for colors defined with the
rgb()syntax in SVG images - cf. #480 - New translation of the tutorial in Ελληνικά, thanks to @sokratisvas
- an
/IDis now inserted in the trailer dictionary of all PDF documents generated. This ID can be controlled through the new file_id() method. - the svg.path package was added as a dependency to better parse SVG images
font_stretchingdoesn't make text spill out ofmulti_cell()andwrite()boundaries anymore, thanks to @gmischlerlocal_context()now always restores the correct font settings after finishing, thanks to @gmischler- properly parsing single-digits arguments in SVG paths - cf. #450
- document outline encoding: it was found to be broken when using a thai font - cf. #458
- a new option
align="X"to.cell()and.multi_cell()allows to center text around the current x position, thanks to @gmischler - allowing to provide an
AnnotationNameandAnnotationFlagsonto text_annotation() - allowing correctly parsing of SVG files with CSS styling (
style="..."attribute), thanks to @RedShy FPDF.star(): new method added to draw regular stars, thanks to @digidigital and @RedShyFPDF.ink_annotation(): new method added to add path annotations- allowing embedding of indexed PNG images without converting them to RGB colorspace, thanks to @RedShy
- allowing to change appearance of highlight annotations by specifying a
TextMarkupType - documentation on how to control objects transparency: link to docs
- documentation on how to create tables and charts using pandas DataFrames: link to docs, thanks to @iwayankurniawan
- added argument
round_cornerstoFPDF.rect()that allows to draw rectangles with round corners: link to docs - thanks to @gonzalobarbaran
FPDF.add_highlight()as been renamed intoFPDF.highlight()
- support for
"x"&"y"attributes in SVG<use>tags - cf. #446 CreationDateof PDFs generated, that was broken - cf. #451multi_cell()andwrite()ignored a trailing newline character in the supplied text since 2.5.1 - fixed thanks to @gmischler
- new
FPDF.page_modeproperty, allowing to display a PDF automatically in full screen: link to docs - new
FPDF.viewer_preferencesproperty: link to docs
- removed a debug
print()statement (multi_cell: new_x=... new_y=...) that had been left in multi_cell() method 🤦♂️ - preserved backward compatibility with PyFPDF for passing positional arguments to
cell()&multi_cell(), which was broken in 2.5.2
- when
regular_polygon()is called withstyle="f", the shape outline is not drawn anymore. Usestyle="DF"to also draw a line around its perimeter.
- the
fillparameter of thepolygon()&polyline()methods have been replaced by astyleargument, offering more control
- new
round_clip()&elliptic_clip()image clipping methods: link to docs CoerciveEnumsubclasses have been added:Align&RenderStyle- documentation on how to embed Matplotlib charts: link to docs
- documentation on how to use
fpdf2with Flask, streamlit, AWS lambdas: link to docs - documentation on how to store PDFs in a database with SQLAlchemy: link to docs
TextMode,XPos&YPosnow inherit fromCoerciveEnumand hence can simply be passed as string parameters
- infinite loop when calling
.multi_cell()without enough horizontal space - cf. #389
- support for
.pklfiles passed toadd_font(). This was deprecated since v2.5.1. As a consequence,fpdf2no more uses thepicklemodule \o/
- new parameters
new_xandnew_yforcell()andmulti_cell(), replacingln=0, thanks to @gmischler - new
highlight()method to insert highlight annotations: documentation - new
offset_rendering()method: documentation - new
.text_modeproperty: documentation - the page structure of the documentation has been revised, with a new page about adding text, thanks to @gmischler
- a warning is now raised if a context manager is used inside an
unbreakable()section, which is not supported
local_context()can now "scope" even more properties, likeblend_mode: documentation
- No font properties should be leaked anymore after using markdown or in any other situations (cf. #359), thanks to @gmischler
- If
multi_cell(align="J")is given text with multiple paragraphs (text followed by an empty line) at once, it now renders the last line of each paragraph left-aligned, instead of just the very last line (cf. #364), thanks to @gmischler - a regression: now again
multi_cell()always renders a cell, even iftxtis an empty string - cf. #349 - a bug with string width calculation when Markdown is enabled - cf. #351
- a few bugs when parsing some SVG files - cf. #356, #358 & #376
- a bug when using
multi_cell(..., split_only=True)inside anunbreakablesection - cf. #359
- The parameter
lntocell()andmulti_cell()is now deprecated: usenew_xandnew_yinstead. - The parameter
centertocell()is now deprecated, usealign="C"instead.
- The documentation outline is revised, and a page about creating Text added, thanks to @gmischler
- support for soft-hyphen (
\u00ad) break inwrite(),cell()&multi_cell()calls - thanks @oleksii-shyman & @gmischler! Documentation: Line breaks - new documentation page on Emojis, Symbols & Dingbats
- documentation on combining
borb&fpdf2: Creating a borb.pdf.document.Document from a FPDF instance
write()now supports soft hyphen characters, thanks to @gmischlerfnameis now a required parameter forFPDF.add_font()image()method now insert.svgimages as PDF paths- the defusedxml package was added as dependency in order to make SVG parsing safer
- log level of
_substitute_page_number()has been lowered fromINFOtoDEBUG
- a bug when rendering Markdown and setting a custom
text_colororfill_color - a bug in
get_string_width()with unicode fonts and Markdown enabled, resulting in calls tocell()/multi_cell()withalign="R"to display nothing - thanks @mcerveny for the fix! - a bug with incorrect width calculation of markdown text
- the font caching mechanism, that used the
picklemodule, has been removed, for security reasons, and because it provided little performance gain, and only for specific use cases - cf. issue #345. That means that thefont_cache_diroptional parameter offpdf.FPDFconstructor and theunioptional argument ofFPDF.add_font()are deprecated. Thefpdf.fpdf.load_cachefunction has also been removed.
To be extra clear: uni=True can now be removed from all calls to FPDF.add_font().
If the value of the fname argument passed to add_font() ends with .ttf, it is considered a TrueType font.
Thanks to @torque for contributing this massive new feature:
- add
fpdf.drawingAPI for composing paths from an arbitrary sequence of lines and curves. - add
fpdf.svg.convert_svg_to_drawingfunction to support converting basic scalable vector graphics (SVG) images to PDF paths.
will_page_break()&accept_page_breakare not invoked anymore during a call tomulti_cell(split_only=True)- Unicode characters in headings are now properly displayed in the table of content, cf. #320 - thanks @lcomrade
-
New
FPDF.pages_countproperty, thanks to @paulacampigotto -
Temporary changes to graphics state variables are now possible using
with FPDF.local_context():, thanks to @gmischler -
a mechanism to detect & downscale oversized images, cf. documentation. Feedbacks on this new feature are welcome!
-
New
set_dash_pattern(), which works with all lines and curves, thanks to @gmischler. -
Templates now support drawing ellipses, thanks to @gmischler
-
New documentation on how to display equations, using Google Charts or
matplotlib: Maths -
The whole documentation can now be downloaded as a PDF: fpdf2-manual.pdf
-
New sections have been added to the tutorial, thanks to @portfedh:
-
New translation of the tutorial in Hindi, thanks to @Mridulbirla13: हिंदी संस्करण; Deutsch, thanks to @digidigital; and Italian thanks to @xit4; Русский thanks to @AABur; and português thanks to @fuscati; français, thanks to @Tititesouris
-
While images transparency is still handled by default through the use of
SMask, this can be disabled by settingpdf.allow_images_transparency = Falsein order to allow compliance with PDF/A-1 -
FPDF.arc: new method added. It enables to draw arcs in a PDF document. -
FPDF.solid_arc: new method added. It enables to draw solid arcs in a PDF document. A solid arc combines an arc and a triangle to form a pie slice. -
FPDF.regular_polygon: new method added, thanks to @bettman-latin
- All graphics state manipulations are now possible within a rotation context, thanks to @gmischler
- The exception making the "x2" template field optional for barcode elements did not work correctly, fixed by @gmischler
- It is now possible to get back to a previous page to add more content, e.g. with a 2-column layout, thanks to @paulacampigotto
- All template elements now have a transparent default background instead of white, thanks to @gmischler
- To reduce the size of generated PDFs, no
SMaskentry is inserted for images that are fully opaque (= with an alpha channel containing only 0xff characters) - The
rect,ellipse&circleall have astyleparameter in common. They now all properly accept a value of"D"and raise aValueErrorfor invalid values.
dashed_line()is now deprecated in favor ofset_dash_pattern()
- ensure support for old field names in
Template.code39for backward compatibility
Template()has gained a more flexible cousinFlexTemplate(), cf. documentation, thanks to @gmischler- markdown support in
multi_cell(), thanks to Yeshi Namkhai - base 64 images can now be provided to
FPDF.image, thanks to @MWhatsUp - documentation on how to generate datamatrix barcodes using the
pystrichlib: documentation section, thanks to @MWhatsUp write_html: headings (<h1>,<h2>...) relative sizes can now be configured through an optionalheading_sizesparameter- a subclass of
HTML2FPDFcan now easily be used by settingFPDF.HTML2FPDF_CLASS, cf. documentation
Template:split_multicell()will not write spurious font data to the target document anymore, thanks to @gmischlerTemplate: rotation now should work correctly in all situations, thanks to @gmischlerwrite_html: headings (<h1>,<h2>...) can now contain non-ASCII characters without triggering aUnicodeEncodeErrorTemplate: CSV column types are now safely parsed, thanks to @gmischlercell(..., markdown=True)"leaked" its final style (bold / italics / underline) onto the following cells
write_html: the line height of headings (<h1>,<h2>...) is now properly scaled with its font size- some
FPDFmethods should not be used inside arotationcontext, or things can get broken. This is now forbidden: an exception is now raised in those cases.
Template:code39barcode input field names changed fromx/y/w/htox1/y1/y2/size
- support for emojis! More precisely unicode characters above
0xFFFFin general, thanks to @moe-25 Templatecan now insert justified textget_scale_factorutility function to obtainFPDF.kwithout having to create a documentconvert_unitutility function to convert a number,x,ypoint, or list ofx,ypoints from one unit to another unit
fpdf.FPDF()constructor now accepts ints or floats as a unit, and raises aValueErrorif an invalid unit is provided.
Templatebackgroundproperty is now properly supported - #203⚠️ Beware that its default value changed from0to0xffffff, as a value of zero would render the background as black.Template.parse_csv: preserving numeric values when using CSV based templates - #205- the code snippet to generate Code 39 barcodes in the documentation was missing the start & end
*characters. This has been fixed, and a warning is now triggered by theFPDF.code39method when those characters are missing.
- Detect missing
uni=Truewhen loading cached fonts (page numbering was missing digits)
- disable font caching when
fpdf.FPDFconstructor invoked withfont_cache_dir=None, thanks to @moe-25 ! FPDF.circle: new method added, thanks to @viraj-shah18 !write_html: support setting HTML font colors by name and short hex codesFPDF.will_page_breakutility method to let users know in advance when adding an element will trigger a page break. This can be useful to repeat table headers on each page for example, cf. documentation on Tables.FPDF.set_linknow support a new optionalxparameter to set the horizontal position after following the link
- fixed a bug when
fpdf.Templatewas used to render QRCodes, due to a forced conversion to string (#175)
- erroneous page breaks occurred for full-width / full-height images
- rendering issue of non-ASCII characters with unicode fonts
- now
fpdf2uses the newly supportedDCTDecodeimage filter for JPEG images, instead ofFlateDecodebefore, in order to improve the compression ratio without any image quality loss. On test images, this reduced the size of embedded JPEG images by 90%. FPDF.cell: thew(width) parameter becomes optional, with a default value ofNone, meaning to generate a cell with the size of the text content provided- the
h(height) parameter of thecell,multi_cell&writemethods gets a default value change,None, meaning to use the current font size - removed the useless
w&hparameters of theFPDF.text_annotation()method
- new
FPDF.add_action()method, documented in the Annotations section FPDF.cell: new optionalmarkdown=Trueparameter that enables basic Markdown-like styling:**bold**, __italics__, --underlined--FPDF.cell: new optional booleancenterparameter that positions the cell horizontallyFPDF.set_link: new optionalzoomparameter that sets the zoom level after following the link. Currently ignored by Sumatra PDF Reader, but observed by Adobe Acrobat reader.write_html: now supportalign="justify"- new method
FPDF.image_filterto control the image filters used for images FPDF.add_page: new optionalduration&transitionparameters used for presentations (documentation page)- extra documentation on how to configure different page formats for specific pages
- support for Code 39 barcodes in
fpdf.template, usingtype="C39"
- avoid an
Undefined fonterror when usingwrite_htmlwith unicode bold or italics fonts
- the
FPDF.set_doc_option()method is deprecated in favour of just setting thecore_fonts_encodingproperty on an instance ofFPDF - the
fpdf.SYSTEM_TTFONTSconfigurable module constant is now ignored
- a bug in the
deprecationmodule that prevented to configurefpdf2constants at the module level
- a "fake duplicates" bug when a
Pillow.Image.Imagewas passed toFPDF.image
- new features: document outline & table of contents! Check out the new dedicated documentation page for more information
- new method
FPDF.text_annotationto insert... Text Annotations FPDF.imagenow also accepts anio.BytesIOas input
write_html: properly handling<img>inside<td>& allowing to center them horizontally
FPDF.set_xmp_metadata- made
<li>bullets & indentation configurable through class attributes, instance attributes or optional method arguments, cf.test_customize_ul
FPDF.multi_cell: line wrapping with justified content and unicode fonts, cf. #118FPDF.multi_cell: whenln=3, automatic page breaks now behave correctly at the bottom of pages
FPDF.polyline&FPDF.polygon: new methods added by @uovodikiwi - thanks!FPDF.set_margin: new method to set the document right, left, top & bottom margins to the same value at onceFPDF.imagenow accepts new optionaltitle&alt_textparameters defining the image title and alternative text describing it, for accessibility purposesFPDF.linknow honor itsalt_textoptional parameter and this alternative text describing links is now properly included in the resulting PDF document- the document language can be set using
FPDF.set_lang
FPDF.unbreakableso that no extra page jump is performed whenFPDF.multi_cellis called inside this context
fpdf.FPDF_CACHE_MODE&fpdf.FPDF_CACHE_DIRin favor of a configurable newfont_cache_diroptional argument of thefpdf.FPDFconstructor
Many thanks to @eumiro & @fbernhart for their contributions to make fpdf2 code cleaner!
FPDF.unbreakable: a new method providing a context-manager in which automatic page breaks are disabled. cf. https://py-pdf.github.io/fpdf2/PageBreaks.htmlFPDF.epw&FPDF.eph: new@propertymethods to retrieve the effective page width / height, that is the page width / height minus its horizontal / vertical margins.FPDF.imagenow accepts also aPillow.Image.Imageas inputFPDF.multi_cellparameters evolve in order to generate tables with multiline text in cells:- its
lnparameter now accepts a value of3that sets the new position to the right without altering vertical offset - a new optional
max_line_heightparameter sets a maximum height of each sub-cell generated
- its
- new documentation pages : how to add content to existing PDFs, HTML, links, tables, text styling & page breaks
- all PDF samples are now validated using 3 different PDF checkers
FPDF.alias_nb_pages: fixed this feature that was broken since v2.0.6FPDF.set_font: fixed a bug where calling it several times, with & without the same parameters, prevented strings passed first to the text-rendering methods to be displayed.
- the
destparameter ofFPDF.outputmethod
- new unit tests, a code formatter (
black) and a linter (pylint) to improve code quality - new boolean parameter
table_line_separatorsforwrite_html& underlyingHTML2FPDFconstructor
- the documentation URL is now simply https://py-pdf.github.io/fpdf2/
- dropped support for external font definitions in
.fontPython files, that relied on a call toexec
- the
typeparameter ofFPDF.imagemethod - the
infileparameter ofTemplateconstructor - the
destparameter ofTemplate.rendermethod
- Making FPDF.output() x100 time faster by using a bytearray buffer
- Fix user's font path (issue PR)
- Fixing #159 issue with set_link + adding GitHub Actions pipeline & badges
User defined path to font is ignored
- non-necessary dependency on
numpy - support for Python 2
- Python 3.9 is now supported
- new specific exceptions:
FPDFException&FPDFPageFormatException - tests to increase line coverage in
image_parsingmodule - a test which uses most of the HTML features
- handling of fonts by the HTML mixin (weight and style) - thanks
cgfrost!
- images centering - thanks
cgfrost! - added missing import statement for
urlopeninimage_parsingmodule - changed urlopen import from
sixlibrary to maintain python2 compatibility
- Ability to use a
BytesIObuffer directly. This can simplify loadingmatplotlibplots into the PDF.
load_resourcenow return argument if type isBytesIO, else load.
- introduced a dependency to
numpyto improve performances by replacing pixel regexes in image parsing (s/o @pennersr)
- support for more recent Python versions
- more documentation
- PDF syntax error when version is > 1.3 due to an invalid
/Transparencydict
- turned
accept_page_breakinto a property - unit tests now use the standard
unittestlib - massive code cleanup using
flake8