Skip to content

Releases: py-pdf/fpdf2

Table improvements, bidirectional text support, support for <path> in SVG and several bug fixes

10 Feb 04:34
1bd4548
Compare
Choose a tag to compare

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 the rowspan attribute, which can be combined with colspan - thanks to @mjasperse
  • TableSpan.COL and TableSpan.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 the render_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 honors align= 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 (ArialHelvetica, CourierNewCourer, TimesNewRomanTimes). They will be removed in a later release.

Support for Images and Clipping Paths in SVG files - Python 3.12 Support - Several Bugfixes

10 Dec 13:40
652a517
Compare
Choose a tag to compare

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 static combine 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. #979
  • TextColumns() can now have images inserted (both raster and vector) - thanks to @gmischler
  • TextColumns() can now advance to the next column with the new new_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 a TypeError when used in tables
  • FPDF.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 cells
  • FPDF.write_html() delays unescaping data so as not to confuse entity names as nested tags
  • FPDF.multi_cell() has improved handling of new_x and new_y when padding is non-zero.
  • FPDF.multi_cell(fill=True) now avoids overlapping multiline strings when padding is non-zero.

Changed

  • the public .images, .icc_profiles & .image_filter attributes of FPDF instances have been moved inside a nested FPDF.image_cache attribute. Similarly, the FPDF.preload_image() is now a function in the fpdf.image_parsing module: documentation
  • the fpdf.svg module now produces WARNING 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

11 Oct 15:08
fd00303
Compare
Choose a tag to compare

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

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 #937
  • FPDF.image(), when provided a BytesIO 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 of FPDF.cell(), FPDF.multi_cell(), FPDF.text() & FPDF.write() have been renamed to text

Text shaping using Harfbuzz - New mirror() method - New AES-256 encryption - Several bugfixes

04 Aug 15:55
Compare
Choose a tag to compare

Added

Fixed

Deprecated

  • the center optional parameter of FPDF.cell() is no more deprecated, as it allows for horizontal positioning, which is different from text alignment control with align="C"

Images can now be embedded as CMYK - Docs for using Pygal & FastAPI - Various bugfixes

28 Apr 16:01
Compare
Choose a tag to compare

Added

Fixed

  • FPDF.table(): images no more overflow cells
  • FPDF.table(): text overflow in the last cell of the header row is now properly handled
  • FPDF.table(): when align="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 of fpdf2 - cf. #740

Deprecated

  • the split_only optional parameter of FPDF.multi_cell(), which is replaced by two new distincts optional parameters: dry_run & output

Removing debug print() statement

03 Apr 12:14
Compare
Choose a tag to compare

Fixed

  • removed a debug print() statement left in output.py:OutputProducer._add_fonts() 🤦‍♂️ - A rule was also added to .pre-commit-config.yaml to avoid this to happen again.

SVG & table() bugfixes

03 Apr 09:59
Compare
Choose a tag to compare

Fixed

  • custom fonts can be used with FPDF.table() without triggering a TypeError: cannot pickle 'dict_keys' object - thanks @aeris07 for the bug report
  • the SVG parser now accepts <rect> with width / height defined as percents

New methods table() and set_fallback_fonts() - keep_aspect_ratio - ICC Profiles

27 Mar 15:43
Compare
Choose a tag to compare

Added

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 with add_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 new FPDF.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 without viewPort or no height / 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 new FPDF.table() method to render <table> tags. As a consequence, it does not support the height attribute defined on <td> / <th> tags anymore, nor height / width attributes defined on <img> tags inside cells, nor width attributes defined on <thead> / <tfoot> tags.

PDF encryption - skewing - markdown hyperlinks - Python 3.11

13 Jan 17:39
Compare
Choose a tag to compare

Added

Changed

  • FPDF.add_link() creates a link to the current page by default, and now accepts optional parameters: x, y, page & zoom.
    Hence calling set_link() is not needed anymore after creating a link with add_link().
  • FPDF.write_html() now generates warnings for unclosed HTML tags, unless warn_on_tags_not_matching=False is set

Fixed

HTMLMixin not needed anymore - more HTML tags supported - demonstration Jupyter notebook

20 Nov 17:51
Compare
Choose a tag to compare

Added

Deprecated

  • HTMLMixin is deprecated, and not needed anymore: the write_html() method is now natively available in the FPDF class - thanks to @yk-jp

Removed

  • open() & close() methods, that were only used internally and should never have been called by end-user code
  • FPDF.state, which was an instance of the DocumentState enum, and has been replaced by moving the final rendering logic into a new fpdf.output module

Fixed

  • after an "empty" cell(), ln() applied a line height of zero #601
  • when using multi_cell() with max_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 with footer() 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 and height 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 the fname font path is used to define the font family. Hence pdf.add_font(fname="fonts/NotoSansArabic.ttf") will define a font named NotoSansArabic.
  • the output of embed_file() is now a PDFEmbeddedFile, not a string, but the internal file name can be retrieved through its .basename property
  • forbid use of get_y() & local_context() inside unbreakable() as it is currently not supported; #557
  • fontTools minimal version requirement set to 4.34.0; #524