javauis/m2g_akn/src/CM2GRenderContext.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/m2g_akn/src/CM2GRenderContext.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,589 @@
+/*
+* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Render context implementation
+*
+*/
+
+// INCLUDE FILES
+#include <eikenv.h> // CCoeEnv
+
+#include "CMIDGraphics.h"
+#include "CM2GRenderContext.h"
+#include "MM2GSVGProxy.h"
+
+M2G_NS_START
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+/* static */ const TReal32       MM2GRenderContext::KFullOpaque             = 1.0;
+/* static */
+const TReal32       MM2GRenderContext::KFullTransparency       = 0.0;
+/* static */
+const TUint8        MM2GRenderContext::KMaxAlphaValue          = 255;
+/* static */
+const TDisplayMode  MM2GRenderContext::KDefaultDisplayMode     = EColor16MA;
+/* static */
+const TDisplayMode  MM2GRenderContext::KMaskDisplayMode        = EGray256;
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::CM2GRenderContext
+// -----------------------------------------------------------------------------
+CM2GRenderContext::CM2GRenderContext()
+        : CBase(),
+        iProxy(NULL),
+        iEngineHandle(M2G_INVALID_HANDLE),
+        iAlpha(MM2GRenderContext::KFullOpaque),
+        iScaledAlpha(MM2GRenderContext::KMaxAlphaValue),
+        iMaskBmp(NULL),
+        iTargetBmp(NULL),
+        iImgBmp(NULL)
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::CM2GRenderContext");
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::NewL
+// -----------------------------------------------------------------------------
+CM2GRenderContext* CM2GRenderContext::NewL(MM2GSVGProxy* aProxy)
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::NewL()");
+
+    CM2GRenderContext* self = new(ELeave) CM2GRenderContext;
+    CleanupStack::PushL(self);
+
+    self->ConstructL(aProxy);
+
+    CleanupStack::Pop();
+
+    return self;
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::~CM2GRenderContext
+// -----------------------------------------------------------------------------
+CM2GRenderContext::~CM2GRenderContext()
+{
+    M2G_DEBUG_2("M2G_DEBUG: CM2GRenderContext::~CM2GRenderContext() - proxy=%d, engine=%d", iProxy, iEngineHandle);
+    if ((iEngineHandle != M2G_INVALID_HANDLE) && (iProxy != NULL))
+    {
+        TRAP_IGNORE(iProxy->DeleteSvgEngineL(iEngineHandle));
+    }
+    delete iImgBmp;
+    delete iMaskBmp;
+    iFbsSession.Disconnect();
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::BindL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::BindL(TInt& aTargetHandle, TBool aUiToolKit)
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::BindL()");
+    if (!aUiToolKit)
+    {
+        // Current Ui Toolkit is LCDUI
+        // Set target graphics bitmap
+        CMIDGraphics* graphics = MIDUnhand<CMIDGraphics>(aTargetHandle);
+        iTargetBmp = graphics->Bitmap();
+        User::LeaveIfNull(iTargetBmp);
+#ifdef RD_JAVA_NGA_ENABLED
+        iTargetCanvas = graphics->GetTargetCanvas();        
+#endif // RD_JAVA_NGA_ENABLED
+    }
+    // initialize the svg image bitmap (on which we will render later during RenderL())
+    InitImageBitmapL();
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::GetImgHandleL
+// -----------------------------------------------------------------------------
+TM2GBitmapHandle CM2GRenderContext::GetImgHandleL() const
+{
+    User::LeaveIfNull(iImgBmp);
+
+    return REINTERPRET_CAST(TM2GBitmapHandle, iImgBmp);
+}
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::InitImageBitmapL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::InitImageBitmapL()
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::InitImageBitmapL() - begin");
+
+    // get the screen size
+    TSize screenSize = CEikonEnv::Static()->ScreenDevice()->SizeInPixels();
+
+    if (iImgBmp == NULL || (iImgBmp && iImgBmp->SizeInPixels() != screenSize))
+    {
+        M2G_DEBUG_2("M2G_DEBUG: CM2GRenderContext::InitImageBitmapL() - new bitmap: w=%d, h=%d", screenSize.iWidth, screenSize.iHeight);
+        // Create a new svg surface if first time
+        // or the size of the screen is different than the actual buffer size
+
+        delete iImgBmp;
+        iImgBmp = NULL;
+
+        iImgBmp = new(ELeave) CFbsBitmap();
+
+        User::LeaveIfError(
+            iImgBmp->Create(screenSize, KDefaultDisplayMode));
+    }
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::InitImageBitmapL() - end");
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::InitMaskL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::InitMaskL(TSize aSize)
+{
+    M2G_DEBUG_2("M2G_DEBUG: CM2GRenderContext::InitMaskL( w=%d, h=%d ) - begin", aSize.iWidth, aSize.iHeight);
+
+    if (iMaskBmp == NULL || (iMaskBmp && iMaskBmp->SizeInPixels() != aSize))
+    {
+        // Create a new mask but first delete the previous one if allocated
+        delete iMaskBmp;
+        iMaskBmp = NULL;
+
+        M2G_DEBUG_0(" M2G_DEBUG: >CM2GRenderContext::InitMaskL() creates new mask ");
+
+        iMaskBmp = new(ELeave) CFbsBitmap();
+
+        User::LeaveIfError(
+            iMaskBmp->Create(aSize, KMaskDisplayMode));
+    }
+
+    User::LeaveIfNull(iMaskBmp);
+
+    // Mask is filled with the current alpha factor
+    FillBitmapL(iMaskBmp, iScaledAlpha);
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::InitMaskL() - end");
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::ReleaseL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::ReleaseL()
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ReleaseL() - begin");
+    iTargetBmp = NULL;
+#ifdef RD_JAVA_NGA_ENABLED
+    iTargetCanvas = NULL;        
+#endif // RD_JAVA_NGA_ENABLED
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ReleaseL() - end");
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::RenderL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::RenderLCDUIL(
+    TM2GSvgDocumentHandle& aSvgDocHandle,
+    const TReal32 aCurrentTime,
+    TInt aSvgW, TInt aSvgH,
+    TM2GRenderRect& aRect
+)
+{
+    // prepare viewbox
+    TRect viewbox;
+    TPoint anchor;
+
+    PrepareViewbox(aRect, aSvgW, aSvgH, viewbox, anchor);
+
+    RenderLCDUIL(aSvgDocHandle, aCurrentTime, viewbox, anchor);
+#ifdef RD_JAVA_NGA_ENABLED
+    if (iTargetCanvas && iTargetCanvas->IsEglAvailable())
+    {
+        iTargetCanvas->UpdateRect(TRect(anchor, viewbox.Size()));
+    }
+#endif // RD_JAVA_NGA_ENABLED
+    
+}
+
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::RenderESWTL(
+    TM2GSvgDocumentHandle& aSvgDocHandle,
+    const TReal32 aCurrentTime,
+    TInt aSvgW, TInt aSvgH,
+    TM2GRenderRect& aRect,
+    MSwtClient* aClientHandle,
+    TBool aUseNativeClear,
+    TInt* aReturnData)
+{
+    // prepare viewbox
+    TRect viewbox;
+    TPoint anchor;
+
+    PrepareViewbox(aRect, aSvgW, aSvgH, viewbox, anchor);
+
+    aReturnData[0] = 0;
+    aReturnData[1] = 0;
+    aReturnData[2] = 0;
+    aReturnData[3] = 0;
+    aReturnData[4] = anchor.iX;
+    aReturnData[5] = anchor.iY;
+    aReturnData[6] = viewbox.iTl.iX;
+    aReturnData[7] = viewbox.iTl.iY;
+    aReturnData[8] = viewbox.Width();
+    aReturnData[9] = viewbox.Height();
+
+    RenderESWTL(aSvgDocHandle, aCurrentTime, viewbox, anchor, aClientHandle, aUseNativeClear, aReturnData);
+
+    return;
+}
+// CM2GRenderContext::SetRenderingQualityL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::SetRenderingQualityL(TInt aMode)
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::SetRenderingQualityL()");
+    User::LeaveIfNull(iProxy);
+    iProxy->RenderQualityL(iEngineHandle, aMode);
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::SetTransparencyL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::SetTransparency(TReal32 aAlpha)
+{
+    iAlpha = aAlpha;
+    iScaledAlpha = STATIC_CAST(TUint8, (aAlpha * MM2GRenderContext::KMaxAlphaValue));
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::ConstructL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::ConstructL(MM2GSVGProxy* aProxy)
+{
+    // Init member variables
+    SetTransparency(MM2GRenderContext::KFullOpaque);
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ConstructL() - begin");
+
+    if (aProxy)
+    {
+        iProxy = aProxy;
+        iProxy->CreateSvgEngineL(iEngineHandle);
+        M2G_DEBUG_2("M2G_DEBUG: CM2GRenderContext::ConstructL() - proxy: %d, new engine: %d", iProxy, iEngineHandle);
+    }
+    else
+    {
+        M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ConstructL() - proxy is invalid");
+        M2G_THROW(KM2GArgNotOk);
+    }
+
+    User::LeaveIfError(iFbsSession.Connect());
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ConstructL() - end");
+}
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::PrepareViewbox
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::PrepareViewbox(
+    TM2GRenderRect& aRr,
+    TInt aSvgW, TInt aSvgH,
+    TRect& aViewbox, TPoint& aAnchor)
+{
+    M2G_DEBUG_6("M2G_DEBUG: CM2GRenderContext::PrepareViewbox() cX=%d, cY=%d, cW=%d, cH=%d, anchorX=%d, anchorY=%d - begin", aRr.GetClipX(), aRr.GetClipY(), aRr.GetClipW(), aRr.GetClipH(), aRr.GetAnchorX(), aRr.GetAnchorY());
+
+    // Create an anchor point and an svg render area rect
+    aAnchor.SetXY(aRr.GetAnchorX(), aRr.GetAnchorY());
+    aViewbox.SetRect(aAnchor, TSize(aSvgW, aSvgH));
+
+    // NOTE: It's already verified in Java side that the SVG render area and
+    // the clip area intersects each other
+    aViewbox.Intersection(aRr);
+
+    // Check if the clip rect has changes the svg rect
+    if (aViewbox.iTl != aAnchor)
+    {
+        // Update anchor position
+        TPoint oldAnchor(aAnchor);
+        aAnchor = aViewbox.iTl;
+
+        // Update svg rect
+        aViewbox.Move((-oldAnchor.iX), (-oldAnchor.iY));
+    }
+    else
+    {
+        // The clip rect has not changed the svg rect. Only the
+        // anchor position need to be updated
+        aViewbox.Move(-aAnchor.iX, -aAnchor.iY);
+    }
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::PrepareViewbox() - end");
+}
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::RenderL
+// -----------------------------------------------------------------------------
+/**
+ * @see CBitmapContext::BitBltMasked()
+ * @note CBitmapContext::BitBltMasked() does alpha blending if the provided mask is 256 and not null,
+ * and simply blits otherwise
+ */
+void CM2GRenderContext::RenderLCDUIL(
+    TM2GSvgDocumentHandle& aSvgDocHandle,
+    TReal32 aCurrentTime,
+    const TRect& aViewbox,
+    const TPoint& aAnchor
+)
+{
+    M2G_DEBUG_4("M2G_DEBUG: CM2GRenderContext::RenderL() viewbox: x=%d, y=%d, w=%d, h=%d begin", aViewbox.iTl.iX, aViewbox.iTl.iY, aViewbox.Size().iWidth, aViewbox.Size().iHeight);
+
+    // No need to render if content is fully transparency (i.e. alpha=0)
+    if (iScaledAlpha == 0)
+    {
+        return;
+    }
+
+    // 0: clear the previous rendered image
+    ClearBitmapL(iImgBmp);
+
+    // 1: render the svg document on the iImgBmp
+    iProxy->RenderDocumentL(
+        iEngineHandle,
+        aSvgDocHandle,
+        GetImgHandleL(), NULL, aCurrentTime);
+
+    CFbsBitmap* mask = NULL;
+
+    // 2: calculate mask if alpha-blending is used
+    if (iScaledAlpha < MM2GRenderContext::KMaxAlphaValue)
+    {
+        // mask is always the same size as the viewbox
+        CreateAlphaBlendMaskL(aViewbox.Size());
+
+        mask = iMaskBmp; // use this mask for alpha blending
+    }
+
+    // 3: blit the rendered image on the target bitmap
+    // it will do alpha blending when mask is not null
+    M2GBitmapUtils::BitBlt(*iTargetBmp,
+                           *iImgBmp,
+                           aAnchor,
+                           &aViewbox,
+                           mask);
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::RenderL() end");
+}
+
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::RenderESWTL(
+    TM2GSvgDocumentHandle& aSvgDocHandle,
+    TReal32 aCurrentTime,
+    const TRect& aViewbox,
+    const TPoint& aAnchor,
+    MSwtClient* /*aClientHandle*/,
+    TBool /*aUseNativeClear*/,
+    TInt* aReturnData)
+{
+    M2G_DEBUG_4("M2G_DEBUG: CM2GRenderContext::RenderL() viewbox: x=%d, y=%d, w=%d, h=%d begin", aViewbox.iTl.iX, aViewbox.iTl.iY, aViewbox.Size().iWidth, aViewbox.Size().iHeight);
+
+    // No need to render if content is fully transparency (i.e. alpha=0)
+    if (iScaledAlpha == 0)
+    {
+        return;
+    }
+
+    // 0: clear the previous rendered image
+    ClearBitmapL(iImgBmp);
+
+    // 1: render the svg document on the iImgBmp
+    iProxy->RenderDocumentL(
+        iEngineHandle,
+        aSvgDocHandle,
+        GetImgHandleL(), NULL, aCurrentTime);
+
+    CFbsBitmapHack* tempImgBmp = new(ELeave) CFbsBitmapHack();
+    tempImgBmp->Create(aViewbox.Size(), iImgBmp->DisplayMode());
+    ClearBitmapL(tempImgBmp);
+
+    M2GBitmapUtils::BitBlt(*tempImgBmp,
+                           *iImgBmp,
+                           aAnchor,
+                           &aViewbox,
+                           NULL);
+    aReturnData[0] = tempImgBmp->Handle();
+    aReturnData[1] = tempImgBmp->GetMyHandle();
+    tempImgBmp = NULL;
+
+    // 2: calculate mask if alpha-blending is used
+    if (iScaledAlpha < MM2GRenderContext::KMaxAlphaValue)
+    {
+        // mask is always the same size as the viewbox
+        CreateAlphaBlendMaskL(aViewbox.Size());
+
+        if (iMaskBmp)
+        {
+            CFbsBitmapHack* tempMaskBmp = new(ELeave) CFbsBitmapHack();
+            tempMaskBmp->Create(aViewbox.Size(), iMaskBmp->DisplayMode());
+            ClearBitmapL(tempMaskBmp);
+
+            M2GBitmapUtils::BitBlt(*tempMaskBmp,
+                                   *iMaskBmp,
+                                   aAnchor,
+                                   &aViewbox,
+                                   NULL);
+
+            aReturnData[2] = tempMaskBmp->Handle();
+            aReturnData[3] = tempMaskBmp->GetMyHandle();
+            tempMaskBmp = NULL;
+        }
+    }
+
+    // Is this needed ??
+    //iImgBmp = NULL;
+    //iMaskBmp = NULL;
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::RenderL() end");
+}
+// CM2GRenderContext::CreateAlphaBlendMask
+// -----------------------------------------------------------------------------
+/**
+ * <li> mask is initialized with iScaledAlpha for all pixels.
+ * <li> reset the mask for those pixels that are not rendered (a = 0).
+ * <li> due to anti-aliasing (a != 1),
+ * recompute the mask by combining the pixel's alpha with the whole image alpha
+ *
+ * @note The svg backbuffer area is larger than the viewbox
+ * @note The size of the mask is the same as for SVG backbuffer
+ */
+void CM2GRenderContext::CreateAlphaBlendMaskL(const TSize& aViewBox)
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::CreateAlphaBlendMaskL() - begin");
+
+    // the mask will have the same size as the svg image bitmap
+    // allocate memory for mask according to the size
+    // and initializes it with iScaledAlpha for each pixel ( i.e. Mem::Fill() = fast operation )
+    InitMaskL(iImgBmp->SizeInPixels());
+
+    // lock svg buffer and mask bitmaps
+    TM2GBitmapLock maskLock(iMaskBmp);
+    TM2GBitmapLock imgLock(iImgBmp);
+
+    TUint8*            maskDataPtr    = REINTERPRET_CAST(TUint8*, iMaskBmp->DataAddress());
+    const TUint32*     imgDataPtr     = iImgBmp->DataAddress();
+
+    // Each row of CFbsBitmap is aligned to a 4 bytes boundary
+    // if the mask width in pixels is not a multiple of 4, then we must align the pointer
+    // to the correct address corresponding to the first pixel on the line below
+
+    TInt maskMaxWidthBytes  = iMaskBmp->ScanLineLength(
+                                  iMaskBmp->SizeInPixels().iWidth, KMaskDisplayMode);
+
+    const TInt maskDeltaIndex = maskMaxWidthBytes - aViewBox.iWidth;
+
+    // the svg backbuffer width could be larger than the viewbox width
+    const TInt imgDeltaIndex = iImgBmp->SizeInPixels().iWidth - aViewBox.iWidth;
+
+    // how many pixels from the viewbox will be rechecked for alpha value
+    const TUint32 countViewBoxPixels = aViewBox.iHeight * aViewBox.iWidth;
+
+    TUint32 imgAlphaMSB;
+    TUint32 imgAlpha32;
+    TUint32 index = 0;
+
+    while (index < countViewBoxPixels)
+    {
+        // get the alpha channel in the most left octet (MSB) within a 4 octet
+        imgAlphaMSB = *imgDataPtr & 0xFF000000;
+
+        if (imgAlphaMSB == 0x0)
+        {
+            // pixel is not rendered so we mask it out
+            *maskDataPtr = 0x0;
+        }
+        else if (imgAlphaMSB != 0xFF000000)
+        {
+            // combine the pixel's alpha with the whole image's alpha (iScaledAlpha)
+            // we are not sure if shifting to right pads it with 0 to the left
+
+            imgAlpha32 = (imgAlphaMSB >> 24) & 0xFF;
+
+            // compute the combined alpha on 32b because of possible overflow,
+            // and then downcast to TUint8
+            // iScaledAlpha = 8b, KMaxAlphaValue = 8b
+
+            *maskDataPtr = TUint8(
+                               (imgAlpha32 * iScaledAlpha) / MM2GRenderContext::KMaxAlphaValue);
+        }
+
+        imgDataPtr++;
+        maskDataPtr++;
+        index++;
+
+        // synchronize the image and mask indexes because the viewbox could be smaller than the image/mask
+        if (index % aViewBox.iWidth == 0)
+        {
+            imgDataPtr += imgDeltaIndex;
+            maskDataPtr += maskDeltaIndex;
+        }
+    }
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::CreateAlphaBlendMaskL() - end");
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::ClearBitmapL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::ClearBitmapL(CFbsBitmap* aBmp)
+{
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ClearBitmap - begin");
+
+    User::LeaveIfNull(aBmp);
+
+    TM2GBitmapLock lock(aBmp);
+
+    TSize   size            = aBmp->SizeInPixels();
+    TInt    scanlineLength  = aBmp->ScanLineLength(size.iWidth, aBmp->DisplayMode());
+
+    TUint32* buf = aBmp->DataAddress();
+    char* bufBytes = REINTERPRET_CAST(char*, buf);
+
+    Mem::FillZ(bufBytes,  size.iHeight * scanlineLength);
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::ClearBitmap - end");
+}
+
+// -----------------------------------------------------------------------------
+// CM2GRenderContext::FillBitmapL
+// -----------------------------------------------------------------------------
+void CM2GRenderContext::FillBitmapL(CFbsBitmap* aBmp, const TUint8& aChar)
+{
+    M2G_DEBUG_1("M2G_DEBUG: CM2GRenderContext::FillBitmap() filled with=%d - begin", aChar);
+
+    User::LeaveIfNull(aBmp);
+
+    TM2GBitmapLock lock(aBmp);
+
+    TSize   size            = aBmp->SizeInPixels();
+    TInt    scanlineLength  = aBmp->ScanLineLength(size.iWidth, aBmp->DisplayMode());
+
+    TUint32* buf = aBmp->DataAddress();
+    char* bufBytes = REINTERPRET_CAST(char*, buf);
+
+    Mem::Fill(bufBytes, size.iHeight * scanlineLength, aChar);
+
+    M2G_DEBUG_0("M2G_DEBUG: CM2GRenderContext::FillBitmap - end");
+}
+
+M2G_NS_END