/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the documentation of the Qt Toolkit.+ −
**+ −
** $QT_BEGIN_LICENSE:LGPL$+ −
** No Commercial Usage+ −
** This file contains pre-release code and may not be distributed.+ −
** You may use this file in accordance with the terms and conditions+ −
** contained in the Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** GNU Lesser General Public License Usage+ −
** Alternatively, this file may be used under the terms of the GNU Lesser+ −
** General Public License version 2.1 as published by the Free Software+ −
** Foundation and appearing in the file LICENSE.LGPL included in the+ −
** packaging of this file. Please review the following information to+ −
** ensure the GNU Lesser General Public License version 2.1 requirements+ −
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.+ −
**+ −
** In addition, as a special exception, Nokia gives you certain additional+ −
** rights. These rights are described in the Nokia Qt LGPL Exception+ −
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
/*!+ −
\page coordsys.html+ −
\title The Coordinate System+ −
\brief Information about the coordinate system used by the paint+ −
system.+ −
+ −
\previouspage Drawing and Filling+ −
\contentspage The Paint System+ −
\nextpage Reading and Writing Image Files+ −
+ −
The coordinate system is controlled by the QPainter+ −
class. Together with the QPaintDevice and QPaintEngine classes,+ −
QPainter form the basis of Qt's painting system, Arthur. QPainter+ −
is used to perform drawing operations, QPaintDevice is an+ −
abstraction of a two-dimensional space that can be painted on+ −
using a QPainter, and QPaintEngine provides the interface that the+ −
painter uses to draw onto different types of devices.+ −
+ −
The QPaintDevice class is the base class of objects that can be+ −
painted: Its drawing capabilities are inherited by the QWidget,+ −
QPixmap, QPicture, QImage, and QPrinter classes. The default+ −
coordinate system of a paint device has its origin at the top-left+ −
corner. The \e x values increase to the right and the \e y values+ −
increase downwards. The default unit is one pixel on pixel-based+ −
devices and one point (1/72 of an inch) on printers.+ −
+ −
The mapping of the logical QPainter coordinates to the physical+ −
QPaintDevice coordinates are handled by QPainter's transformation+ −
matrix, viewport and "window". The logical and physical coordinate+ −
systems coincide by default. QPainter also supports coordinate+ −
transformations (e.g. rotation and scaling).+ −
+ −
\tableofcontents+ −
+ −
\section1 Rendering+ −
+ −
\section2 Logical Representation+ −
+ −
The size (width and height) of a graphics primitive always+ −
correspond to its mathematical model, ignoring the width of the+ −
pen it is rendered with:+ −
+ −
\table+ −
\row+ −
\o \inlineimage coordinatesystem-rect.png+ −
\o \inlineimage coordinatesystem-line.png+ −
\row+ −
\o QRect(1, 2, 6, 4)+ −
\o QLine(2, 7, 6, 1)+ −
\endtable+ −
+ −
\section2 Aliased Painting+ −
+ −
When drawing, the pixel rendering is controlled by the+ −
QPainter::Antialiasing render hint.+ −
+ −
The \l {QPainter::RenderHint}{RenderHint} enum is used to specify+ −
flags to QPainter that may or may not be respected by any given+ −
engine. The QPainter::Antialiasing value indicates that the engine+ −
should antialias edges of primitives if possible, i.e. smoothing+ −
the edges by using different color intensities.+ −
+ −
But by default the painter is \e aliased and other rules apply:+ −
When rendering with a one pixel wide pen the pixels will be+ −
rendered to the \e {right and below the mathematically defined+ −
points}. For example:+ −
+ −
\table+ −
\row+ −
\o \inlineimage coordinatesystem-rect-raster.png+ −
\o \inlineimage coordinatesystem-line-raster.png+ −
+ −
\row+ −
\o+ −
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 0+ −
+ −
\o+ −
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 1+ −
\endtable+ −
+ −
When rendering with a pen with an even number of pixels, the+ −
pixels will be rendered symetrically around the mathematical+ −
defined points, while rendering with a pen with an odd number of+ −
pixels, the spare pixel will be rendered to the right and below+ −
the mathematical point as in the one pixel case. See the QRectF+ −
diagrams below for concrete examples.+ −
+ −
\table+ −
\header+ −
\o {3,1} QRectF+ −
\row+ −
\o \inlineimage qrect-diagram-zero.png+ −
\o \inlineimage qrectf-diagram-one.png+ −
\row+ −
\o Logical representation+ −
\o One pixel wide pen+ −
\row+ −
\o \inlineimage qrectf-diagram-two.png+ −
\o \inlineimage qrectf-diagram-three.png+ −
\row+ −
\o Two pixel wide pen+ −
\o Three pixel wide pen+ −
\endtable+ −
+ −
Note that for historical reasons the return value of the+ −
QRect::right() and QRect::bottom() functions deviate from the true+ −
bottom-right corner of the rectangle.+ −
+ −
QRect's \l {QRect::right()}{right()} function returns \l+ −
{QRect::left()}{left()} + \l {QRect::width()}{width()} - 1 and the+ −
\l {QRect::bottom()}{bottom()} function returns \l+ −
{QRect::top()}{top()} + \l {QRect::height()}{height()} - 1. The+ −
bottom-right green point in the diagrams shows the return+ −
coordinates of these functions.+ −
+ −
We recommend that you simply use QRectF instead: The QRectF class+ −
defines a rectangle in the plane using floating point coordinates+ −
for accuracy (QRect uses integer coordinates), and the+ −
QRectF::right() and QRectF::bottom() functions \e do return the+ −
true bottom-right corner.+ −
+ −
Alternatively, using QRect, apply \l {QRect::x()}{x()} + \l+ −
{QRect::width()}{width()} and \l {QRect::y()}{y()} + \l+ −
{QRect::height()}{height()} to find the bottom-right corner, and+ −
avoid the \l {QRect::right()}{right()} and \l+ −
{QRect::bottom()}{bottom()} functions.+ −
+ −
\section2 Anti-aliased Painting+ −
+ −
If you set QPainter's \l {QPainter::Antialiasing}{anti-aliasing}+ −
render hint, the pixels will be rendered symetrically on both+ −
sides of the mathematically defined points:+ −
+ −
\table+ −
\row+ −
\o \inlineimage coordinatesystem-rect-antialias.png+ −
\o \inlineimage coordinatesystem-line-antialias.png+ −
\row+ −
\o+ −
+ −
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 2+ −
+ −
\o+ −
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 3+ −
\endtable+ −
+ −
\section1 Transformations+ −
+ −
By default, the QPainter operates on the associated device's own+ −
coordinate system, but it also has complete support for affine+ −
coordinate transformations.+ −
+ −
You can scale the coordinate system by a given offset using the+ −
QPainter::scale() function, you can rotate it clockwise using the+ −
QPainter::rotate() function and you can translate it (i.e. adding+ −
a given offset to the points) using the QPainter::translate()+ −
function.+ −
+ −
\table+ −
\row+ −
\o \inlineimage qpainter-clock.png+ −
\o \inlineimage qpainter-rotation.png+ −
\o \inlineimage qpainter-scale.png+ −
\o \inlineimage qpainter-translation.png+ −
\row+ −
\o nop+ −
\o \l {QPainter::rotate()}{rotate()}+ −
\o \l {QPainter::scale()}{scale()}+ −
\o \l {QPainter::translate()}{translate()}+ −
\endtable+ −
+ −
You can also twist the coordinate system around the origin using+ −
the QPainter::shear() function. See the \l {demos/affine}{Affine+ −
Transformations} demo for a visualization of a sheared coordinate+ −
system. All the transformation operations operate on QPainter's+ −
transformation matrix that you can retrieve using the+ −
QPainter::worldTransform() function. A matrix transforms a point+ −
in the plane to another point.+ −
+ −
If you need the same transformations over and over, you can also+ −
use QTransform objects and the QPainter::worldTransform() and+ −
QPainter::setWorldTransform() functions. You can at any time save the+ −
QPainter's transformation matrix by calling the QPainter::save()+ −
function which saves the matrix on an internal stack. The+ −
QPainter::restore() function pops it back.+ −
+ −
One frequent need for the transformation matrix is when reusing+ −
the same drawing code on a variety of paint devices. Without+ −
transformations, the results are tightly bound to the resolution+ −
of the paint device. Printers have high resolution, e.g. 600 dots+ −
per inch, whereas screens often have between 72 and 100 dots per+ −
inch.+ −
+ −
\table 100%+ −
\header+ −
\o {2,1} Analog Clock Example+ −
\row+ −
\o \inlineimage coordinatesystem-analogclock.png+ −
\o+ −
The Analog Clock example shows how to draw the contents of a+ −
custom widget using QPainter's transformation matrix.+ −
+ −
Qt's example directory provides a complete walk-through of the+ −
example. Here, we will only review the example's \l+ −
{QWidget::paintEvent()}{paintEvent()} function to see how we can+ −
use the transformation matrix (i.e. QPainter's matrix functions)+ −
to draw the clock's face.+ −
+ −
We recommend compiling and running this example before you read+ −
any further. In particular, try resizing the window to different+ −
sizes.+ −
+ −
\row+ −
\o {2,1}+ −
+ −
\snippet examples/widgets/analogclock/analogclock.cpp 9+ −
+ −
First, we set up the painter. We translate the coordinate system+ −
so that point (0, 0) is in the widget's center, instead of being+ −
at the top-left corner. We also scale the system by \c side / 100,+ −
where \c side is either the widget's width or the height,+ −
whichever is shortest. We want the clock to be square, even if the+ −
device isn't.+ −
+ −
This will give us a 200 x 200 square area, with the origin (0, 0)+ −
in the center, that we can draw on. What we draw will show up in+ −
the largest possible square that will fit in the widget.+ −
+ −
See also the \l {Window-Viewport Conversion} section.+ −
+ −
\snippet examples/widgets/analogclock/analogclock.cpp 18+ −
+ −
We draw the clock's hour hand by rotating the coordinate system+ −
and calling QPainter::drawConvexPolygon(). Thank's to the+ −
rotation, it's drawn pointed in the right direction.+ −
+ −
The polygon is specified as an array of alternating \e x, \e y+ −
values, stored in the \c hourHand static variable (defined at the+ −
beginning of the function), which corresponds to the four points+ −
(2, 0), (0, 2), (-2, 0), and (0, -25).+ −
+ −
The calls to QPainter::save() and QPainter::restore() surrounding+ −
the code guarantees that the code that follows won't be disturbed+ −
by the transformations we've used.+ −
+ −
\snippet examples/widgets/analogclock/analogclock.cpp 24+ −
+ −
We do the same for the clock's minute hand, which is defined by+ −
the four points (1, 0), (0, 1), (-1, 0), and (0, -40). These+ −
coordinates specify a hand that is thinner and longer than the+ −
minute hand.+ −
+ −
\snippet examples/widgets/analogclock/analogclock.cpp 27+ −
+ −
Finally, we draw the clock face, which consists of twelve short+ −
lines at 30-degree intervals. At the end of that, the painter is+ −
rotated in a way which isn't very useful, but we're done with+ −
painting so that doesn't matter.+ −
\endtable+ −
+ −
For a demonstation of Qt's ability to perform affine+ −
transformations on painting operations, see the \l+ −
{demos/affine}{Affine Transformations} demo which allows the user+ −
to experiment with the transformation operations. See also the \l+ −
{painting/transformations}{Transformations} example which shows+ −
how transformations influence the way that QPainter renders+ −
graphics primitives. In particular, it shows how the order of+ −
transformations affects the result.+ −
+ −
For more information about the transformation matrix, see the+ −
QTransform documentation.+ −
+ −
\section1 Window-Viewport Conversion+ −
+ −
When drawing with QPainter, we specify points using logical+ −
coordinates which then are converted into the physical coordinates+ −
of the paint device.+ −
+ −
The mapping of the logical coordinates to the physical coordinates+ −
are handled by QPainter's world transformation \l+ −
{QPainter::worldTransform()}{worldTransform()} (described in the \l+ −
Transformations section), and QPainter's \l+ −
{QPainter::viewport()}{viewport()} and \l+ −
{QPainter::window()}{window()}. The viewport represents the+ −
physical coordinates specifying an arbitrary rectangle. The+ −
"window" describes the same rectangle in logical coordinates. By+ −
default the logical and physical coordinate systems coincide, and+ −
are equivalent to the paint device's rectangle.+ −
+ −
Using window-viewport conversion you can make the logical+ −
coordinate system fit your preferences. The mechanism can also be+ −
used to make the drawing code independent of the paint device. You+ −
can, for example, make the logical coordinates extend from (-50,+ −
-50) to (50, 50) with (0, 0) in the center by calling the+ −
QPainter::setWindow() function:+ −
+ −
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 4+ −
+ −
Now, the logical coordinates (-50,-50) correspond to the paint+ −
device's physical coordinates (0, 0). Independent of the paint+ −
device, your painting code will always operate on the specified+ −
logical coordinates.+ −
+ −
By setting the "window" or viewport rectangle, you perform a+ −
linear transformation of the coordinates. Note that each corner of+ −
the "window" maps to the corresponding corner of the viewport, and+ −
vice versa. For that reason it normally is a good idea to let the+ −
viewport and "window" maintain the same aspect ratio to prevent+ −
deformation:+ −
+ −
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 5+ −
+ −
If we make the logical coordinate system a square, we should also+ −
make the viewport a square using the QPainter::setViewport()+ −
function. In the example above we make it equivalent to the+ −
largest square that fit into the paint device's rectangle. By+ −
taking the paint device's size into consideration when setting the+ −
window or viewport, it is possible to keep the drawing code+ −
independent of the paint device.+ −
+ −
Note that the window-viewport conversion is only a linear+ −
transformation, i.e. it does not perform clipping. This means that+ −
if you paint outside the currently set "window", your painting is+ −
still transformed to the viewport using the same linear algebraic+ −
approach.+ −
+ −
\image coordinatesystem-transformations.png+ −
+ −
The viewport, "window" and transformation matrix determine how+ −
logical QPainter coordinates map to the paint device's physical+ −
coordinates. By default the world transformation matrix is the+ −
identity matrix, and the "window" and viewport settings are+ −
equivalent to the paint device's settings, i.e. the world,+ −
"window" and device coordinate systems are equivalent, but as we+ −
have seen, the systems can be manipulated using transformation+ −
operations and window-viewport conversion. The illustration above+ −
describes the process.+ −
+ −
\omit+ −
\section1 Related Classes+ −
+ −
Qt's paint system, Arthur, is primarily based on the QPainter,+ −
QPaintDevice, and QPaintEngine classes:+ −
+ −
\table+ −
\header \o Class \o Description+ −
\row+ −
\o QPainter+ −
\o+ −
The QPainter class performs low-level painting on widgets and+ −
other paint devices. QPainter can operate on any object that+ −
inherits the QPaintDevice class, using the same code.+ −
\row+ −
\o QPaintDevice+ −
\o+ −
The QPaintDevice class is the base class of objects that can be+ −
painted. Qt provides several devices: QWidget, QImage, QPixmap,+ −
QPrinter and QPicture, and other devices can also be defined by+ −
subclassing QPaintDevice.+ −
\row+ −
\o QPaintEngine+ −
\o+ −
The QPaintEngine class provides an abstract definition of how+ −
QPainter draws to a given device on a given platform. Qt 4+ −
provides several premade implementations of QPaintEngine for the+ −
different painter backends we support; it provides one paint+ −
engine for each supported window system and painting+ −
frameworkt. You normally don't need to use this class directly.+ −
\endtable+ −
+ −
The 2D transformations of the coordinate system are specified+ −
using the QTransform class:+ −
+ −
\table+ −
\header \o Class \o Description+ −
\row+ −
\o QTransform+ −
\o+ −
A 3 x 3 transformation matrix. Use QTransform to rotate, shear,+ −
scale, or translate the coordinate system.+ −
\endtable+ −
+ −
In addition Qt provides several graphics primitive classes. Some+ −
of these classes exist in two versions: an \c{int}-based version+ −
and a \c{qreal}-based version. For these, the \c qreal version's+ −
name is suffixed with an \c F.+ −
+ −
\table+ −
\header \o Class \o Description+ −
\row+ −
\o \l{QPoint}(\l{QPointF}{F})+ −
\o+ −
A single 2D point in the coordinate system. Most functions in Qt+ −
that deal with points can accept either a QPoint, a QPointF, two+ −
\c{int}s, or two \c{qreal}s.+ −
\row+ −
\o \l{QSize}(\l{QSizeF}{F})+ −
\o+ −
A single 2D vector. Internally, QPoint and QSize are the same, but+ −
a point is not the same as a size, so both classes exist. Again,+ −
most functions accept either QSizeF, a QSize, two \c{int}s, or two+ −
\c{qreal}s.+ −
\row+ −
\o \l{QRect}(\l{QRectF}{F})+ −
\o+ −
A 2D rectangle. Most functions accept either a QRectF, a QRect,+ −
four \c{int}s, or four \c {qreal}s.+ −
\row+ −
\o \l{QLine}(\l{QLineF}{F})+ −
\o+ −
A 2D finite-length line, characterized by a start point and an end+ −
point.+ −
\row+ −
\o \l{QPolygon}(\l{QPolygonF}{F})+ −
\o+ −
A 2D polygon. A polygon is a vector of \c{QPoint(F)}s. If the+ −
first and last points are the same, the polygon is closed.+ −
\row+ −
\o QPainterPath+ −
\o+ −
A vectorial specification of a 2D shape. Painter paths are the+ −
ultimate painting primitive, in the sense that any shape+ −
(rectange, ellipse, spline) or combination of shapes can be+ −
expressed as a path. A path specifies both an outline and an area.+ −
\row+ −
\o QRegion+ −
\o+ −
An area in a paint device, expressed as a list of+ −
\l{QRect}s. In general, we recommend using the vectorial+ −
QPainterPath class instead of QRegion for specifying areas,+ −
because QPainterPath handles painter transformations much better.+ −
\endtable+ −
\endomit+ −
+ −
\sa {Analog Clock Example}, {Transformations Example}+ −
*/+ −