Graphics and Drawing
On Symbian OS, applications do not draw directly to the window, but use a graphics context (GC) for drawing to the window. An area inside the physical screen (the device's display) first needs to be defined, any drawing occurs inside that defined window area, thus preventing an application from drawing outside its window area.
In principle, all normal graphics drawing in Symbian OS takes place in an RWindow-derived window, owned by the window server (WSERV). WSERV uses the font and bitmap server (FBSERV) for effective handling of fonts and bitmaps. It also manages other aspects of the user interaction (such as key input handling, pointer events, and so on). FBSERV is highly optimized for speed and memory consumption and all fonts and bitmaps are loaded only once into memory, and then reference counted to determine when they can be unloaded. The optimization can occasionally cause problems. For example, if an application loads a font and forgets to release it after use, it could lead to situations where the font file is left open. If the user tries to remove the font file from the file system, the installer returns an 'In use' error and removal is prevented. Another potential error situation comes with scalable graphics images. These are loaded into the memory once, and all future access is handled by using the cached image. If the content of the MIF file is altered, it might not be reflected when loading images, until the cached image is released from the memory, and the updated file reloaded.
If you need to update the screen a number of times per second, for example when writing a game, drawing through WSERV may be too slow. As an alternative, you can also draw graphics using direct screen access (DSA), which greatly reduces the overhead of communicating with the window server, and increases the drawing speed.
When you create an application using the Symbian OS application framework, drawable windows are created by constructing CCoe-Control-derived container classes for UIs, and the drawing is handled using CWindowGc in the CCoeControl's Draw() function. In case you need to get access to the container's window, you could get a handle to it by using the Window() function defined for CCoe-Control, the area set for the container can be fetched with the Rect() function call and its position in the display is returned by the Position-RelativeToScreen() function. With CCoeControl, there is no need to activate/deactivate the graphics context (and trying to do so might lead to a panic) or to implement active objects for monitoring redraw events, since all of this is already handled by the Symbian OS application framework and the CCoeControl class.
An important issue to understand with Symbian OS - and drawing in it-is that Symbian OS is event-driven, and also all drawing is implemented as event-driven drawing. This means that each redraw is started with an event, usually a WSERV-generated redraw event. WSERV implements a queue for storing redraw events in case they can't be delivered, and this queue holds a maximum of only one redraw event per window. If your application is unable to receive and handle redrawing because it is handling an event of higher priority, subsequent redraw events can be lost. However, as soon as the application can handle events again, it will process exactly one redraw event from the WSERV.
This is important to understand, since ifthe application is busy handling some other events, it will not be able to receive redraw events until it has finished. This means that no updates to the window will occur until the application has completed processing for the other event. Most often this happens when using tight for or while loops or, for example, when implementing delays with calls to User::After(). It also can happen when using User::WaitForRequest() to wait active object requests to complete. In the worst case scenario the window server will panic the hanging thread with ViewSrv 11 panic. This is why we have warned you not to use User::Wait... () throughout, whenever it has been shown in sample code (it is shown only to make the code snippet simpler).
In case the drawing also has to be handled with these tight-looping functions, the loops should be implemented as active objects where each RunL call does one round of the loop and then sleeps for a while. The sleeping could, for example, be implemented as an RTimer/CPeriodic type of timer (with idle priority). This method would also allow the drawing loops to be cancelled (since key events can be received and a menu can be shown), and it allows applications to receive redraw events from the WSERV. For more information about active objects, please refer to Chapter 3.
Drawing events are also buffered in the client side. In practice this means that lines inside the Draw() function are not executed one-by-one in the WSERV, but instead line commands are collected into a buffer, which will be executed when it is big enough or when it is flushed. For this reason, having for/while loops or User::After() in the Draw() function and trying to do drawing into the same area while changing the drawing content will not work well in practice. Instead, this kind of drawing should be timed or looped outside the Draw() function using active objects, drawing one state at a time, and waiting between draws.
The most important feature of the Draw() function is that it is non-leaving and constant. This means that no code inside the Draw() function may have the potential to leave-in case the leaving code cannot be avoided, it must be TRAPed. Since this function is constant, it cannot modify values so, for example, you can't change state variables belonging to the class inside the Draw() function. Instead, you need to change the values outside and then call the DrawNow() function to inform WSERV to draw the required content to the container's screen.
All example code for drawing in normal application frameworks in this section assumes that drawing is handled inside CCoeControl's Draw() function, where the graphics context (GC) is retrieved as follows:
void CMyContainer::Draw(const TRect& aRect,) const {
The example code in the recipes below shows just the snippets most relevant to the discussion in question. Further information about graphics and drawing on Symbian OS can be found in the Symbian Developer Library documentation, available in each SDK and online. See the Graphics section of the Symbian OS Guide for an overview of using WSERV and FBSERV, and the C++ Component Reference section for details of each API. You will also find a set of recipes for using OpenGL ES, for 3D graphics, later in Section 4.6.
Post a comment