1import ctypes
2
3from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo
4from .backend_qt5 import QtCore, QtGui, _BackendQT5, FigureCanvasQT
5from .qt_compat import QT_API, _setDevicePixelRatio
6
7
8class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo):
9    def __init__(self, figure=None):
10        super().__init__(figure=figure)
11        self._renderer = RendererCairo(self.figure.dpi)
12        self._renderer.set_width_height(-1, -1)  # Invalid values.
13
14    def draw(self):
15        if hasattr(self._renderer.gc, "ctx"):
16            self.figure.draw(self._renderer)
17        super().draw()
18
19    def paintEvent(self, event):
20        dpi_ratio = self._dpi_ratio
21        width = int(dpi_ratio * self.width())
22        height = int(dpi_ratio * self.height())
23        if (width, height) != self._renderer.get_canvas_width_height():
24            surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
25            self._renderer.set_ctx_from_surface(surface)
26            self._renderer.set_width_height(width, height)
27            self.figure.draw(self._renderer)
28        buf = self._renderer.gc.ctx.get_target().get_data()
29        qimage = QtGui.QImage(buf, width, height,
30                              QtGui.QImage.Format_ARGB32_Premultiplied)
31        # Adjust the buf reference count to work around a memory leak bug in
32        # QImage under PySide on Python 3.
33        if QT_API == 'PySide':
34            ctypes.c_long.from_address(id(buf)).value = 1
35        _setDevicePixelRatio(qimage, dpi_ratio)
36        painter = QtGui.QPainter(self)
37        painter.eraseRect(event.rect())
38        painter.drawImage(0, 0, qimage)
39        self._draw_rect_callback(painter)
40        painter.end()
41
42
43@_BackendQT5.export
44class _BackendQT5Cairo(_BackendQT5):
45    FigureCanvas = FigureCanvasQTCairo
46