You Are Here:

Community: Blogs

Who am I?

Carbider

Konstantine Voytenko
BluSPAN project coordinator
Fishnest Ltd.
bluspan@gmail.com

 

Calendar

« November 2009 »
Mo Tu We Th Fr Sa Su
            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            
 

Konstantine Voytenko's Forum Nokia Blog

GUI application with the BitmapBuffer

Carbider | 04 July, 2008 13:34

    In the previous post we've developed the RBitmapBuffer buffer class that holds a bitmap buffer (sources are available at the end of this post).

    Now we'll use this class in a simple Symbian UI application.
It can be tied to the Symbian applications in a many ways but we'll see the one that goes for "Hello World" sample provided with Carbide.c++ IDE.

So start the Carbide.c++ (I use the version 1.3). Create new project (File -> New -> Symbian OS C++ Project). Select the "3-rd Feature Ed. GUI Application".

The IDE will create the project with a list of items. The file of interest for us is a "..AppView.cpp" because it defines the behavior of ..AppView class that has an access to the screen.
Besides that file we, of course, need some others that establish the connections inside the program logic.

The full list is:
Listing 1.
sources:
src/..AppUi.cpp
src/..AppView.cpp
src/BitmapBuffer.cpp
src/BufferRenderer.cpp

headers:
inc/..AppUi.h
inc/..AppView.h
inc/BitmapBuffer.h
inc/BufferRenderer.h

The "BitmapBuffer" and "BufferRenderer" sources are available at the end of this post.

The ".." is the name of your project.

First let's go to the "..AppView.h" file.
We will add a new property to the ..AppView class. This property would be:
CBufferRendereriBufferRenderer;
It would store the image buffer and will be able to render it (draw on it).
To simplify the code we will make iBufferRenderer as public, for anyone can access it and draw something on it.

We'll also add one new method to the ..AppView class to output the buffer.
That is shown below (the file: "..AppView.cpp"):

Listing 2.
/**
 * Function will draw the image
 *
 */
void ..AppView::DrawImage(CWindowGc& aGc) const
{
    CFbsBitmap* bitmap = iBufferRenderer->getBitmapBuffer()      ;
    TSize       size     ( bitmap->SizeInPixels() )              ;
   
    aGc.BitBlt( TPoint(0,0), bitmap, TRect( TPoint(0,0), size ) ); // Draw
   
} // function

Also, we will append some code to the ..AppView's constructor, destructor and Draw() methods:

Listing 3.
// ------------- Constructor

void ..AppView::ConstructL(const TRect& aRect)
{
    CreateWindowL();
    SetRect(aRect);
    ActivateL();
   
    // - - - - - - -
    // Appended code :
   
    // Get system metrics
    TInt  color, gray         ;
    TRect screenSize  (Rect());
    TDisplayMode displayMode =
    CCoeEnv::Static()->WsSession().GetDefModeMaxNumColors( color, gray );
   
    // Main - instantiate the Buffer Renderer object
    iBufferRenderer          = CBufferRenderer::NewL(displayMode, screenSize);
   
} // function

// ------------- Destructor

..AppView::~CBBufferEx_AppView()
{
    // - - - - - - -
    // Appended code :
   
    // Dealocate the memory for the Buffer Renderer object
    delete iBufferRenderer;
   
} // function

// ------------- AppView's Draw() method

void ..AppView::Draw(const TRect& /*aRect*/) const
{
    CWindowGc& gc = SystemGc();
    TRect drawRect(Rect());
    gc.Clear(drawRect);
   
    // - - - - - - -
    // Appended code :

    // Put the buffer on the screen
    DrawImage(gc);
   
} // function

Now, let's draw the rectangle on the phone screen when the user selects the 'Message' button from the options menu.
To do that, we will go to the "..AppUi.cpp" file and append the HandleCommandL() method with the code below:

Listing 4.
void ..AppUi::HandleCommandL(TInt aCommand)
{
    switch (aCommand)
    {
       
        //...  ommited for clarity

        case ECommand1:
            {
            //... 
           
            // - - - - - - -
            // Appended code :
           
            // Force to draw the rectangle
            iAppView->iBufferRenderer->drawRect(TRect(10, 10, 100, 100));
            }
            break;
           
           
        //... 
       
    } // switch
      
} // function

