Releases: py-pdf/fpdf2
Releases · py-pdf/fpdf2
Table improvements, bidirectional text support, support for <path> in SVG and several bug fixes
Table improvements, bidirectional text support, support for <path> in SVG and several bug fixes
Latest
Added
- 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) - tutorial in Dutch: Handleiding - thanks to @Polderrider
- 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
Fixed
- 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
Changed
- 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
Deprecated
- font aliases (
Arial
→Helvetica
,CourierNew
→Courer
,TimesNewRoman
→Times
). They will be removed in a later release.
Support for Images and Clipping Paths in SVG files - Python 3.12 Support - Several Bugfixes
Added
- 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
Fixed
- 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.
Changed
- 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.
Improvements to FPDF.table() - Text regions layout management - several bugfixes
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).
Added
- The new experimental method
text_columns()
allows to render text within a single or multiple columns, including height balancing: documentation FPDF.write_html()
now supports heading colors defined as attributes (e.g.<h2 color="#00ff00">...
)FPDF.table()
: Now supports padding in cells : documentationFPDF.table()
: Now supports vertical alignment in cells : documentationFPDF.table()
: Now supports outer border width for rendering the outer border of the table with a different line-widthFPDF.table()
: Now supports multiple heading rows : documentation- documentation on how to use
livereload
to enable a "watch" mode with PDF generation: Combine with livereload
Changed
- The formatting output by
write_html()
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.
Fixed
- In multi_cells and table cells with horizontal padding, the text was not given quite enough space.
write_html()
can now handle formatting tags within paragraphs without adding extra line breaks (except in table cells for now).- the font size in HTML
<pre>
and<code>
tags is not fixed to 11 pica anymore, but adapts to the preceding text. FPDF.ln()
, when called before any text has been written, will now use the current font height instead of doing nothing - cf. issue #937FPDF.image()
, when provided aBytesIO
instance, does not close it anymore - cf. issue #881- Invalid characters were being generated when a string contains parentheses - cf. issue #884
- Frozen Glyph dataclass was causing problems for FPDFRecorder with TTF fonts - 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 - cf. issue #892- Encryption of strings containing non-latin characters - cf. issue #933
- Handling of fragments with zero-length - cf. issue #902
Deprecated
- to improve naming consistency, the
txt
parameters ofFPDF.cell()
,FPDF.multi_cell()
,FPDF.text()
&FPDF.write()
have been renamed totext
Text shaping using Harfbuzz - New mirror() method - New AES-256 encryption - Several bugfixes
Added
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://pyfpdf.github.io/fpdf2/HTML.html
Fixed
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
Deprecated
- 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"
Images can now be embedded as CMYK - Docs for using Pygal & FastAPI - Various bugfixes
Added
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://pyfpdf.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
Fixed
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
Changed
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
Deprecated
- the
split_only
optional parameter ofFPDF.multi_cell()
, which is replaced by two new distincts optional parameters:dry_run
&output
Removing debug print() statement
Fixed
- 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.
SVG & table() bugfixes
Fixed
- 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
New methods table() and set_fallback_fonts() - keep_aspect_ratio - ICC Profiles
Added
- 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").- new methods:
FPDF.preload_image()
&FPDF.use_font_style()
- 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 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
Fixed
- 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
Changed
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
Removed
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.
PDF encryption - skewing - markdown hyperlinks - Python 3.11
Added
- 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
Changed
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
Fixed
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
HTMLMixin not needed anymore - more HTML tags supported - demonstration Jupyter notebook
Added
- 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></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://pyfpdf.github.io/fpdf2/CombineWithPyPDF2.html - new documentation for using Jinja with
fpdf2
: https://pyfpdf.github.io/fpdf2/TemplatingWithJinja.html
Deprecated
HTMLMixin
is deprecated, and not needed anymore: thewrite_html()
method is now natively available in theFPDF
class - thanks to @yk-jp
Removed
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
Fixed
- 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.
Changed
- 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