|
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 */ |