Don't forget to include the (#include "BufferRenderer.h") BufferRenderer to the "..AppView.h" file.

You also need to include this list of libraries to your mmp file:
Listing 5.
    fbscli.lib
    bitgdi.lib
    ws32.lib

The sources of "BitmapBuffer" and "BufferRenderer" classes are available in this zip file: ..BitmapBufferClassExample..zip


end

Bitmap manipulation: Image buffer

Carbider | 13 June, 2008 10:16

    Sometimes you need to draw some graphics (lines, rectangles, images) on top of the Symbian application. When this graphics refreshes often (like animation) you need create some secondary bitmap buffer where the next frame would be drawn.
The primary and secondary buffers may then be switched.
    This is important because if to draw different picture elements to the main buffer (which continuously is mapped onto the screen of phone), user will watch flicker image. The same would be if try erasing the main buffer and then draw new frame of animation on it.

Use of the second bitmap can be attributed to the technology of "Dual buffering".


Let's look how can we realize this technique in a Symbian GUI project.
First, I'll abstract from the whole application and will show the core of creating and manipulating the buffer.

Secondary we will tie this to a simple 'Hello World!' GUI project which is available in Carbide.c++ IDE.

=== The Core ===

Let us create a Symbian C++ class that will have necessary properties and methods to organize the buffer. And also to draw to the buffer. That would be the RBitmapBuffer class.


Listing 1.
class RBitmapBuffer
{
public:

    // Some constructors and cleanup stack operations omitted for clarity
    The properties would be:
   
    CFbsBitmap*        iBitmapBuffer    ;  // Contains the bitmap whis is our buffer
    CFbsBitGc *        iDrawer            ;  // CFbsBitGc - the class to draw on Bitmap device
    CFbsBitmapDevice*  iBmpDevice        ;  // BitmapDevice is a mediator between the drawer and the buffer.
    TRect              iSizeOfScreenRect;  // The size of the screen
    TDisplayMode*      pDisplayMode        ;  // The display mode of the buffer. In general this represents the color mode.
   
    =============
    The methods would be:
   
    /* Two-phased constructor. */
    RBitmapBuffer* RBitmapBuffer::NewL(const TDisplayMode&, const TRect& )
    {
        //omitted for clarity
        //call to ConstructL
    }

    /* Initialize renderer */
    void RBitmapBuffer::ConstructL(const TDisplayMode&  aDisplayMode, const TRect& aSizeOfScreenRect)
    {
        setSizeOfScreen(aSizeOfScreenRect);
        setDisplayMode (aDisplayMode);
       
        iBitmapBuffer  = new (ELeave) CFbsBitmap;   
        iBitmapBuffer ->Create(iSizeOfScreenRect.Size() , *pDisplayMode);

        iDrawer        = CFbsBitGc::NewL();
        iBmpDevice     = CFbsBitmapDevice::NewL(iBitmapBuffer);
        // Activate virtual bitmap device
        iDrawer       -> Activate(iBmpDevice);
        iDrawer       -> SetPenColor(KRgbBlack);

        /*
           See the description below
        */

    } // function    

    /* Sets display mode of the buffer */
    void RBitmapBuffer::setDisplayMode(const TDisplayMode&  aDisplayMode)
    { pDisplayMode = (TDisplayMode*) &aDisplayMode; }
   
    /* Sets sizeOfScreeen property */
    void RBitmapBuffer::setSizeOfScreen(const TRect& aSizeOfScreenRect)
    { iSizeOfScreenRect = aSizeOfScreenRect; }
   
    /* Returns the buffer pointer so any other class can use it */
    CFbsBitmap* RBitmapBuffer::getBitmapBuffer()
    { return iBitmapBuffer; }
   
