1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
|
/****************************************************************************
**
** Copyright (C) 2011 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:FDL$
** 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 Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of this
** file.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qt4-arthur.html
\title The Arthur Paint System
\contentspage {What's New in Qt 4}{Home}
\previouspage The Interview Framework
\nextpage The Scribe Classes
This document describes Qt 4's painting system, providing a
comparison between the approaches used by Qt when rendering
graphics in Qt 3 and Qt 4.
\tableofcontents
\section1 Architecture
The Qt 4 Paint System is primarily based on the classes
QPainter, QPaintDevice, and QPaintEngine. QPainter is the
class used to perform drawing operations, such as drawLine()
and drawRect(). QPaintDevice represents a device that can be
painted on using a QPainter; both QWidget and QPixmap are
QPaintDevices. QPaintEngine provides the interface that the
painter uses to draw onto different types of devices.
\section2 A Look Back at Qt 3
In Qt 3, QPainter could be used to draw on widgets and pixmaps.
(It could also be used to draw to printers on Windows and Mac OS
X.) When other paint devices needed to be supported, such as
QPrinter on X11, this was done by deriving from QPaintDevice and
reimplementing the virtual function QPaintDevice::cmd(). A
reimplemented paint device was treated as an external device.
QPainter was capable of recognizing external devices and could
serialize each paint operation to the reimplemented cmd()
function. This allowed reimplementation of arbitrary devices, but
the approach has some disadvantages which we have addressed in
Qt 4. One of these is that an external device could not reuse any
functionality implemented in QPainter since QPainter was tied to
widget/pixmap painting on that platform. Supporting multiple
device backends, such as OpenGL, was therefore inconvenient and
not very efficient.
This has led us to devise a more convenient and intuitive API for
Qt 4.
\section2 How Painting is Done in Qt 4
In Qt 4 we have introduced the QPaintEngine abstract class.
Implementations of this class provide the concrete functionality
needed to draw to specific device types. The QPaintEngine class
is only used internally by QPainter and QPaintDevice, and it is
hidden from application programmers unless they reimplement their own
device types for their own QPaintEngine subclasses. Qt currently
provides paint engines for the following platforms and APIs:
\list
\o A pixel-based engine for the Windows platform that is
also used to draw onto QImages on all platforms
\o OpenGL on all platforms
\o PostScript on Linux, Unix, and Mac OS X
\o QuickDraw and CoreGraphics on Mac OS X
\o X11 and the X Render Extension on Linux and Unix systems
\omit
\o QVFb, VNC, and LinuxFb for Qt for Embedded Linux
\endomit
\endlist
To implement support for a new backend, you must derive from
QPaintEngine and reimplement its virtual functions. You also need
to derive from QPaintDevice and reimplement the virtual function
QPaintDevice::paintEngine() to tell QPainter which paint engine
should be used to draw on this particular device.
The main benefit of this approach is that all painting follows the
same painting pipeline. This means that adding support for new features
and providing default implementations for unsupported ones has
become much simpler.
\section1 New Features in the Qt 4 Paint System
\section2 Gradient Brushes
With Qt 4 it is possible to fill shapes using gradient
brushes. A gradient in this case is used to describe the transition
from one color at a given point to different color at another point. A
gradient can span from one color to another or over a
number of colors by specifying multiple colors at positions in the
gradient area. Qt 4 supports linear, radial, and conical gradients.
Linear gradients are specified using two control points.
Setting a linear gradient brush is done by creating a QLinearGradient
object and setting it as a brush.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 0
The code shown above produces a pattern as show in the following
pixmap:
\img diagonalGradient.png
Radial gradients are specified using a center, a radius, and a
focal point. Setting a radial brush is done by creating a QRadialGradient
object and setting it as a brush.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 1
The code shown above produces a pattern as shown in the following
pixmap:
\img radialGradient.png
Conical gradients are specified using a center and a start
angle. Setting a conical brush is done by creating a
QConicalGradient object and setting it as a brush.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 2
The code shown above produces a pattern as shown in the following
pixmap:
\img conicalGradient.png
\section2 Alpha-Blended Drawing
With Qt 4 we support alpha-blended outlining and filling. The
alpha channel of a color is defined through QColor. The alpha
channel specifies the transparency effect, 0 represents a fully
transparent color, while 255 represents a fully opaque color. For
example:
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 3
The code shown above produces the following output:
\img alphafill.png
Alpha-blended drawing is supported on Windows, Mac OS X, and on
X11 systems that have the X Render extension installed.
\section2 QPainter and QGLWidget
It is now possible to open a QPainter on a QGLWidget as if it
were a normal QWidget. One huge benefit from this is that we
utilize the high performance of OpenGL for most drawing
operations, such as transformations and pixmap drawing.
\section2 Anti-Aliased Edges
On platforms where this is supported by the native drawing API, we
provide the option of turning on anti-aliased edges when drawing
graphics primitives.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 4
This produces the following output:
\img antialiased.png
Anti-aliasing is supported when drawing to a QImage and on all
systems, except on X11 when XRender is not present.
\section2 Extensive Use of Native Graphics Operations
Where this makes sense, Qt uses native graphics
operations. The benefit we gain from this is that these operations
can potentially be performed in hardware, giving significant
speed improvements over many pure-software implementations.
Among these are native transformations (Mac OS X and OpenGL),
making painting with a world matrix much faster. Some pixmap
operations have also been moved closer to the underlying
hardware implementations.
\section2 Painter Paths
A painter path is an object composed of a number of graphical
building blocks, such as rectangles, ellipses, lines, and curves.
A painter path can be used for filling, outlining, and for clipping.
The main advantage of painter paths over normal drawing operations
is that it is possible to build up non-linear shapes which can be
drawn later in one go.
Building blocks can be joined in closed subpaths, such as a
rectangle or an ellipse, or they can exist independently as unclosed
subpaths, although an unclosed path will not be filled.
Below is a code example on how a path can be used. The
painter in this case has a pen width of 3 and a light blue brush. We
first add a rectangle, which becomes a closed subpath. We then add
two bezier curves, and finally draw the entire path.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 5
The code above produces the following output:
\img pathexample.png
\section2 Widget Double-Buffering
In Qt 4, all widgets are double-buffered by default.
In previous versions of Qt double-buffering was achieved by
painting to an off-screen pixmap then copying the pixmap to the
screen. For example:
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 6
Since the double-buffering is handled by QWidget internally this
now becomes:
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 7
Double-buffering is turned on by default, but can be turned off for
individual widgets by setting the widget attribute
Qt::WA_PaintOnScreen.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 8
\section2 Pen and Brush Transformation
In Qt 3, pens and brushes weren't affected by the painter's
transformation matrix. For example, if you drew a rectangle with a
pen width of 1 using a scaled painter, the resulting line width
would still be 1. This made it difficult to implement features
such as zooming and high-resolution printing.
In Qt 4, pens and brushes honor the painter's transformation
matrix.
Note that this feature is still in development and not yet
supported on all platforms.
\section2 Custom Filled Pens
In Qt 4, it is possible to specify how an outline should be
filled. It can be a solid color or a QBrush, which makes it
possible to specify both texture and gradient fills for both
text and outlines.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 9
The code above produces the following output:
\img gradientText.png
\section2 QImage as a Paint Device
A great improvement of Qt 4 over previous versions it that it now
provides a pixel-based raster paint engine which allows users to
open a painter on a QImage. The QImage paint engine supports the
full feature set of QPainter (paths, antialiasing, alphablending,
etc.) and can be used on all platforms.
One advantage of this is that it is possible to guarantee the
pixel exactness of any drawing operation in a platform-independent
way.
Painting on an image is as simple as drawing on any other paint device.
\snippet doc/src/snippets/code/doc_src_qt4-arthur.cpp 10
\section2 SVG Rendering Support
\l{Scalable Vector Graphics} (SVG) is an language for describing both static
and animated two-dimensional vector graphics. Qt includes support for the
\l{SVG 1.2 Tiny Static Features}{static features} of \l{SVG 1.2 Tiny}, taking
advantage of the improved paint system in Qt 4. SVG drawings can be rendered
onto any QPaintDevice subclass, such as QWidget, QImage, and QGLWidget, to
take advantage of specific advantages of each device. This approach gives
developers the flexibility to experiment, in order to find the best solution
for each application.
\image svg-image.png
Since SVG is an XML-based format, the QtXml module is required to read SVG
files. For this reason, classes for SVG handling are provided separately in
the QtSvg module.
Displaying an SVG drawing in an application is as simple as displaying a
bitmap image. QSvgWidget is a display widget that can be placed in an
appropriate place in a user interface, and new content can be loaded as
required. For example, a predetermined file can be loaded and displayed in
a widget with little effort:
\snippet doc/src/snippets/qsvgwidget/main.cpp 0
For applications with more specialized requirements, the QSvgRenderer class
provides more control over the way SVG drawings are rendered and animated.
*/
|