Reputation: 338
I am a newcomer to Qt and I am trying to do some QPainter
drawing with the following test code:
QPixmap pixmap(20, 20);
pixmap.fill(Qt::white);
QPainter painter(&pixmap);
// Draw a rectangle (works fine in both Qt4 and Qt5)
painter.setPen(Qt::blue);
painter.drawLine(0, 0, 10, 0);
painter.drawLine(0, 0, 0, 10);
painter.drawLine(10, 0, 10, 10);
painter.drawLine(0, 10, 10, 10);
// Draw an example line from official docs (broken in Qt5)
painter.setPen(Qt::darkGreen);
painter.drawLine(2, 7, 6, 1);
// Draw an X (broken in Qt5)
painter.drawLine(13, 13, 18, 18);
painter.drawLine(13, 18, 18, 13);
Somehow, Qt4 (4.8.4) and Qt5 (5.0.1, 5.0.2) give me completely different results.
It does not look like Qt5 follows the rules described in its own official docs. However, there is a new QPainter::Qt4CompatiblePainting
render hint. If I set it, it indeed gives me the same result as in Qt4.
So my questions are:
Upvotes: 2
Views: 2206
Reputation: 338
So I opened a bug on Qt tracker and got the following response by Gunnar Sletta:
It is correct that the rasterisation rules were improved and made consistent in Qt 5. They are now consistent with how we render antialiased graphics (which was always the correct way). Aliased graphics was always off-by-0.5 in a broken way in Qt 4 which caused all sort of issues. The docs should be updated accordingly. All the bottom-right-shifting logic applies to the Qt4 compat mode only.
The default cap style (how we draw end points) for QPen is Qt::SquareCap. This means that the line becomes half a pixel longer in each direction, totalling to one pixel which lands at the bottom. Set the cap style to FlatCap and the extra pixel goes away as it should.
My further experiments show that just setting pen style to Qt::FlatCap
is not enough - it still leaves some issues (of other kind). The correct way to get results like Qt4 without compatibility flag right now seems to be using floating-point coordinates instead of integer and adding 0.5 to all end points (without setting the Qt::FlatCap
line style). For example:
painter.setPen(Qt::darkGreen);
painter.drawLine(QPointF(2.5, 7.5), QPointF(6.5, 1.5));
An easier way to automate this once and for all is to make the following call after creating the painter:
painter.translate(0.5, 0.5);
Upvotes: 1