posted by Jean-Louis Villecroze on Wed 8th Dec 2004 21:40 UTC

"Zinzala, Page 3/11"
A few considerations

Before we get down to business, let's talk a little about the coding conventions and practices that we are going to use. The coding style might be new to you, unless you have already been exposed to some Symbian programming. We will also be using exceptions for error handling associated with two very interesting things called two-phase construction and cleanup stack.

The need for both mechanisms arise from the fact that an embedded system must be stable and must run for a long period of time. This puts pressure on the applications to avoid memory leak, and to be robust to situations where resources are low. Error conditions must also be handled in a safe and appropriate fashion.

The cleanup stack provides a way of cleaning objects allocated on the heap, whose pointers will be lost when an exception occurs. Because a class destructor will not be called on a partially created object, a C++ constructor should not throw an exception in order to avoid memory leak. It is recommended that you use a two-phase construction. This also gives the opportunity to push objects on the cleanup stack. If you have some Symbian experience, it will look very familiar...

Since we are only focusing on building a custom widget, we are not going to discuss the purpose and usefulness of the two-phase construction and cleanup stack in detail. Instead, you may want to read the first Zinzala newsletter or a document on Symbian Application Development to learn more about them.

The code sequences that we will be addressing in this article have been annotated in order to explain particular points. Don't get confused if it doesn't look like it could compile ;-) A link to the complete version will be given before each annotated sequence.

2. Implementing skinability

In order to support skinability in the widget, we need to answer these two questions:

  1. How do I transform a graphic into something useful for the widget?
  2. How will the widget access it ?

Turning a GIF into a resource

Instead of letting the widget load each graphic file, we are going to process and store them into one shared object (a .so). This solution saves the widget the need of transforming each image from a GIF file to a cBitmap object each time we construct it. It also presents a more elegant solution, since all the graphics will be in one file. Now, we are going to transform all our graphics into a set of resources. For that purpose we are going to create a simple tool, which outputs given GIF files into a C++ file to be compiled. We will be calling it img2res.

Loading an image into a cBitmap
First, we will see how we can load a given graphic file into a cBitmap object which defines a basic bitmap. The current version of the Zinzala SDK does not provide any mechanism to do so in the way BeOS was using translators, so we are going to use a little bit of pure Photon API.

Here's the implementation of the function LoadBitmap():

cBitmap *LoadBitmap(const tChar *aFilename)
   PhImage_t*     lImage = NULL;
   PiLoadInfo_t   lInfo;
   PiIoHandler_t* lHandler;
   const tChar*   lExt;
   tUint16        lPos;

   // extract extension of the image

In order to load an image, we need to find out what the image format is from its file extension. By using the static class sStrTools, which provides many methods to manipulate strings, we can search for the position of the last dot in the string. The file extension will be everything after the last dot. If that character cannot be found, sStrTools::FindLast() will return false.

      // get the handler for the image format
      lExt     = &aFilename[lPos+1];
      lHandler = PiIoGetHandlerByExt(lExt);


Once we have got the file extension in the variable lExt, we can call the Photon function PiIoGetHandlerByExt() to give us the handler that will be used to load the image. If the file format is not supported lHandler will be set to NULL. Photon currently provide only handlers for GIF, JPEG, BMP and PNG.


         lInfo.flags           = Pi_IO_SHMEM;
         lInfo.shmem_threshold = 100;
         lInfo.handler         = lHandler;
         lInfo.filename        = aFilename;

         // load the image
         lImage = PiLoadImage(&lInfo);

PiLoadImage() loads the image from the file into a Photon image structure PhImage_t. A structure of type PiLoadInfo_t is used as an argument to pass all the required information to the function, such as the filename and the handler to be used. The flag Pi_IO_SHMEM indicates that the image to be created should use shared memory, if its size is above a given threshold. Using shared memory for the image data, which are rows of pixels, is a nice idea when the bitmap is to be displayed. The Photon server will access the image's data in the shared memory when it is draw, instead of having the application send it. This is not really required here, since we will not be displaying the image.

            cBitmap* lBitmap;

            // create a cBitmap and return it
            lBitmap = new cBitmap(lImage);
               return lBitmap;
               return NULL;
            return NULL;

If the image was successfully loaded into lImage, we can use it to create a cBitmap object. The static method VerifyD() checks the validity of the object. If the object has been allocated and is invalid, it will be deleted by that method. Otherwise, the method will return kErrNone. Since the cBitmap assume ownership of the Photon image, we don't need to delete it.

         return NULL;
      return NULL;

Table of contents
  1. "Zinzala, Page 1/11"
  2. "Zinzala, Page 2/11"
  3. "Zinzala, Page 3/11"
  4. "Zinzala, Page 4/11"
  5. "Zinzala, Page 5/11"
  6. "Zinzala, Page 6/11"
  7. "Zinzala, Page 7/11"
  8. "Zinzala, Page 8/11"
  9. "Zinzala, Page 9/11"
  10. "Zinzala, Page 10/11"
  11. "Zinzala, Page 11/11"
e p (0)    12 Comment(s)

Technology White Papers

See More