edvardsp
edvardsp

Reputation: 133

qt - QPainter::rotate with non-perpendicular angles causes wiggly lines

I'm trying to draw text on a widget at an angle which is non-perpendicular, i.e. between 0 and 90. Drawing the text itself is no issue, but the resulting text is very wiggly/unevenly drawn.

In the picture below, I'm drawing to lines of text at a 45 degree angle. The first line of text is many underscores ("_____"), and second line of text is "Multithreading". Underscores are drawn here instead of a line just to highlight the issue.

enter image description here

As you can see, the first line obviously shows the text is not evenly drawn. This is more subtle in the second line, but still visible.

Drawing at perpendicular angles (0, 90, 180, etc.) does not cause this effect. Any reason why this is happening?

I'm working on Windows 10 with Qt 5.7.0.

Minimal code example:

void MyWidget::paintEvent( QPaintEvent * /* event */ )
{
    QFont font;
    font.setPointSize( 16 );
    font.setStyleStrategy( QFont::StyleStrategy::PreferAntialias );
    setFont( font );

    QImage image( size(), QImage::Format_ARGB32_Premultiplied );
    QPainter imagePainter( &image );
    imagePainter.initFrom( this );
    imagePainter.setFont( font() );
    imagePainter.setRenderHint( QPainter::Antialiasing, true );
    imagePainter.eraseRect( rect() );
    // Set logical origo in the middle of the image
    m_window = QRect(
        - width() / 2,  // x
        - height() / 2, // y
        width(),        // w
        height()        // h
    );
    imagePainter.setWindow( m_window );
    m_viewport = QRect(
        0,              // x
        0,              // y
        width(),        // w
        height()        // h
    );
    imagePainter.setViewport( m_viewport );

    draw( imagePainter );
    imagePainter.end();

    QPainter widgetPainter( this );
    widgetPainter.drawImage( 0, 0, image );
}

void MyWidget::draw( QPainter & painter )
{
    painter.save();
    // Rotate anti-clockwise
    painter.rotate( -m_degrees );
    painter.drawText( m_window.top(), 0, tr( "Multithreads" ) );
    painter.drawText( m_window.top(), 15, tr( "__________" ) );

    painter.restore();
}

Upvotes: 2

Views: 592

Answers (1)

edvardsp
edvardsp

Reputation: 133

I found a workaround from this Qt bug ticket. In short, the fix is to draw the text as a QPainterPath rather than as text.

Example of the fix is

// Do this
QPainterPath glyphPath;
glyphPath.addText( x, y, painter.font(), text );
painter.fillPath( glyphPath, painter.pen().color() );
// instead of this
painter.drawText( x, y, text );

EDIT:

The difference can be seen below.

Before:

Before, buggy text

After:

After, correct text

Upvotes: 5

Related Questions