[Development] Behavior change: A sane and consistent QPainter coordinate system in Qt 5

Samuel Rødal samuel.rodal at digia.com
Thu Oct 11 13:57:30 CEST 2012

While we're on the topic of pixels,

in Qt 4 we in effect have two coordinate systems. The antialiased 
coordinate system where (0, 0) corresponds to the top left corner of the 
top left pixel, and the aliased coordinate system where (0, 0) 
corresponds to the center of the top left pixel. That means if you fill 
a rectangle QRectF(0.1, 0.1, 10, 10) without QPainter::Antialiasing 
enabled it will actually round up and start filling at (1, 1).

The reason for the aliased coordinate system being that way goes all the 
way back to X11 only having integer coordinate line drawing and polygon 
filling. The raster paint engine was made to match the behavior of the 
X11 paint engine and thus the half pixel offset became the de facto 
standard for the fill rules in our painting systems.

_Except_ in cases like image / pixmap painting, where both the X11 and 
raster paint engine simply rounded the QPointF coordinate. Thus drawing 
a rect and an image of the same size at the same sub-pixel coordinates 
would lead to a one pixel delta between the two (a bug that occasionally 
gets reported but typically closed as "Won't fix"). Once we became fully 
aware of this inconsistency (well into the 4.x series) we were too 
afraid to fix it, to avoid breaking existing applications that relied on 
the current behavior.

Well, this has left us with a coordinate system that is neither 
internally consistent, nor consistent with the antialiased coordinate 
system (which closely matches how the OpenGL coordinate system works, 
although in that case the y axis is flipped). The result of these 
inconsistencies can easily be seen in the filltest.qps arthur test run 
with the lance tool against 4.8: 

As the arthur test shows, in some cases the way we fill and the way we 
sample brush textures don't even match.

Although it's a bit late, I think Qt 5 is a good time to fix this so 
that we finally get a consistent coordinate system without gotchas at 
every corner when using sub-pixel coordinates. I have a work in progress 
patch in Code Review that gets rid of the half pixel aliased coordinate 
offset by default: https://codereview.qt-project.org/#change,36757

Here is how the arthur test looks with the new behavior: 

For applications that do depend on the old behavior, I introduce a new 
render hint, QPainter::LegacyFillRules, which restores the 4.x behavior. 
The patch makes use of this render hint in some of Qt's style painting 
code (mostly to make the Windows "95" and Cleanlooks styles look good, 
as they draw aliased polygons in some places).

It's unfortunate to potentially cause some extra trouble for a subset of 
existing applications that wish to port to Qt 5, but weighed against the 
utter embarrassment of the current fill rules I think we need this change.


More information about the Development mailing list