[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:
http://chaos.troll.no/~sroedal/fillrules.png
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:
http://chaos.troll.no/~sroedal/fillrules-qt5.png
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.
--
Samuel
More information about the Development
mailing list