Skip to content

[ENH]: Add a QtPgfPng backend? #28086

Open
@anntzer

Description

@anntzer

Problem

Per #28084 and a few other older similar issues, some users are confused because they cannot see pgf-generated plots (which can include xelatex/lualatex-specific latex constructs, in particular) interactively, as the interactive guis still use the "standard" latex support.

As it turns out it is relatively easy(?) to implement a minimal "interactive" backend that uses pgf and pdf->png to conversion to interactively display pgf-generated plots. Obviously it has the most terrible performance ever (each draw involves a full tex compilation of the image), but (per the above) it could have some uses...

Proposed solution

Minimum patch implementing the (minimally tested...) backend is below. Test e.g. by setting MPLBACKEND to qtpgfpng and plotting.

diff --git c/lib/matplotlib/backends/backend_qtpgfpng.py i/lib/matplotlib/backends/backend_qtpgfpng.py
new file mode 100644
index 0000000000..f44097dc0b
--- /dev/null
+++ i/lib/matplotlib/backends/backend_qtpgfpng.py
@@ -0,0 +1,27 @@
+from tempfile import TemporaryDirectory
+
+import numpy as np
+import PIL.Image
+
+from .backend_pgf import FigureCanvasPgf
+from .backend_qt import FigureCanvasQT
+from .qt_compat import QtGui
+
+
+class FigureCanvasQTPgfPng(FigureCanvasPgf, FigureCanvasQT):
+    def paintEvent(self, event):
+        with TemporaryDirectory() as tmpdir:
+            self.print_png(f"{tmpdir}/image.png")
+            img = np.asarray(PIL.Image.open(f"{tmpdir}/image.png"))
+        qimage = QtGui.QImage(
+            img, img.shape[1], img.shape[0],
+            QtGui.QImage.Format.Format_RGBA8888)
+        qimage.setDevicePixelRatio(self.device_pixel_ratio)
+        painter = QtGui.QPainter(self)
+        painter.eraseRect(event.rect())
+        painter.drawImage(0, 0, qimage)
+        self._draw_rect_callback(painter)
+        painter.end()
+
+
+FigureCanvas = FigureCanvasQTPgfPng
diff --git c/lib/matplotlib/backends/meson.build i/lib/matplotlib/backends/meson.build
index 1e3e47c0a9..967cab902b 100644
--- c/lib/matplotlib/backends/meson.build
+++ i/lib/matplotlib/backends/meson.build
@@ -19,6 +19,7 @@ python_sources = [
   'backend_qt.py',
   'backend_qtagg.py',
   'backend_qtcairo.py',
+  'backend_qtpgfpng.py',
   'backend_qt5.py',
   'backend_qt5agg.py',
   'backend_qt5cairo.py',
diff --git c/lib/matplotlib/backends/registry.py i/lib/matplotlib/backends/registry.py
index 484d6ed5f2..ac18cc28c9 100644
--- c/lib/matplotlib/backends/registry.py
+++ i/lib/matplotlib/backends/registry.py
@@ -32,7 +32,7 @@ class BackendRegistry:
         "GTK3Agg", "GTK3Cairo", "GTK4Agg", "GTK4Cairo",
         "MacOSX",
         "nbAgg",
-        "QtAgg", "QtCairo", "Qt5Agg", "Qt5Cairo",
+        "QtAgg", "QtCairo", "QtPgfPng", "Qt5Agg", "Qt5Cairo",
         "TkAgg", "TkCairo",
         "WebAgg",
         "WX", "WXAgg", "WXCairo",

(#27913 (comment) is also relevant)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions