0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 |
** All rights reserved.
|
|
5 |
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
6 |
**
|
|
7 |
** This file is part of the documentation of the Qt Toolkit.
|
|
8 |
**
|
|
9 |
** $QT_BEGIN_LICENSE:LGPL$
|
|
10 |
** No Commercial Usage
|
|
11 |
** This file contains pre-release code and may not be distributed.
|
|
12 |
** You may use this file in accordance with the terms and conditions
|
|
13 |
** contained in the Technology Preview License Agreement accompanying
|
|
14 |
** this package.
|
|
15 |
**
|
|
16 |
** GNU Lesser General Public License Usage
|
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
18 |
** General Public License version 2.1 as published by the Free Software
|
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
20 |
** packaging of this file. Please review the following information to
|
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
23 |
**
|
|
24 |
** In addition, as a special exception, Nokia gives you certain additional
|
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
27 |
**
|
|
28 |
** If you have questions regarding the use of this file, please contact
|
|
29 |
** Nokia at qt-info@nokia.com.
|
|
30 |
**
|
|
31 |
**
|
|
32 |
**
|
|
33 |
**
|
|
34 |
**
|
|
35 |
**
|
|
36 |
**
|
|
37 |
**
|
|
38 |
** $QT_END_LICENSE$
|
|
39 |
**
|
|
40 |
****************************************************************************/
|
|
41 |
|
|
42 |
/*!
|
|
43 |
\page coordsys.html
|
|
44 |
\title The Coordinate System
|
|
45 |
\brief Information about the coordinate system used by the paint
|
|
46 |
system.
|
|
47 |
|
|
48 |
\previouspage Drawing and Filling
|
|
49 |
\contentspage The Paint System
|
|
50 |
\nextpage Reading and Writing Image Files
|
|
51 |
|
|
52 |
The coordinate system is controlled by the QPainter
|
|
53 |
class. Together with the QPaintDevice and QPaintEngine classes,
|
|
54 |
QPainter form the basis of Qt's painting system, Arthur. QPainter
|
|
55 |
is used to perform drawing operations, QPaintDevice is an
|
|
56 |
abstraction of a two-dimensional space that can be painted on
|
|
57 |
using a QPainter, and QPaintEngine provides the interface that the
|
|
58 |
painter uses to draw onto different types of devices.
|
|
59 |
|
|
60 |
The QPaintDevice class is the base class of objects that can be
|
|
61 |
painted: Its drawing capabilities are inherited by the QWidget,
|
|
62 |
QPixmap, QPicture, QImage, and QPrinter classes. The default
|
|
63 |
coordinate system of a paint device has its origin at the top-left
|
|
64 |
corner. The \e x values increase to the right and the \e y values
|
|
65 |
increase downwards. The default unit is one pixel on pixel-based
|
|
66 |
devices and one point (1/72 of an inch) on printers.
|
|
67 |
|
|
68 |
The mapping of the logical QPainter coordinates to the physical
|
|
69 |
QPaintDevice coordinates are handled by QPainter's transformation
|
|
70 |
matrix, viewport and "window". The logical and physical coordinate
|
|
71 |
systems coincide by default. QPainter also supports coordinate
|
|
72 |
transformations (e.g. rotation and scaling).
|
|
73 |
|
|
74 |
\tableofcontents
|
|
75 |
|
|
76 |
\section1 Rendering
|
|
77 |
|
|
78 |
\section2 Logical Representation
|
|
79 |
|
|
80 |
The size (width and height) of a graphics primitive always
|
|
81 |
correspond to its mathematical model, ignoring the width of the
|
|
82 |
pen it is rendered with:
|
|
83 |
|
|
84 |
\table
|
|
85 |
\row
|
|
86 |
\o \inlineimage coordinatesystem-rect.png
|
|
87 |
\o \inlineimage coordinatesystem-line.png
|
|
88 |
\row
|
|
89 |
\o QRect(1, 2, 6, 4)
|
|
90 |
\o QLine(2, 7, 6, 1)
|
|
91 |
\endtable
|
|
92 |
|
|
93 |
\section2 Aliased Painting
|
|
94 |
|
|
95 |
When drawing, the pixel rendering is controlled by the
|
|
96 |
QPainter::Antialiasing render hint.
|
|
97 |
|
|
98 |
The \l {QPainter::RenderHint}{RenderHint} enum is used to specify
|
|
99 |
flags to QPainter that may or may not be respected by any given
|
|
100 |
engine. The QPainter::Antialiasing value indicates that the engine
|
|
101 |
should antialias edges of primitives if possible, i.e. smoothing
|
|
102 |
the edges by using different color intensities.
|
|
103 |
|
|
104 |
But by default the painter is \e aliased and other rules apply:
|
|
105 |
When rendering with a one pixel wide pen the pixels will be
|
|
106 |
rendered to the \e {right and below the mathematically defined
|
|
107 |
points}. For example:
|
|
108 |
|
|
109 |
\table
|
|
110 |
\row
|
|
111 |
\o \inlineimage coordinatesystem-rect-raster.png
|
|
112 |
\o \inlineimage coordinatesystem-line-raster.png
|
|
113 |
|
|
114 |
\row
|
|
115 |
\o
|
|
116 |
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 0
|
|
117 |
|
|
118 |
\o
|
|
119 |
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 1
|
|
120 |
\endtable
|
|
121 |
|
|
122 |
When rendering with a pen with an even number of pixels, the
|
|
123 |
pixels will be rendered symetrically around the mathematical
|
|
124 |
defined points, while rendering with a pen with an odd number of
|
|
125 |
pixels, the spare pixel will be rendered to the right and below
|
|
126 |
the mathematical point as in the one pixel case. See the QRectF
|
|
127 |
diagrams below for concrete examples.
|
|
128 |
|
|
129 |
\table
|
|
130 |
\header
|
|
131 |
\o {3,1} QRectF
|
|
132 |
\row
|
|
133 |
\o \inlineimage qrect-diagram-zero.png
|
|
134 |
\o \inlineimage qrectf-diagram-one.png
|
|
135 |
\row
|
|
136 |
\o Logical representation
|
|
137 |
\o One pixel wide pen
|
|
138 |
\row
|
|
139 |
\o \inlineimage qrectf-diagram-two.png
|
|
140 |
\o \inlineimage qrectf-diagram-three.png
|
|
141 |
\row
|
|
142 |
\o Two pixel wide pen
|
|
143 |
\o Three pixel wide pen
|
|
144 |
\endtable
|
|
145 |
|
|
146 |
Note that for historical reasons the return value of the
|
|
147 |
QRect::right() and QRect::bottom() functions deviate from the true
|
|
148 |
bottom-right corner of the rectangle.
|
|
149 |
|
|
150 |
QRect's \l {QRect::right()}{right()} function returns \l
|
|
151 |
{QRect::left()}{left()} + \l {QRect::width()}{width()} - 1 and the
|
|
152 |
\l {QRect::bottom()}{bottom()} function returns \l
|
|
153 |
{QRect::top()}{top()} + \l {QRect::height()}{height()} - 1. The
|
|
154 |
bottom-right green point in the diagrams shows the return
|
|
155 |
coordinates of these functions.
|
|
156 |
|
|
157 |
We recommend that you simply use QRectF instead: The QRectF class
|
|
158 |
defines a rectangle in the plane using floating point coordinates
|
|
159 |
for accuracy (QRect uses integer coordinates), and the
|
|
160 |
QRectF::right() and QRectF::bottom() functions \e do return the
|
|
161 |
true bottom-right corner.
|
|
162 |
|
|
163 |
Alternatively, using QRect, apply \l {QRect::x()}{x()} + \l
|
|
164 |
{QRect::width()}{width()} and \l {QRect::y()}{y()} + \l
|
|
165 |
{QRect::height()}{height()} to find the bottom-right corner, and
|
|
166 |
avoid the \l {QRect::right()}{right()} and \l
|
|
167 |
{QRect::bottom()}{bottom()} functions.
|
|
168 |
|
|
169 |
\section2 Anti-aliased Painting
|
|
170 |
|
|
171 |
If you set QPainter's \l {QPainter::Antialiasing}{anti-aliasing}
|
|
172 |
render hint, the pixels will be rendered symetrically on both
|
|
173 |
sides of the mathematically defined points:
|
|
174 |
|
|
175 |
\table
|
|
176 |
\row
|
|
177 |
\o \inlineimage coordinatesystem-rect-antialias.png
|
|
178 |
\o \inlineimage coordinatesystem-line-antialias.png
|
|
179 |
\row
|
|
180 |
\o
|
|
181 |
|
|
182 |
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 2
|
|
183 |
|
|
184 |
\o
|
|
185 |
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 3
|
|
186 |
\endtable
|
|
187 |
|
|
188 |
\section1 Transformations
|
|
189 |
|
|
190 |
By default, the QPainter operates on the associated device's own
|
|
191 |
coordinate system, but it also has complete support for affine
|
|
192 |
coordinate transformations.
|
|
193 |
|
|
194 |
You can scale the coordinate system by a given offset using the
|
|
195 |
QPainter::scale() function, you can rotate it clockwise using the
|
|
196 |
QPainter::rotate() function and you can translate it (i.e. adding
|
|
197 |
a given offset to the points) using the QPainter::translate()
|
|
198 |
function.
|
|
199 |
|
|
200 |
\table
|
|
201 |
\row
|
|
202 |
\o \inlineimage qpainter-clock.png
|
|
203 |
\o \inlineimage qpainter-rotation.png
|
|
204 |
\o \inlineimage qpainter-scale.png
|
|
205 |
\o \inlineimage qpainter-translation.png
|
|
206 |
\row
|
|
207 |
\o nop
|
|
208 |
\o \l {QPainter::rotate()}{rotate()}
|
|
209 |
\o \l {QPainter::scale()}{scale()}
|
|
210 |
\o \l {QPainter::translate()}{translate()}
|
|
211 |
\endtable
|
|
212 |
|
|
213 |
You can also twist the coordinate system around the origin using
|
|
214 |
the QPainter::shear() function. See the \l {demos/affine}{Affine
|
|
215 |
Transformations} demo for a visualization of a sheared coordinate
|
|
216 |
system. All the transformation operations operate on QPainter's
|
|
217 |
transformation matrix that you can retrieve using the
|
|
218 |
QPainter::worldTransform() function. A matrix transforms a point
|
|
219 |
in the plane to another point.
|
|
220 |
|
|
221 |
If you need the same transformations over and over, you can also
|
|
222 |
use QTransform objects and the QPainter::worldTransform() and
|
|
223 |
QPainter::setWorldTransform() functions. You can at any time save the
|
|
224 |
QPainter's transformation matrix by calling the QPainter::save()
|
|
225 |
function which saves the matrix on an internal stack. The
|
|
226 |
QPainter::restore() function pops it back.
|
|
227 |
|
|
228 |
One frequent need for the transformation matrix is when reusing
|
|
229 |
the same drawing code on a variety of paint devices. Without
|
|
230 |
transformations, the results are tightly bound to the resolution
|
|
231 |
of the paint device. Printers have high resolution, e.g. 600 dots
|
|
232 |
per inch, whereas screens often have between 72 and 100 dots per
|
|
233 |
inch.
|
|
234 |
|
|
235 |
\table 100%
|
|
236 |
\header
|
|
237 |
\o {2,1} Analog Clock Example
|
|
238 |
\row
|
|
239 |
\o \inlineimage coordinatesystem-analogclock.png
|
|
240 |
\o
|
|
241 |
The Analog Clock example shows how to draw the contents of a
|
|
242 |
custom widget using QPainter's transformation matrix.
|
|
243 |
|
|
244 |
Qt's example directory provides a complete walk-through of the
|
|
245 |
example. Here, we will only review the example's \l
|
|
246 |
{QWidget::paintEvent()}{paintEvent()} function to see how we can
|
|
247 |
use the transformation matrix (i.e. QPainter's matrix functions)
|
|
248 |
to draw the clock's face.
|
|
249 |
|
|
250 |
We recommend compiling and running this example before you read
|
|
251 |
any further. In particular, try resizing the window to different
|
|
252 |
sizes.
|
|
253 |
|
|
254 |
\row
|
|
255 |
\o {2,1}
|
|
256 |
|
|
257 |
\snippet examples/widgets/analogclock/analogclock.cpp 9
|
|
258 |
|
|
259 |
First, we set up the painter. We translate the coordinate system
|
|
260 |
so that point (0, 0) is in the widget's center, instead of being
|
|
261 |
at the top-left corner. We also scale the system by \c side / 100,
|
|
262 |
where \c side is either the widget's width or the height,
|
|
263 |
whichever is shortest. We want the clock to be square, even if the
|
|
264 |
device isn't.
|
|
265 |
|
|
266 |
This will give us a 200 x 200 square area, with the origin (0, 0)
|
|
267 |
in the center, that we can draw on. What we draw will show up in
|
|
268 |
the largest possible square that will fit in the widget.
|
|
269 |
|
|
270 |
See also the \l {Window-Viewport Conversion} section.
|
|
271 |
|
|
272 |
\snippet examples/widgets/analogclock/analogclock.cpp 18
|
|
273 |
|
|
274 |
We draw the clock's hour hand by rotating the coordinate system
|
|
275 |
and calling QPainter::drawConvexPolygon(). Thank's to the
|
|
276 |
rotation, it's drawn pointed in the right direction.
|
|
277 |
|
|
278 |
The polygon is specified as an array of alternating \e x, \e y
|
|
279 |
values, stored in the \c hourHand static variable (defined at the
|
|
280 |
beginning of the function), which corresponds to the four points
|
|
281 |
(2, 0), (0, 2), (-2, 0), and (0, -25).
|
|
282 |
|
|
283 |
The calls to QPainter::save() and QPainter::restore() surrounding
|
|
284 |
the code guarantees that the code that follows won't be disturbed
|
|
285 |
by the transformations we've used.
|
|
286 |
|
|
287 |
\snippet examples/widgets/analogclock/analogclock.cpp 24
|
|
288 |
|
|
289 |
We do the same for the clock's minute hand, which is defined by
|
|
290 |
the four points (1, 0), (0, 1), (-1, 0), and (0, -40). These
|
|
291 |
coordinates specify a hand that is thinner and longer than the
|
|
292 |
minute hand.
|
|
293 |
|
|
294 |
\snippet examples/widgets/analogclock/analogclock.cpp 27
|
|
295 |
|
|
296 |
Finally, we draw the clock face, which consists of twelve short
|
|
297 |
lines at 30-degree intervals. At the end of that, the painter is
|
|
298 |
rotated in a way which isn't very useful, but we're done with
|
|
299 |
painting so that doesn't matter.
|
|
300 |
\endtable
|
|
301 |
|
|
302 |
For a demonstation of Qt's ability to perform affine
|
|
303 |
transformations on painting operations, see the \l
|
|
304 |
{demos/affine}{Affine Transformations} demo which allows the user
|
|
305 |
to experiment with the transformation operations. See also the \l
|
|
306 |
{painting/transformations}{Transformations} example which shows
|
|
307 |
how transformations influence the way that QPainter renders
|
|
308 |
graphics primitives. In particular, it shows how the order of
|
|
309 |
transformations affects the result.
|
|
310 |
|
|
311 |
For more information about the transformation matrix, see the
|
|
312 |
QTransform documentation.
|
|
313 |
|
|
314 |
\section1 Window-Viewport Conversion
|
|
315 |
|
|
316 |
When drawing with QPainter, we specify points using logical
|
|
317 |
coordinates which then are converted into the physical coordinates
|
|
318 |
of the paint device.
|
|
319 |
|
|
320 |
The mapping of the logical coordinates to the physical coordinates
|
|
321 |
are handled by QPainter's world transformation \l
|
|
322 |
{QPainter::worldTransform()}{worldTransform()} (described in the \l
|
|
323 |
Transformations section), and QPainter's \l
|
|
324 |
{QPainter::viewport()}{viewport()} and \l
|
|
325 |
{QPainter::window()}{window()}. The viewport represents the
|
|
326 |
physical coordinates specifying an arbitrary rectangle. The
|
|
327 |
"window" describes the same rectangle in logical coordinates. By
|
|
328 |
default the logical and physical coordinate systems coincide, and
|
|
329 |
are equivalent to the paint device's rectangle.
|
|
330 |
|
|
331 |
Using window-viewport conversion you can make the logical
|
|
332 |
coordinate system fit your preferences. The mechanism can also be
|
|
333 |
used to make the drawing code independent of the paint device. You
|
|
334 |
can, for example, make the logical coordinates extend from (-50,
|
|
335 |
-50) to (50, 50) with (0, 0) in the center by calling the
|
|
336 |
QPainter::setWindow() function:
|
|
337 |
|
|
338 |
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 4
|
|
339 |
|
|
340 |
Now, the logical coordinates (-50,-50) correspond to the paint
|
|
341 |
device's physical coordinates (0, 0). Independent of the paint
|
|
342 |
device, your painting code will always operate on the specified
|
|
343 |
logical coordinates.
|
|
344 |
|
|
345 |
By setting the "window" or viewport rectangle, you perform a
|
|
346 |
linear transformation of the coordinates. Note that each corner of
|
|
347 |
the "window" maps to the corresponding corner of the viewport, and
|
|
348 |
vice versa. For that reason it normally is a good idea to let the
|
|
349 |
viewport and "window" maintain the same aspect ratio to prevent
|
|
350 |
deformation:
|
|
351 |
|
|
352 |
\snippet doc/src/snippets/code/doc_src_coordsys.qdoc 5
|
|
353 |
|
|
354 |
If we make the logical coordinate system a square, we should also
|
|
355 |
make the viewport a square using the QPainter::setViewport()
|
|
356 |
function. In the example above we make it equivalent to the
|
|
357 |
largest square that fit into the paint device's rectangle. By
|
|
358 |
taking the paint device's size into consideration when setting the
|
|
359 |
window or viewport, it is possible to keep the drawing code
|
|
360 |
independent of the paint device.
|
|
361 |
|
|
362 |
Note that the window-viewport conversion is only a linear
|
|
363 |
transformation, i.e. it does not perform clipping. This means that
|
|
364 |
if you paint outside the currently set "window", your painting is
|
|
365 |
still transformed to the viewport using the same linear algebraic
|
|
366 |
approach.
|
|
367 |
|
|
368 |
\image coordinatesystem-transformations.png
|
|
369 |
|
|
370 |
The viewport, "window" and transformation matrix determine how
|
|
371 |
logical QPainter coordinates map to the paint device's physical
|
|
372 |
coordinates. By default the world transformation matrix is the
|
|
373 |
identity matrix, and the "window" and viewport settings are
|
|
374 |
equivalent to the paint device's settings, i.e. the world,
|
|
375 |
"window" and device coordinate systems are equivalent, but as we
|
|
376 |
have seen, the systems can be manipulated using transformation
|
|
377 |
operations and window-viewport conversion. The illustration above
|
|
378 |
describes the process.
|
|
379 |
|
|
380 |
\omit
|
|
381 |
\section1 Related Classes
|
|
382 |
|
|
383 |
Qt's paint system, Arthur, is primarily based on the QPainter,
|
|
384 |
QPaintDevice, and QPaintEngine classes:
|
|
385 |
|
|
386 |
\table
|
|
387 |
\header \o Class \o Description
|
|
388 |
\row
|
|
389 |
\o QPainter
|
|
390 |
\o
|
|
391 |
The QPainter class performs low-level painting on widgets and
|
|
392 |
other paint devices. QPainter can operate on any object that
|
|
393 |
inherits the QPaintDevice class, using the same code.
|
|
394 |
\row
|
|
395 |
\o QPaintDevice
|
|
396 |
\o
|
|
397 |
The QPaintDevice class is the base class of objects that can be
|
|
398 |
painted. Qt provides several devices: QWidget, QImage, QPixmap,
|
|
399 |
QPrinter and QPicture, and other devices can also be defined by
|
|
400 |
subclassing QPaintDevice.
|
|
401 |
\row
|
|
402 |
\o QPaintEngine
|
|
403 |
\o
|
|
404 |
The QPaintEngine class provides an abstract definition of how
|
|
405 |
QPainter draws to a given device on a given platform. Qt 4
|
|
406 |
provides several premade implementations of QPaintEngine for the
|
|
407 |
different painter backends we support; it provides one paint
|
|
408 |
engine for each supported window system and painting
|
|
409 |
frameworkt. You normally don't need to use this class directly.
|
|
410 |
\endtable
|
|
411 |
|
|
412 |
The 2D transformations of the coordinate system are specified
|
|
413 |
using the QTransform class:
|
|
414 |
|
|
415 |
\table
|
|
416 |
\header \o Class \o Description
|
|
417 |
\row
|
|
418 |
\o QTransform
|
|
419 |
\o
|
|
420 |
A 3 x 3 transformation matrix. Use QTransform to rotate, shear,
|
|
421 |
scale, or translate the coordinate system.
|
|
422 |
\endtable
|
|
423 |
|
|
424 |
In addition Qt provides several graphics primitive classes. Some
|
|
425 |
of these classes exist in two versions: an \c{int}-based version
|
|
426 |
and a \c{qreal}-based version. For these, the \c qreal version's
|
|
427 |
name is suffixed with an \c F.
|
|
428 |
|
|
429 |
\table
|
|
430 |
\header \o Class \o Description
|
|
431 |
\row
|
|
432 |
\o \l{QPoint}(\l{QPointF}{F})
|
|
433 |
\o
|
|
434 |
A single 2D point in the coordinate system. Most functions in Qt
|
|
435 |
that deal with points can accept either a QPoint, a QPointF, two
|
|
436 |
\c{int}s, or two \c{qreal}s.
|
|
437 |
\row
|
|
438 |
\o \l{QSize}(\l{QSizeF}{F})
|
|
439 |
\o
|
|
440 |
A single 2D vector. Internally, QPoint and QSize are the same, but
|
|
441 |
a point is not the same as a size, so both classes exist. Again,
|
|
442 |
most functions accept either QSizeF, a QSize, two \c{int}s, or two
|
|
443 |
\c{qreal}s.
|
|
444 |
\row
|
|
445 |
\o \l{QRect}(\l{QRectF}{F})
|
|
446 |
\o
|
|
447 |
A 2D rectangle. Most functions accept either a QRectF, a QRect,
|
|
448 |
four \c{int}s, or four \c {qreal}s.
|
|
449 |
\row
|
|
450 |
\o \l{QLine}(\l{QLineF}{F})
|
|
451 |
\o
|
|
452 |
A 2D finite-length line, characterized by a start point and an end
|
|
453 |
point.
|
|
454 |
\row
|
|
455 |
\o \l{QPolygon}(\l{QPolygonF}{F})
|
|
456 |
\o
|
|
457 |
A 2D polygon. A polygon is a vector of \c{QPoint(F)}s. If the
|
|
458 |
first and last points are the same, the polygon is closed.
|
|
459 |
\row
|
|
460 |
\o QPainterPath
|
|
461 |
\o
|
|
462 |
A vectorial specification of a 2D shape. Painter paths are the
|
|
463 |
ultimate painting primitive, in the sense that any shape
|
|
464 |
(rectange, ellipse, spline) or combination of shapes can be
|
|
465 |
expressed as a path. A path specifies both an outline and an area.
|
|
466 |
\row
|
|
467 |
\o QRegion
|
|
468 |
\o
|
|
469 |
An area in a paint device, expressed as a list of
|
|
470 |
\l{QRect}s. In general, we recommend using the vectorial
|
|
471 |
QPainterPath class instead of QRegion for specifying areas,
|
|
472 |
because QPainterPath handles painter transformations much better.
|
|
473 |
\endtable
|
|
474 |
\endomit
|
|
475 |
|
|
476 |
\sa {Analog Clock Example}, {Transformations Example}
|
|
477 |
*/
|