QBrush transformation ignored by QPrinter/QPdfWriter

155 Views Asked by At

I am using PyQt 5.15.2 (Qt 5.15.2) on macOs 10.15.7. I am trying to produce a PDF from a QGraphicsScene. I am drawing some paths with a brush that has a pixmap texture, and a scale transformation applied (with brush.setTransform). When I display the scene in a QGraphicsView I get exactly the desired output. When I render the same scene to a QPrinter (set to produce a pdf) the texture is applied but ignoring the transformation. Is this a known limitation? Is there a way around it?

Below is a minimal example showing the problem in a context similar to my use case. Here I am creating a texture on the fly for illustration purposes. The rendering artifacts due to antialiasing are irrelevant for my question. The issue is the discrepancy between the scale (set at .5) of the texture in the rendered brush and the scale (always 1) in the pdf output. [To generate the output just double click on the view, you'll see a test.pdf in the current path.]

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtPrintSupport import *

class Test(QGraphicsView):

  def __init__(self):
    QGraphicsView.__init__(self)

    # Here I am creating a texture for testing
    # it is a 50x50 black square
    s = 50
    img = QImage(s, s, QImage.Format_ARGB32)
    img.fill(Qt.transparent)
    for x in range(s):
      img.setPixelColor(x,0,Qt.black)
      img.setPixelColor(x,s-1,Qt.black)
      img.setPixelColor(s-1,x,Qt.black)
      img.setPixelColor(0,x,Qt.black)

    self.scene = QGraphicsScene()
    self.setScene(self.scene)
    r = self.scene.addRect(0, 0, 1404, 1872)

    pen = QPen()
    pen.setWidth(150)
    pen.setCapStyle(Qt.RoundCap)
    pen.setJoinStyle(Qt.RoundJoin)

    b=QBrush(img)
    # Here I am transforming the brush so that the texture should be scaled 50% in both height and width
    tr = QTransform()
    tr.scale(.5,.5)
    b.setTransform(tr)
    pen.setBrush(b)

    # A random path for testing, drawn using the textured brush
    path = QPainterPath(QPointF(200, 200))
    path.lineTo(300,300)
    path.lineTo(300,1000)
    path.lineTo(700,700)
    self.pathItem = QGraphicsPathItem(path, r)
    self.pathItem.setPen(pen)

  def resizeEvent(self, event):
    self.fitInView(self.sceneRect(), Qt.KeepAspectRatio)

  def mouseDoubleClickEvent(self, event):
    printer = QPrinter(QPrinter.HighResolution)
    printer.setOutputFormat(QPrinter.PdfFormat)
    # printer.setPageSize(QPrinter.A4)
    printer.setOutputFileName("test.pdf")
    printer.setPaperSize(QSizeF(1404,1872), QPrinter.Millimeter)
    printer.setPageMargins(0,0,0,0, QPrinter.Millimeter)
    p=QPainter()
    p.begin(printer)
    self.scene.render(p)
    p.end()

if __name__ == '__main__':
  app = QApplication([])
  print(QT_VERSION_STR)
  print(PYQT_VERSION_STR)
  viewer = Test()
  viewer.show()
  app.exec_()

The desired output is on the left, as correctly displayed by the QGraphicsView. On the right is the PDF rendering of the same scene, which incorrectly ignores the scaling of the brush.

preview

0

There are 0 best solutions below