    /* Closes (deallocates) all the resources */
    CFbsBitmap* RBitmapBuffer::Close()
    {
        delete        iBitmapBuffer     ;  // Contains the bitmap whis is our buffer
        delete        iDrawer            ;  // CFbsBitGc - the class to draw on Bitmap device
        delete        iBmpDevice        ;  // BitmapDevice is a mediator between the drawer and the buffer.
    }

} // class

Let's look through the ConstructL() method which prepares the bitmap buffer.

1. Set screen size.
2. Set display mode.
3. Allocate the object of CFbsBitmap class.
4. Initialize it by Create() method as empty buffer.
5. Allocate the CFbsBitGc and CFbsBitmapDevice objects to allow drawing to the bitmap buffer.
6. Show the iDrawer the device that it can draw. The device is iBmpDevice which is initialized with iBitmapBuffer object (the actual buffer).
7. Set the color of of drawer.


Now we can inherit the RBitmapBuffer class to create a new CBufferRenderer class which will draw something to the buffer.
Let's see:


Listing 2.
class CBufferRenderer : public CBase, public RBitmapBuffer
{
  public:

    =============
    The methods (except the constructors):

    void CBufferRenderer::drawRect(TRect *aRect)
    {
        // Use parent's drawer mechanism
        iDrawer->DrawRect  ( *aRect );
    }
   
    void CBufferRenderer::~CBufferRenderer()
    {
        Close();
    }


} // class

After instantiating the CBufferRenderer class we can draw some rectangles on it (or lots of other picture elements and bitmaps) and then return the buffer to the main program that will substitute the old screen image with the new one. The code will look like below:

Listing 3.
void mainDrawer()
{
    TDisplayMode displayMode  = iEikEnv->WsSession().GetDefModeMaxNumColors( color, gray );
    TRect screenSize            (10, 10, 20, 20);
    TRect myRectangle           (10, 10, 20, 20);
    CBufferRenderer*            myBackBuffer;

    myBackBuffer              = CBufferRenderer::NewL(screenSize, displayMode);
   
    CleanupStack             :: PushL(myBackBuffer);
   
    myBackBuffer             -> drawRect(&myRectangle);
   
    someMainProgramDrawer    -> (myBackBuffer->getBitmapBuffer);
   
    CleanupStack             :: Pop(myBackBuffer);
    delete                      myBackBuffer;
} // function


Today I've shown the idea of the main core of the bitmap buffer.
This example has some pseudo code (the main program is not defined).

At the next post I'll show how to tie the RBitmapBuffer with the real Symbian GUI application.

However here is a list of the headers and libraries you will need to include to the project to use the above graphics classes:

Listing 4.
    fbscli.lib
    bitgdi.lib
    ws32.lib
 
 

Rate This

 
 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia 
RDF Facets: qdcZidentifierQSxhttpE3aE2fE2fblogsE2eforumE2enokiaE2ecomE2fblogE2fpaulE2dcoultonsE2dforumE2dnokiaE2dblogE2farchivesE2f2009E2f04E2fX qdcZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qdcZtypeQUqfntypeZBlogContentQ qdcZtypeQUqfntypeZCommunityContentQ qdcZtypeQUqfntypeZE52esourceQ qdcZtypeQUqfntypeZWebpageQ qdcZtypeQUqmarsZManagedE52esourceQ qdcZtypeQUqwebZInformationE52esourceQ qdcZtypeQUqwebZPageQ qdcZtypeQUqwebZE52esourceQ qdcZtypeQUqrdfsZE52esourceQ qfnZtypeQUqfntypeZBlogContentQ qfnZtypeQUqfntypeZCommunityContentQ qfnZtypeQUqfntypeZE52esourceQ qfnZtypeQUqfntypeZWebpageQ qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX qrdfZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qrdfZtypeQUqfntypeZBlogContentQ qrdfZtypeQUqfntypeZCommunityContentQ qrdfZtypeQUqfntypeZE52esourceQ qrdfZtypeQUqfntypeZWebpageQ qrdfZtypeQUqmarsZManagedE52esourceQ qrdfZtypeQUqwebZInformationE52esourceQ qrdfZtypeQUqwebZPageQ qrdfZtypeQUqwebZE52esourceQ qrdfZtypeQUqrdfsZE52esourceQ