Search code examples
c++qtqpainterqpainterpath

Draw text around QPainterPath efficiently


The following code draws text around a QPainterPath:

QString text = "Short text";
QPainterPath rawPath;
// fill path ...

while (...)
{
    double percent = ...;
    double angle = rawPath.angleAtPercent(percent);
    QPointF point = rawPath.pointAtPercent(percent);

    m_painter.save();

    m_painter.translate(point);
    m_painter.rotate(-angle);

    // Version 1:
    //m_painter.drawText(0, 0, text.at(currentChar));

    // Version 2:
    QPainterPath p2;
    p2.addText(0, 0, font, text.at(currentChar));
    m_painter.drawPath(p2);

    m_painter.restore();
}

The graphical result is as expected but the performance of both, Version 1 and Version 2 is very poor. The bottleneck is the QPainter::drawText() respectively the QPainterPath::addText() method. Is there a more efficient way to draw text around a path?

Regards,


Solution

  • There is no built-in method to draw a text following a path.

    But, if QPainter is not efficient enough, you can gain some perfs by building a new path with your text and by drawing after your loop (you will not use QPainter::save() and QPainter::restore() in a loop):

    void paintEvent(QPaintEvent* event)
        {
            QString text = "Short text";
            text = text.repeated(1000); // Check with a very long text
            QPainterPath rawPath;
            rawPath.addEllipse(QRect(0, 0, 200, 200));
    
            QPainterPath path;
    
            double const step = 1.0 / double(text.length());
            double percent = 0.0;
            for(QChar const& c: text)
            {
                double angle = rawPath.angleAtPercent(percent);
                QPointF point = rawPath.pointAtPercent(percent);
    
                QTransform mat;
                mat.rotate(-angle);
                QPainterPath p2;
                p2.addText(0, 0, font(), c);
                p2 = mat.map(p2);
                path.addPath(p2.translated(point));
                percent += step;
            }
    
            QPainter painter(this);
            painter.drawPath(path.translated(100, 100));
        }