Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b1a54a1
Feature: Matplotlib renderer
petri-lipponen-movesense Dec 10, 2025
88e8fad
- add dependency
petri-lipponen-movesense Dec 10, 2025
70ff91f
- more dep
petri-lipponen-movesense Dec 10, 2025
0dd0abf
- fix version
petri-lipponen-movesense Dec 10, 2025
5e9902f
- fix if condition
petri-lipponen-movesense Dec 10, 2025
de2a5fe
- fix
petri-lipponen-movesense Dec 10, 2025
8d06f2a
- set copy=false for speed
petri-lipponen-movesense Dec 10, 2025
21dc25a
Merge branch 'py-pdf:master' into feature/matplotlib_renderer
petri-lipponen-movesense Dec 15, 2025
30980b7
- revert lineplot test case
petri-lipponen-movesense Dec 15, 2025
2bc2c78
- fix fonts
petri-lipponen-movesense Dec 15, 2025
be248ac
- added mention on CHANGELOG.md
petri-lipponen-movesense Dec 15, 2025
33750dd
- added support for simple dashed lines
petri-lipponen-movesense Dec 17, 2025
5247d33
- code formatting
petri-lipponen-movesense Dec 17, 2025
f890abc
- some linter fixes
petri-lipponen-movesense Dec 17, 2025
d8d7646
- re-black
petri-lipponen-movesense Dec 17, 2025
6399508
- fixed linter warnings
petri-lipponen-movesense Dec 17, 2025
bf2c516
- moved matplotlib to test dependency
petri-lipponen-movesense Dec 17, 2025
d341578
- try using assert_pdf_equal
petri-lipponen-movesense Dec 17, 2025
54ab63a
- hope this fixes it...
petri-lipponen-movesense Dec 17, 2025
549b630
- move matplotlib as optional depedency
petri-lipponen-movesense Dec 17, 2025
518c2a4
- removed renderer from init.py
petri-lipponen-movesense Dec 17, 2025
6157929
- disabled assert_pdf_equal
petri-lipponen-movesense Dec 18, 2025
bcc10f5
- add matplotlib to docs
petri-lipponen-movesense Dec 19, 2025
60476db
- remove generate=True
petri-lipponen-movesense Dec 19, 2025
de5ee7d
- fix lint
petri-lipponen-movesense Dec 19, 2025
0e54f13
- re-black
petri-lipponen-movesense Dec 19, 2025
1ddb74e
Update fpdf/fpdf_renderer.py
petri-lipponen-movesense Dec 19, 2025
ed1d426
Update docs/Maths.md
petri-lipponen-movesense Dec 19, 2025
fc08f24
- use uppercase for logger
petri-lipponen-movesense Dec 19, 2025
4a665d1
- style fixes
petri-lipponen-movesense Dec 19, 2025
42b18f4
- cleanup
petri-lipponen-movesense Dec 19, 2025
77e904b
- re-fix generate=true
petri-lipponen-movesense Dec 19, 2025
fc85d0d
- re-black
petri-lipponen-movesense Dec 19, 2025
5634ed7
- lint fix
petri-lipponen-movesense Dec 19, 2025
5846c21
- handle case of empty path
petri-lipponen-movesense Jan 21, 2026
39cf82a
- skip & log non-iterable path segments
petri-lipponen-movesense Jan 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ nosetests.xml
*.*~
*.swo
*.swp
test/mpl_renderer/generated_pdf/*.pdf
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to add this

2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
## [2.8.6] - Not released yet
### Added
* support for SVG `<linearGradient>` and `<radialGradient>` elements - _cf._ [issue #1580](https://github.com/py-pdf/fpdf2/issues/1580) - thanks to @Ani07-05
* Direct FPDF renderer for matplotlib images
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a link there to the new documentation section in https://py-pdf.github.io/fpdf2/Maths.html#using-matplotlib ?


### Fixed
* a bug when rendering empty tables with `INTERNAL` layout, that caused an extra border to be rendered due to an erroneous use of `list.index()` - _cf._ [issue #1669](https://github.com/py-pdf/fpdf2/issues/1669)
### Changed
Expand Down
70 changes: 70 additions & 0 deletions docs/Maths.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,73 @@ If you have trouble with the SVG export, you can also render the matplotlib figu
```python
{% include "../tutorial/equation_matplotlib_raster.py" %}
```

### Using fpdf2 renderer ###

Comment thread
petri-lipponen-movesense marked this conversation as resolved.
_New in [:octicons-tag-24: 2.8.6](https://github.com/py-pdf/fpdf2/blob/master/CHANGELOG.md)_

The new _experimental_ fpdf2 renderer for matplotlib allows direct rendering to the FPDF2 document. This provides a large performance benefit compared to using SVG (over x3 faster) or PNG intermediate rendering. There are a couple of down sides to this method of rendering the plots:

1. The `bbox_inches='tight'` -option cannot be used on savefig (or it can cause a lot of weird stuff)
2. One must calculate the _origin_ and _scale_ parameters for setting the layout on pdf document

The following code samples demonstrate the use of the new codepath:

#### Original code using SVG ####

```python
fig, ax = plt.subplots(figsize=(w_inch, h_inch))

t = [i * 0.01 for i in range(1000)]
s = [sin(value) + cos(value*value) for value in t]
ax.plot(t, s, 'blue', linewidth=1)
ax.set_title("Line Plot Figure")
ax.set_xlabel("t")
ax.set_ylabel("sin(t) + cos(t^2)")
ax.autoscale_view()

# Save plot to SVG
buffer = BytesIO()
fig.savefig(buffer, format='svg', dpi=300, pad_inches=0.1)

plt.close(fig)
buffer.seek(0)

# Draw SVG to PDF
pdf.image(buffer, x=x, y=y, w=w, h=h)
```


#### New FPDF rendering ####

```python
import matplotlib as mpl
mpl.use("module://fpdf.fpdf_renderer")
```
...

```python
fig, ax = plt.subplots(figsize=(w_inch, h_inch))

t = [i * 0.01 for i in range(1000)]
s = [sin(value) + cos(value*value) for value in t]
ax.plot(t, s, 'blue', linewidth=1)
ax.set_title("Line Plot Figure")
ax.set_xlabel("t")
ax.set_ylabel("sin(t) + cos(t^2)")
ax.autoscale_view()

# Calc scale and origin
if w == 0:
w = fig.bbox.width
scale = float(w / fig.bbox.width)
if h == 0:
h = fig.bbox.height * scale
origin = (float(x), float(y + h)) # FPDF uses bottom-left as origin

# Call savefig directly with fpdf object and origin & scale
fig.savefig (fname=None, fpdf=pdf, origin=origin, scale=scale)
plt.close(fig)
```


Loading