source: trunk/doc/src/examples/context2d.qdoc@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 14.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at [email protected].
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \example script/context2d
30 \title Context2D Example
31
32 This Qt Script example is an implementation of the Context2D API.
33
34 \image context2d-example.png
35
36 Context2D is part of the specification for the HTML \c{<canvas>}
37 element. It can be used to draw graphics via scripting. A good
38 resource for learning more about the HTML \c{<canvas>} element is
39 the \l{http://developer.mozilla.org/en/docs/HTML:Canvas}{Mozilla Developer Center}.
40
41 \section1 Using The HTML Canvas Element in a Web Browser
42
43 First, let's look at how the \c{<canvas>} element is typically
44 used in a web browser. The following HTML snippet defines a
45 canvas of size 400x400 pixels with id \c{mycanvas}:
46
47 \code
48 <canvas width="400" height="400" id="mycanvas">Fallback content goes here.</canvas>
49 \endcode
50
51 To draw on the canvas, we must first obtain a reference to the
52 DOM element corresponding to the \c{<canvas>} tag and then call
53 the element's getContext() function. The resulting object
54 implements the Context2D API that we use to draw.
55
56 \code
57 <script>
58 var canvas = document.getElementById("mycanvas");
59 var ctx = canvas.getContext("2d");
60
61 // Draw a face
62 ctx.beginPath();
63 ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
64 ctx.moveTo(110,75);
65 ctx.arc(75,75,35,0,Math.PI,false); // Mouth
66 ctx.moveTo(65,65);
67 ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye
68 ctx.moveTo(95,65);
69 ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye
70 ctx.stroke();
71 </script>
72 \endcode
73
74 When the page is rendered by a browser that supports the
75 \c{<canvas>} tag, this would be the result:
76
77 \image context2d-example-smileysmile.png
78
79 \section1 Using Qt Script to script a Canvas
80
81 The goal of this example is to be able to evaluate scripts
82 that use the Context2D API, and render the results. Basic
83 interaction (mouse, keyboard) should also be supported.
84 In other words, we want to present scripts with an execution
85 environment that very much resembles that of a web browser. Of
86 course, our environment is only a small subset of what a browser
87 provides; i.e. we don't provide a full DOM API, only what is
88 needed to run "self-contained" Context2D scripts (i.e. scripts
89 that don't depend on other parts of the DOM document).
90
91 Our "Context2D-browser" is set up through the following steps:
92 \list
93 \o Create an Environment.
94 \o Create a Context2D, and a QContext2DCanvas widget to render it.
95 \o Add the canvas object to the environment; this will enable
96 scripts to obtain a reference to it.
97 \o Evaluate scripts in the environment.
98 \endlist
99
100 Once a script has been evaluated, the application handles any
101 timer events and input events that occur subsequently
102 (i.e. forwards events to their associated script targets).
103
104 \section1 The Context2D Class
105
106 The "heart" of this example is the Context2D C++ class that implements
107 the drawing API. Its interface is defined in terms of properties
108 and slots. Note that this class isn't tied to Qt Script in any
109 way.
110
111 \snippet examples/script/context2d/context2d.h 0
112
113 The properties define various aspects of the Context2D
114 configuration.
115
116 \snippet examples/script/context2d/context2d.h 1
117
118 The slots define the operations that can be performed.
119
120 \snippet examples/script/context2d/context2d.h 2
121
122 The changed() signal is emitted when the contents of the drawing
123 area has changed, so that clients associated with the Context2D
124 object (i.e. the canvas widget that renders it) are notified.
125
126 \section2 Implementation
127
128 Conveniently enough, the concepts, data structures and operations
129 of the Context2D API map more or less directly to Qt's painting
130 API. Conceptually, all we have to do is initialize a QPainter
131 according to the Context2D properties, and use functions like
132 QPainter::strokePath() to do the painting. Painting is done on a
133 QImage.
134
135 \snippet examples/script/context2d/context2d.cpp 0
136
137 The property accessors and most of the slots manipulate the
138 internal Context2D state in some way. For the \c{lineCap}
139 property, Context2D uses a string representation; we therefore
140 have to map it from/to a Qt::PenCapStyle. The \c{lineJoin}
141 property is handled in the same fashion. All the property setters
142 also set a \e{dirty flag} for the property; this is used to
143 decide which aspects of the QPainter that need to be updated
144 before doing the next painting operation.
145
146 \snippet examples/script/context2d/context2d.cpp 3
147
148 The implementation of the \c{fillStyle} property is interesting,
149 since the value can be either a string or a \c{CanvasGradient}.
150 We handle this by having the property be of type QVariant,
151 and check the actual type of the value to see how to handle the
152 write.
153
154 \snippet examples/script/context2d/context2d.cpp 1
155
156 Context2D does not have a concept of a paint event; painting
157 operations can happen at any time. We would like to be efficient,
158 and not have to call QPainter::begin() and QPainter::end() for
159 every painting operation, since typically many painting operations
160 will follow in quick succession. The implementations of the
161 painting operations use a helper function, beginPainting(), that
162 activates the QPainter if it isn't active already, and updates
163 the state of the QPainter (brush, pen, etc.) so that it reflects
164 the current Context2D state.
165
166 \snippet examples/script/context2d/context2d.cpp 2
167
168 The implementation of each painting operation ends by calling
169 scheduleChange(), which will post a zero-timer event if one is
170 not already pending. When the application returns to the event
171 loop later (presumably after all the drawing operations have
172 finished), the timer will trigger, QPainter::end() will be
173 called, and the changed() signal is emitted with the new
174 image as argument. The net effect is that there will typically
175 be only a single (QPainter::begin(), QPainter::end()) pair
176 executed for the full sequence of painting operations.
177
178 \section1 The Canvas Widget
179
180 \snippet examples/script/context2d/qcontext2dcanvas.h 0
181
182 The QContext2DCanvas class provides a widget that renders
183 the contents of a Context2D object. It also provides a
184 minimal scripting API, most notably the getContext() function.
185
186 \snippet examples/script/context2d/qcontext2dcanvas.cpp 3
187
188 The constructor connects to the changed() signal of the
189 Context2D object, so that the widget can update itself