Search code examples
c++qttextprintingqpainterpath

QPainterPath text renders wrong when printing


With Qt 5.4.2, I'm using a QPainterPath to render text, since the text may be split into characters and each character rendered along a curve. I see different results across platforms and when I print. To render the text, I've tried using QPainter's drawPath() and drawPolygon() methods.

OS X 10.11.6:

  • drawPath: top line in Indic text has gaps that should not be there, both in a QGraphicsView and when I print.
  • drawPolygon: the top line is solid as it should be, both in a QGraphicsView and when I print. However, when printed, I get lots of extra fine lines between various random points in the text.

Window 7:

  • drawPath: same as on the Mac: there are gaps in top line, both the QGraphicsView and when I print.
  • drawPolygon: the QGraphicsView is correct (no gaps), but printing still has the gaps in the top line, though it does not have the extra fine lines as when printed on the Mac. So printing with drawPolygon produces identical incorrect output as printing with drawPath.

Here's a sample app that demonstrates these issues. Here's the paint code from my QGraphicsItem subclass in my sample app:

void MapGraphicsTextElement::paint(QPainter *painter,
                                   const QStyleOptionGraphicsItem * /*option*/,
                                   QWidget * /*widget*/) {

  painter->setFont(font_);
  painter->setRenderHint(QPainter::Antialiasing);
  painter->setBrush(QBrush(QColor(Qt::black)));
  painter->setPen(Qt::NoPen);

  QPainterPath path;
  path.addText(0, 0, font_, text_);

  if (fix_gaps_) {
    QPolygonF poly = path.toFillPolygon();
    painter->drawPolygon(poly, Qt::WindingFill);
  } else {
    painter->drawPath(path);
  }
}

Here's the code from the sample app that creates the scene and adds two of my QGraphicsItem subclass objects to the scene:

QGraphicsScene * PrintsLines::CreateScene()
{
  QGraphicsScene *scene = new QGraphicsScene(0, 0, 500, 500, this);

  QScopedPointer<MapGraphicsTextElement> item(new MapGraphicsTextElement());

  item->SetText("My test text here.");
  item->SetFixGaps(fix_gaps_->isChecked());
  QFont item_font("Arial");
  item_font.setPixelSize(12);
  item->SetFont(item_font);
  item->setPos(128, 115);
  scene->addItem(item.take());

  QScopedPointer<MapGraphicsTextElement> item2(new MapGraphicsTextElement());

  item2->SetText("मेदितेरेनियन सि");
  item2->SetFixGaps(fix_gaps_->isChecked());
  QFont item_font2("Arial");
  item_font2.setPixelSize(48);
  item2->SetFont(item_font2);
  item2->setPos(128, 215);
  scene->addItem(item2.take());

  return scene;
}

How can I make what is rendered in a QGraphicsView and is printed are identical and correct? If different solutions are required for OS X and Windows, that's ok. Or if a newer version of Qt is required to solve this, I could upgrade Qt.

UPDATE:

As Kuba Ober suggested, I have demonstrated the printing bugs with this simple app below. I'm not sure how to proceed from here.

#include <QApplication>

#include <QtGui/QPainter>
#include <QtGui/QPainterPath>
#include <QtGui/QFont>
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrinter>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  QPrinter *printer = new QPrinter();
  QPrintDialog dialog(printer);
  if (dialog.exec() == QDialog::Accepted) {
    QFont font("Arial");
    font.setPointSize(48);

    QPainter painter(printer);
    painter.setFont(font);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(QBrush(QColor(Qt::black)));
    painter.setPen(Qt::NoPen);

    // drawPath()
    QPainterPath path_drawPath;
    path_drawPath.addText(100, 200, font, "मेदितेरेनियन सि");
    painter.drawPath(path_drawPath);

    // drawPolygon()
    QPainterPath path_drawPoly;
    path_drawPoly.addText(100, 300, font, "मेदितेरेनियन सि");
    QPolygonF poly = path_drawPoly.toFillPolygon();
    painter.drawPolygon(poly, Qt::WindingFill);
  }

  return 0;
}

Solution

  • painter.drawText() is working for printing and for creating pdf's. painter.drawPolygon() is working for on-screen rendering and outputting raster images (png & jpg). This workaround appears to be sufficient to solve my problem.