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)
.
- new optional parameter
border
for 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=True
toFPDF.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
Align
values (along with string values like'C'
,'L'
,'R'
) inl_margin
ofTextStyle
to 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 CreationDate
metadata used a wrong timezone offset for UTC - issue #1261insert_toc_placeholder()
did not properly 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
AnnotationDict
properties 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
,fpdf2
does 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.
Templates
can now be also defined in JSON files.- support to optionally set
wrapmode
in 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
fpdf2
with Rough.js: link to docs - documentation on how to use
fpdf2
with 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_ratio
in combination with an enum value provided tox
FPDF.write_html()
: now supports CSS page breaks properties : documentationFPDF.write_html()
: new optionalfont_family
parameter to set the default font familyFPDF.write_html()
: spacing before lists can now be adjusted via thetag_styles
attribute - thanks to @lcgeneralprojects- file names are mentioned in errors when
fpdf2
fails to parse a SVG image
FPDF.local_context()
used to leak styling during page breaks, when renderingfooter()
&header()
- MR: #1207fpdf.drawing.DeviceCMYK
objects 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
/Resources
directories 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_margin
andbottom_margin
inHTML2FPDF._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_string
did 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
RecursionError
in 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.TitleStyle
has been renamed intofpdf.TextStyle
FPDF.write_html()
:tag_indents
introduced in the last version - Now the indentation can be provided through thetag_styles
parameter, using the.l_margin
ofTextStyle
instances
FPDF.local_context()
used to treatfont_size
as a value in points. Now this is the role offont_size_pt
, whereasfont_size
allows to set the font size into chosen document units (specified withFPDF(unit=)
) - MR: #1207FPDF.circle()
: the previousr
parameter, that in fact defined the diameter, has been replaced by a newradius
paremeter. Thex
&y
parameters 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
style
attribute 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_headings
forFPDF.table()
that indicates whether to print table headings on every page - support for overriding paragraph direction on bidirectional text
- new optional
li_prefix_color
parameter forFPDF.write_html()
- support for
start
&type
attributes of<ol>
tags, andtype
attribute of<ul>
tags, when usingFPDF.write_html()
FPDF.write_html()
now accepts atag_styles
parameter to control the font, color & size of HTML elements:<a>
,<blockquote>
,<li>
...FPDF.write_html()
now accepts atag_indents
parameter to control, for example, the indent of<blockquote>
elementsFPDF.write_html()
now honorsline-height
attributes on<ol>
&<li>
elements, or the same CSS property instyle
attributes on those tags- allow to define custom
cell_fill_mode
logic 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
level
in classOutlineSection
fromstr
toint
. - 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_indent
parameters ofFPDF.write_html()
are replaced by the newtag_indents
generic parameter. - The
heading_sizes
&pre_code_font
parameters ofFPDF.write_html()
are replaced by the newtag_styles
generic parameter.
- support for
<path>
elements in SVG<clipPath>
elements - support for
bidirectional
text shaping - thanks to @andersonhc - documentation on how to combine
fpdf2
with mistletoe in order to generate PDF documents from Markdown (link) - support for
Table
cells that span multiple rows via therowspan
attribute, which can be combined withcolspan
- thanks to @mjasperse TableSpan.COL
andTableSpan.ROW
enums that can be used as placeholder table entries to identify span extents - thanks to @mjasperse
- 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
TitleStyle
is 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=0
in 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
Table
have 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 staticcombine
method 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 aTypeError
when 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_ratio
argument. 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_x
andnew_y
whenpadding
is non-zero.FPDF.multi_cell(fill=True)
now avoids overlapping multiline strings whenpadding
is non-zero.
- the public
.images
,.icc_profiles
&.image_filter
attributes ofFPDF
instances have been moved inside a nestedFPDF.image_cache
attribute. Similarly, theFPDF.preload_image()
is now a function in thefpdf.image_parsing
module: documentation - the
fpdf.svg
module now producesWARNING
log 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
livereload
to 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 aBytesIO
instance, 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
txt
parameters 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_width
andwrapmode
. Links can also be added to cells by passing alink
parameter toRow.cell()
FPDF.multi_cell()
: has a new optionalcenter
parameter 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()
: thecolspan
setting has been fixed - documentationFPDF.image()
: allowing images path starting withdata
to 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
center
optional 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
graphs
andcharts
generated usingPygal
lib: documentation section - thanks to @ssavi-ict - documentation on how to use
fpdf2
with 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_only
optional 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.yaml
to 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
/height
defined as percents
- documentation on how to generate Code128 barcodes using the
python-barcode
lib: documentation section
- renamed
fonts.FontStyle
tofonts.FontFace
, andFPDF.use_font_style
toFPDF.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_ratio
optional boolean parameter, to fit it inside a given rectangle: documentationFPDF.multi_cell()
andFPDF.write()
now accept awrapmode
argument 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
TitleStyle
constructor 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:
fpdf2
can now embed SVG files withoutviewPort
or 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 theheight
attribute defined on<td>
/<th>
tags anymore, norheight
/width
attributes defined on<img>
tags inside cells, norwidth
attributes 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()
: thex
parameter now accepts a value of"C"
/Align.C
/"R"
/Align.R
to 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=True
FPDF.write_html()
: support forline-height
attribute 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=False
is set
FPDF.write_html()
: aValueError: Incoherent hierarchy
could be raised with some headings hierarchyFPDF.write_html()
:<img>
withoutheight
attribute overlaps with the following content #632 - thanks to @Bubbu0129FPDF.image()
: performance issue with adding large images withFlateDecode
image 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_dimensions
property onFPDF
instances - 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
fpdf2
resource 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
HTMLMixin
is deprecated, and not needed anymore: thewrite_html()
method is now natively available in theFPDF
class - 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 theDocumentState
enum, and has been replaced by moving the final rendering logic into a newfpdf.output
module
- after an "empty"
cell()
,ln()
applied a line height of zero #601 - when using
multi_cell()
withmax_line_height
to 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-width
attribute values with an explicit unit, thanks to @gmischler; #526 - the SVG parser now accepts absolute units for
width
andheight
attributes, 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 thefname
font 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.basename
property - 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
fpdf2
now 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
CreationDate
of 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
/ID
is 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_stretching
doesn'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
AnnotationName
andAnnotationFlags
onto 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_corners
toFPDF.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 CreationDate
of 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_mode
property, allowing to display a PDF automatically in full screen: link to docs - new
FPDF.viewer_preferences
property: 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
fill
parameter of thepolygon()
&polyline()
methods have been replaced by astyle
argument, offering more control
- new
round_clip()
&elliptic_clip()
image clipping methods: link to docs CoerciveEnum
subclasses have been added:Align
&RenderStyle
- documentation on how to embed Matplotlib charts: link to docs
- documentation on how to use
fpdf2
with Flask, streamlit, AWS lambdas: link to docs - documentation on how to store PDFs in a database with SQLAlchemy: link to docs
TextMode
,XPos
&YPos
now inherit fromCoerciveEnum
and hence can simply be passed as string parameters
- infinite loop when calling
.multi_cell()
without enough horizontal space - cf. #389
- support for
.pkl
files passed toadd_font()
. This was deprecated since v2.5.1. As a consequence,fpdf2
no more uses thepickle
module \o/
- new parameters
new_x
andnew_y
forcell()
andmulti_cell()
, replacingln=0
, thanks to @gmischler - new
highlight()
method to insert highlight annotations: documentation - new
offset_rendering()
method: documentation - new
.text_mode
property: 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 iftxt
is 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 anunbreakable
section - cf. #359
- The parameter
ln
tocell()
andmulti_cell()
is now deprecated: usenew_x
andnew_y
instead. - The parameter
center
tocell()
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 @gmischlerfname
is now a required parameter forFPDF.add_font()
image()
method now insert.svg
images 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 fromINFO
toDEBUG
- a bug when rendering Markdown and setting a custom
text_color
orfill_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
pickle
module, 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_dir
optional parameter offpdf.FPDF
constructor and theuni
optional argument ofFPDF.add_font()
are deprecated. Thefpdf.fpdf.load_cache
function 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.drawing
API for composing paths from an arbitrary sequence of lines and curves. - add
fpdf.svg.convert_svg_to_drawing
function to support converting basic scalable vector graphics (SVG) images to PDF paths.
will_page_break()
&accept_page_break
are 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_count
property, 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 = False
in 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
SMask
entry is inserted for images that are fully opaque (= with an alpha channel containing only 0xff characters) - The
rect
,ellipse
&circle
all have astyle
parameter in common. They now all properly accept a value of"D"
and raise aValueError
for invalid values.
dashed_line()
is now deprecated in favor ofset_dash_pattern()
- ensure support for old field names in
Template.code39
for 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
pystrich
lib: documentation section, thanks to @MWhatsUp write_html
: headings (<h1>
,<h2>
...) relative sizes can now be configured through an optionalheading_sizes
parameter- a subclass of
HTML2FPDF
can 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 aUnicodeEncodeError
Template
: 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
FPDF
methods should not be used inside arotation
context, or things can get broken. This is now forbidden: an exception is now raised in those cases.
Template
:code39
barcode input field names changed fromx/y/w/h
tox1/y1/y2/size
- support for emojis! More precisely unicode characters above
0xFFFF
in general, thanks to @moe-25 Template
can now insert justified textget_scale_factor
utility function to obtainFPDF.k
without having to create a documentconvert_unit
utility function to convert a number,x,y
point, or list ofx,y
points from one unit to another unit
fpdf.FPDF()
constructor now accepts ints or floats as a unit, and raises aValueError
if an invalid unit is provided.
Template
background
property is now properly supported - #203⚠️ Beware that its default value changed from0
to0xffffff
, 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.code39
method when those characters are missing.
- Detect missing
uni=True
when loading cached fonts (page numbering was missing digits)
- disable font caching when
fpdf.FPDF
constructor 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_break
utility method to let users know in advance when adding an elemnt will trigger a page break. This can be useful to repeat table headers on each page for exemple, cf. documentation on Tables.FPDF.set_link
now support a new optionalx
parameter to set the horizontal position after following the link
- fixed a bug when
fpdf.Template
was used to render QRCodes, due to a forced conversion to string (#175)
- erroneous page breaks occured for full-width / full-height images
- rendering issue of non-ASCII characaters with unicode fonts
- now
fpdf2
uses the newly supportedDCTDecode
image filter for JPEG images, instead ofFlateDecode
before, in order to improve the compression ratio without any image quality loss. On test images, this reduced the size of embeded 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
&write
methods gets a default value change,None
, meaning to use the current font size - removed the useless
w
&h
parameters of theFPDF.text_annotation()
method
- new
FPDF.add_action()
method, documented in the Annotations section FPDF.cell
: new optionalmarkdown=True
parameter that enables basic Markdown-like styling:**bold**, __italics__, --underlined--
FPDF.cell
: new optional booleancenter
parameter that positions the cell horizontallyFPDF.set_link
: new optionalzoom
parameter 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_filter
to control the image filters used for images FPDF.add_page
: new optionalduration
&transition
parameters 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 font
error when usingwrite_html
with unicode bold or italics fonts
- the
FPDF.set_doc_option()
method is deprecated in favour of just setting thecore_fonts_encoding
property on an instance ofFPDF
- the
fpdf.SYSTEM_TTFONTS
configurable module constant is now ignored
- a bug in the
deprecation
module that prevented to configurefpdf2
constants at the module level
- a "fake duplicates" bug when a
Pillow.Image.Image
was passed toFPDF.image
- new features: document outline & table of contents! Check out the new dedicated documentation page for more information
- new method
FPDF.text_annotation
to insert... Text Annotations FPDF.image
now also accepts anio.BytesIO
as 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.image
now accepts new optionaltitle
&alt_text
parameters defining the image title and alternative text describing it, for accessibility purposesFPDF.link
now honor itsalt_text
optional 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.unbreakable
so that no extra page jump is performed whenFPDF.multi_cell
is called inside this context
fpdf.FPDF_CACHE_MODE
&fpdf.FPDF_CACHE_DIR
in favor of a configurable newfont_cache_dir
optional argument of thefpdf.FPDF
constructor
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@property
methods to retrieve the effective page width / height, that is the page width / height minus its horizontal / vertical margins.FPDF.image
now accepts also aPillow.Image.Image
as inputFPDF.multi_cell
parameters evolve in order to generate tables with multiline text in cells:- its
ln
parameter now accepts a value of3
that sets the new position to the right without altering vertical offset - a new optional
max_line_height
parameter 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
dest
parameter ofFPDF.output
method
- new unit tests, a code formatter (
black
) and a linter (pylint
) to improve code quality - new boolean parameter
table_line_separators
forwrite_html
& underlyingHTML2FPDF
constructor
- the documentation URL is now simply https://py-pdf.github.io/fpdf2/
- dropped support for external font definitions in
.font
Python files, that relied on a call toexec
- the
type
parameter ofFPDF.image
method - the
infile
parameter ofTemplate
constructor - the
dest
parameter ofTemplate.render
method
- 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_parsing
module - 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 statment for
urlopen
inimage_parsing
module - changed urlopen import from
six
library to maintain python2 compatibility
- Ability to use a
BytesIO
buffer directly. This can simplify loadingmatplotlib
plots into the PDF.
load_resource
now return argument if type isBytesIO
, else load.
- introduced a dependency to
numpy
to 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
/Transparency
dict
- turned
accept_page_break
into a property - unit tests now use the standard
unittest
lib - massive code cleanup using
flake8