javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtimage.cpp
branchRCL_3
changeset 19 04becd199f91
child 60 6c158198356e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtimage.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1945 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Nokia Corporation - S60 implementation
+ *******************************************************************************/
+
+
+#include "swtimage.h"
+#include "swtgrimagedata.h"
+#include "swtgrpalettedata.h"
+#include "swtcontrolhelper.h"
+#include "swtdisplay.h" // needed for macro definitions
+
+
+// Look-up table for the bit-reversed value of a byte.
+static const TUint8 KBitReverseTable[256] =
+{
+    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::NewL
+// ---------------------------------------------------------------------------
+//
+CSwtImage* CSwtImage::NewL(MSwtDevice& aDevice, const TSize& aSize,
+                           MSwtDisplay& aDisplay, TDisplayMode aMode /*=ENone*/)
+{
+    CSwtImage* self = new(ELeave) CSwtImage(&aDevice, &aDisplay);
+    CleanupStack::PushL(self);
+    self->ConstructL(aSize, aMode);
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::NewL
+// ---------------------------------------------------------------------------
+//
+CSwtImage* CSwtImage::NewL(MSwtDevice* aDevice, const MSwtImageData& aData,
+                           MSwtDisplay* aDisplay)
+{
+    CSwtImage* self = new(ELeave) CSwtImage(aDevice, aDisplay);
+    CleanupStack::PushL(self);
+    self->ConstructL(aData);
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::NewL
+// ---------------------------------------------------------------------------
+//
+CSwtImage* CSwtImage::NewL(CFbsBitmap& aBitmap, CFbsBitmap* aMask,
+                           const TPoint& aTopLeft, TInt aDelayTime, TSwtGifDisposal aDisposalMethod)
+{
+    CSwtImage* self = new(ELeave) CSwtImage(NULL, NULL);
+    CleanupStack::PushL(self);
+    self->ConstructL(aBitmap, aMask, aTopLeft, aDelayTime, aDisposalMethod);
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::CSwtImage
+// ---------------------------------------------------------------------------
+//
+inline CSwtImage::CSwtImage(MSwtDevice* aDevice, MSwtDisplay* aDisplay)
+        : iDevice(aDevice)
+        , iMaskType(ENoMask)
+        , iDisplay(aDisplay)
+{
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::~CSwtImage
+// ---------------------------------------------------------------------------
+//
+CSwtImage::~CSwtImage()
+{
+    iScaledMasks.ResetAndDestroy();
+    iScaledMasksInverted.ResetAndDestroy();
+    iScaledBitmaps.ResetAndDestroy();
+    iScaledBitmapRefs.Close();
+    delete iColorKey;
+    if (!iOwnExternally)
+    {
+        delete iMask;
+        delete iBitmap;
+    }
+    delete iMaskInverted;
+    delete iBitmapDevice;
+    if (iDisplay)
+    {
+        iDisplay->RemoveResourceChangeObserver(this);
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::ConstructL(const TSize& aSize, TDisplayMode aMode)
+{
+    ASSERT(iDevice);
+    ASSERT(iDisplay);
+
+    // Create the bitmap
+    iBitmap = new(ELeave) CFbsBitmap;
+
+    // By default set the image color depth to that of the device.
+    TDisplayMode mode = (aMode != ENone) ? aMode :
+                        iDisplay->CoeEnv()->ScreenDevice()->DisplayMode();
+
+    // 12-bit images aren't handled by SWT, neither will we
+    if (mode == EColor4K)
+    {
+        mode = iDisplay->CoeEnv()->ScreenDevice()->DisplayMode();
+    }
+
+    User::LeaveIfError(iBitmap->Create(aSize, mode));
+
+    // We have to set twips size of bitmap because this is used in order to get
+    // best sized fonts if a GC is created on this bitmap ( if we don't then
+    // HAL will be used and maybe this could return wrong values if device
+    // resolution has changed )
+    iBitmap->SetSizeInTwips(&(iDevice->GraphicsDevice()));
+    iDisplay->AddResourceChangeObserverL(this);
+
+    // Create the bitmap device
+    iBitmapDevice = CFbsBitmapDevice::NewL(iBitmap);
+
+    // Initialise the image information
+    iInfo.iSize = aSize;
+    iInfo.iDepth = BitDepth(mode);
+    iInfo.iScanlinePad = ScanlinePadding(iInfo.iDepth);
+    iInfo.iBytesPerLine = BytesPerLine(iInfo.iSize.iWidth, iInfo.iDepth,
+                                       iInfo.iScanlinePad);
+    iInfo.iTransparentPixel = -1;
+    iInfo.iMaskPad =  0;
+    iInfo.iAlpha = -1;
+    iInfo.iType = ESwtImagePng;
+    iInfo.iTopLeft = TPoint(0, 0);
+    iInfo.iDisposalMethod = KSwtDisposalUnspecified;
+    iInfo.iDelayTime = 0;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::ConstructL(const MSwtImageData& aData)
+{
+    TDisplayMode mode(DisplayMode(aData));
+    if (mode == ENone)
+    {
+        User::Leave(ESwtErrorUnsupportedDepth);
+    }
+
+    iInfo = aData.Info();
+
+    // Create the bitmap and its device
+    iBitmap = new(ELeave) CFbsBitmap;
+    User::LeaveIfError(iBitmap->Create(iInfo.iSize, mode));
+    iBitmapDevice = CFbsBitmapDevice::NewL(iBitmap);
+
+    // Fill the bitmap
+    if (aData.PixelBuffer().Length() != 0)
+    {
+        CopyData(*iBitmap, aData.PixelBuffer(), iInfo.iSize.iHeight,
+                 iInfo.iDepth, iInfo.iBytesPerLine, &(aData.Palette()));
+    }
+    else
+    {
+        FillBitmapL(*iBitmapDevice, KRgbBlack, TRect(iInfo.iSize));
+    }
+
+    if (iInfo.iAlpha != -1)
+    {
+        // Global alpha value, causes alphaData to be ignored.
+        iMaskType = EAlphaMask;
+        iMask = new(ELeave) CFbsBitmap;
+        User::LeaveIfError(iMask->Create(iInfo.iSize, EGray256));
+
+        iMask->LockHeap();
+        Mem::Fill(iMask->DataAddress(),
+                  iInfo.iSize.iWidth * iInfo.iSize.iHeight, iInfo.iAlpha);
+        iMask->UnlockHeap();
+    }
+    else
+    {
+        // Binary mask
+        if (aData.MaskBuffer())
+        {
+            iMaskType = EBinaryMask;
+            iMask = new(ELeave) CFbsBitmap;
+            User::LeaveIfError(iMask->Create(iInfo.iSize, EGray2));
+            TInt bpl = BytesPerLine(iInfo.iSize.iWidth, 1, iInfo.iMaskPad);
+            CopyData(*iMask, *aData.MaskBuffer(), iInfo.iSize.iHeight, 1, bpl, NULL);
+        }
+        // Colour key mask, binary mask
+        else if (iInfo.iTransparentPixel != -1)
+        {
+            iMaskType = EDirtyColorKey;
+            iMask = new(ELeave) CFbsBitmap;
+            User::LeaveIfError(iMask->Create(iInfo.iSize, EGray2));
+            SetColorKeyL(aData);
+            ComputeColorKeyMask();
+        }
+        // Alpha mask
+        else if (aData.AlphaBuffer())
+        {
+            iMaskType = EAlphaMask;
+            iMask = new(ELeave) CFbsBitmap;
+            User::LeaveIfError(iMask->Create(iInfo.iSize, EGray256));
+            CopyData(*iMask, *aData.AlphaBuffer(), iInfo.iSize.iHeight, 8,
+                     iInfo.iSize.iWidth, NULL);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::ConstructL(CFbsBitmap& aBitmap, CFbsBitmap* aMask,
+                           const TPoint& aTopLeft, TInt aDelayTime, TSwtGifDisposal aDisposalMethod)
+{
+    // Caution: when using this constructor you depend on the external bitmap's lifetime
+    iOwnExternally = ETrue;
+
+    iBitmap = &aBitmap;
+    iMask = aMask;
+
+    TDisplayMode mode = iBitmap->DisplayMode();
+    if (mode == ENone || mode == EColor4K)
+    {
+        // 12-bit images aren't handled by SWT, neither will we
+        User::Leave(ESwtErrorUnsupportedDepth);
+    }
+
+    iInfo.iSize = iBitmap->SizeInPixels();
+    iInfo.iDepth = BitDepth(mode);
+    iInfo.iScanlinePad = ScanlinePadding(iInfo.iDepth);
+    iInfo.iBytesPerLine = BytesPerLine(iInfo.iSize.iWidth, iInfo.iDepth, iInfo.iScanlinePad);
+    iInfo.iTransparentPixel = -1;
+    iInfo.iMaskPad = 0;
+    iInfo.iAlpha = -1;
+    iInfo.iType = ESwtImagePng;
+    iInfo.iTopLeft = aTopLeft;
+    iInfo.iDisposalMethod = aDisposalMethod;
+    iInfo.iDelayTime = aDelayTime;
+
+    if (iMask)
+    {
+        if (iMask->DisplayMode() == EGray2)
+        {
+            iMaskType = EBinaryMask;
+        }
+        else
+        {
+            iMaskType = EAlphaMask;
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::SetColorKeyL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::SetColorKeyL(const MSwtImageData& aData)
+{
+    ASSERT(!iColorKey);
+
+    iColorKey = new(ELeave) TRgb;
+
+    const MSwtPaletteData& palette = aData.Palette();
+    const MSwtImageData::TInfo& info = aData.Info();
+
+    if (palette.IsDirect())
+    {
+        switch (info.iDepth)
+        {
+            // Monochrome, the transparent pixel is either black or white
+        case 1:
+            *iColorKey = (info.iTransparentPixel == 0) ?
+                         TRgb(0, 0, 0) : TRgb(255u, 255u, 255u);
+            break;
+            // Direct colour, extract components
+        case 16:
+        case 24:
+        case 32:
+            *iColorKey = GetRgb(info.iTransparentPixel,
+                                palette.DirectData());
+            break;
+        default:
+            User::Leave(KErrNotSupported);
+            break;
+        }
+    }
+    else
+    {
+        switch (aData.Info().iDepth)
+        {
+            // Look up the transparent pixel in the palette
+        case 1:
+        case 2:
+        case 4:
+        case 8:
+            *iColorKey = palette.IndirectData()->GetEntry(
+                             info.iTransparentPixel);
+            break;
+        default:
+            User::Leave(KErrNotSupported);
+            break;
+        }
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::EnsureMaskIsUpToDate
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::EnsureMaskIsUpToDate() const
+{
+    if (iMaskType == EDirtyColorKey)
+    {
+        const_cast<CSwtImage*>(this)->ComputeColorKeyMask();
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::ComputeColorKeyMask
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::ComputeColorKeyMask()
+{
+    ASSERT(iBitmap);
+    ASSERT(iMask && iMask->DisplayMode() == EGray2);
+    ASSERT(iColorKey);
+    ASSERT(iMaskType == EDirtyColorKey);
+
+    iMask->LockHeap(EFalse);
+    TUint32* maskPtr = iMask->DataAddress();
+
+    const TSize size(iBitmap->SizeInPixels());
+    const TInt wordsPerMaskLine = CFbsBitmap::ScanLineLength(size.iWidth, EGray2) / 4;
+
+    TRgb pixel;
+    for (TInt y = 0; y < size.iHeight; ++y)
+    {
+        TUint32 word32 = 0;
+        TInt bitsInWord = 0;
+        TInt wordsWritten = 0;
+
+        for (TInt x = 0; x < size.iWidth; ++x)
+        {
+            iBitmap->GetPixel(pixel, TPoint(x, y));
+            word32 >>= 1;
+            word32 |= (pixel == *iColorKey) ? 0 : 0x80000000;
+            if (++bitsInWord == 32)
+            {
+                maskPtr[wordsWritten++] = word32;
+                bitsInWord = 0;
+            }
+        }
+
+        if (bitsInWord != 0)
+        {
+            maskPtr[wordsWritten] = word32 >> (32 - bitsInWord);
+        }
+
+        maskPtr += wordsPerMaskLine;
+    }
+
+    iMask->UnlockHeap();
+    iMaskType = EColorKey;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::IsGrayscale
+// ---------------------------------------------------------------------------
+//
+TBool CSwtImage::IsGrayscale() const
+{
+    switch (iBitmap->DisplayMode())
+    {
+    case EGray2:
+    case EGray4:
+    case EGray16:
+    case EGray256:
+        return ETrue;
+    default:
+        return EFalse;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetPaletteDataL
+// ---------------------------------------------------------------------------
+//
+CSwtGrPaletteData* CSwtImage::GetPaletteDataL() const
+{
+    TDisplayMode mode(iBitmap->DisplayMode());
+
+    // Decide whether the palette is direct or indirect
+    TBool isDirect;
+    switch (mode)
+    {
+    case EGray2:
+    case EGray4:
+    case EGray16:
+    case EGray256:
+        isDirect = EFalse;
+        break;
+    case EColor64K:
+    case EColor16M:
+    case EColor16MU:
+    case EColor16MA:
+    case EColor16MAP:
+        isDirect = ETrue;
+        break;
+    default:
+        ASSERT(EFalse);
+        return NULL;
+    }
+
+    // Create and fill the palette data
+    CSwtGrPaletteData* data = CSwtGrPaletteData::NewL(isDirect);
+    if (isDirect)
+    {
+        CSwtGrPaletteData::TDirectData directData;
+        if (mode == EColor64K)
+        {
+            // 16-bit Symbian bitmaps are stored as [rrrrrggg gggbbbbb] ( binary )
+            directData.iRedMask = 0xF800;   // [11111000 00000000] binary
+            directData.iGreenMask = 0x07E0; // [00000111 11100000] binary
+            directData.iBlueMask = 0x001F;  // [00000000 00011111] binary
+            directData.iRedShift = -8;
+            directData.iGreenShift = -3;
+            directData.iBlueShift =  3;
+        }
+        else if (mode == EColor16M)
+        {
+            // 24-bit Symbian bitmaps are stored in BGR order; 24-bit SWT images
+            // are stored in MSB first order, this yields a pixel format of 0xbbggrr
+            directData.iRedMask = 0x0000FF;
+            directData.iGreenMask = 0x00FF00;
+            directData.iBlueMask = 0xFF0000;
+            directData.iRedShift = 0;
+            directData.iGreenShift = -8;
+            directData.iBlueShift = -16;
+        }
+        else
+        {
+            // EColor16MU, EColor16MA or EColor16MAP
+            // 32-bit Symbian bitmaps are stored in BGR order; 32-bit SWT images
+            // are stored in MSB first order, this yields a pixel format of 0xbbggrraa
+            directData.iRedMask = 0x0000FF00;
+            directData.iGreenMask = 0x00FF0000;
+            directData.iBlueMask = 0xFF000000;
+            directData.iRedShift = -8;
+            directData.iGreenShift = -16;
+            directData.iBlueShift = -24;
+        }
+        data->SetDirectData(directData);
+    }
+    else
+    {
+        data->SetIndirectData(NewGrayPaletteL(mode));
+    }
+
+    return data;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::PaletteGrayMode
+// ---------------------------------------------------------------------------
+//
+TDisplayMode CSwtImage::PaletteGrayMode(TInt aDepth, const CPalette& aPalette)
+{
+    TDisplayMode mode;
+
+    // Find the mode by looking at the bit depth
+    switch (aDepth)
+    {
+    case 8:
+        mode = EGray256;
+        break;
+    case 4:
+        mode = EGray16;
+        break;
+    case 2:
+        mode = EGray4;
+        break;
+    case 1:
+        mode = EGray2;
+        break;
+    default:
+        mode = ENone;
+        break;
+    }
+
+    // Check the colours
+    if (mode != ENone)
+    {
+        // Check the number of colours is 2^depth
+        const TInt count = aPalette.Entries();
+        if (count != (1 << aDepth))
+        {
+            return ENone;
+        }
+
+        // Check the colours are indeed gray and evenly scattered
+        for (TInt i = 0; i<count; ++i)
+        {
+            TInt l = (i*255) / (count - 1);
+            if (aPalette.GetEntry(i) != TRgb(l, l, l))
+            {
+                return ENone;
+            }
+        }
+    }
+
+    return mode;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::DisplayMode
+// ---------------------------------------------------------------------------
+//
+TDisplayMode CSwtImage::DisplayMode(const MSwtImageData& aData)
+{
+    TDisplayMode mode(ENone);
+
+    const MSwtPaletteData& palette = aData.Palette();
+    const MSwtImageData::TInfo& info = aData.Info();
+
+    // Non paletted modes
+    if (palette.IsDirect())
+    {
+        switch (info.iDepth)
+        {
+        case 1:
+            mode = EGray2;
+            break;
+        case 16:
+            mode = EColor64K;
+            break;
+        case 8:
+        case 24:
+            mode = EColor16M;
+            break;
+        case 32:
+            mode = EColor16MU;
+            break;
+        default:
+            break;
+        }
+    }
+    // Paletted modes
+    else
+    {
+        // For some reason, CFbsBitmap::SetPalette() is implemented as empty.
+        // The result is that paletted modes are not handled correctly. The
+        // workaround is to convert all colour paletted modes to 24 bits, we
+        // waste a lot of memory but at least it works.
+        TDisplayMode grayMode(PaletteGrayMode(info.iDepth,
+                                              *(palette.IndirectData())));
+        mode = (grayMode != ENone) ? grayMode : EColor16MU;
+    }
+
+    return mode;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::BitDepth
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::BitDepth(TDisplayMode aMode)
+{
+    return TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::ImageDepth
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::ImageDepth() const
+{
+    switch (iBitmap->DisplayMode())
+    {
+    case EGray2:
+        return 1;
+    case EGray4:
+        return 2;
+    case EGray16:
+        return 4;
+    case EGray256:
+        return 8;
+    case EColor16:
+        return 4;
+    case EColor256:
+        return 8;
+    case EColor64K:
+        return 16;
+    case EColor16M:
+        return 24;
+    case EColor16MU:
+        return 32;
+    case EColor16MA:
+        return 32;
+    case EColor16MAP:
+        return 32;
+    case ERgb:
+        return 24;
+    case EColor4K:
+        return 12;
+
+    default:
+    case ENone:
+    case EColorLast:
+        ASSERT(EFalse);
+        return 0;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::ScanlinePadding
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::ScanlinePadding(TInt aBitDepth)
+{
+    switch (aBitDepth)
+    {
+    case 1:
+    case 2:
+    case 4:
+    case 16:
+    case 24:
+    case 32:
+        return 4;
+    case 8:
+        // This is because of alpha data which is not supposed to have padding
+        return 1;
+    default:
+        ASSERT(EFalse);
+        return 0;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::BytesPerLine
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::BytesPerLine(TInt aPixelsPerLine, TInt aBitsPerPixel,
+                             TInt aPadding)
+{
+    TInt byteCount = (aPixelsPerLine * aBitsPerPixel + 7) / 8;
+    TInt remainder = byteCount % aPadding;
+    TInt extra = (remainder != 0) ? aPadding-remainder : 0;
+    return byteCount + extra;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::FillBitmapL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::FillBitmapL(CFbsBitmapDevice& aDevice, const TRgb& aColor,
+                            const TRect& aRect)
+{
+    CFbsBitGc* gc = CFbsBitGc::NewL();
+    gc->Activate(&aDevice);
+
+    gc->SetPenStyle(CGraphicsContext::ENullPen);
+    gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+    gc->SetBrushColor(aColor);
+    gc->DrawRect(aRect);
+
+    delete gc;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::BitBltBitmapL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::BitBltBitmapL(CFbsBitmapDevice& aDevice, const CFbsBitmap& aBitmap)
+{
+    CFbsBitGc* gc = CFbsBitGc::NewL();
+    gc->Activate(&aDevice);
+    gc->BitBlt(TPoint(0,0), &aBitmap);
+    delete gc;
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::FillBitmapL
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::FillBitmapL(CFbsBitmap& aBitmap, const TRgb& aColor,
+                            const TRect& aRect)
+{
+    CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(&aBitmap);
+    CleanupStack::PushL(device);
+    FillBitmapL(*device, aColor, aRect);
+    CleanupStack::PopAndDestroy(device);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::NewGrayPaletteL
+// ---------------------------------------------------------------------------
+//
+CPalette* CSwtImage::NewGrayPaletteL(TDisplayMode aMode)
+{
+    TInt count;
+
+    switch (aMode)
+    {
+    case EGray2:
+        count = 2;
+        break;
+    case EGray4:
+        count = 4;
+        break;
+    case EGray16:
+        count = 16;
+        break;
+    case EGray256:
+        count = 256;
+        break;
+    default:
+        ASSERT(EFalse);
+        return NULL;
+    }
+
+    CPalette* palette = CPalette::NewL(count);
+    for (TInt i = 0; i < count; ++i)
+    {
+        TInt shade = (i*255) / (count-1);
+        palette->SetEntry(i, TRgb(shade, shade, shade));
+    }
+
+    return palette;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::BitShift
+// ---------------------------------------------------------------------------
+//
+inline TUint CSwtImage::BitShift(TUint aValue, TInt aShift)
+{
+    return (aShift >= 0) ? (aValue << aShift) : (aValue >> -aShift);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetRed
+// ---------------------------------------------------------------------------
+//
+inline TUint CSwtImage::GetRed(TUint aPixel,
+                               const MSwtPaletteData::TDirectData& aPalette)
+{
+    return BitShift(aPixel & aPalette.iRedMask, aPalette.iRedShift);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetGreen
+// ---------------------------------------------------------------------------
+//
+inline TUint CSwtImage::GetGreen(TUint aPixel,
+                                 const MSwtPaletteData::TDirectData& aPalette)
+{
+    return BitShift(aPixel & aPalette.iGreenMask, aPalette.iGreenShift);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetBlue
+// ---------------------------------------------------------------------------
+//
+inline TUint CSwtImage::GetBlue(TUint aPixel,
+                                const MSwtPaletteData::TDirectData& aPalette)
+{
+    return BitShift(aPixel & aPalette.iBlueMask, aPalette.iBlueShift);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetBlue
+// ---------------------------------------------------------------------------
+//
+inline TRgb CSwtImage::GetRgb(TUint aPixel,
+                              const MSwtPaletteData::TDirectData& aPalette)
+{
+    return TRgb(GetRed(aPixel, aPalette), GetGreen(aPixel, aPalette), GetBlue(aPixel, aPalette));
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::WritePixel16
+// ---------------------------------------------------------------------------
+//
+inline void CSwtImage::WritePixel16(TUint8*& aPtr, TUint aPixel,
+                                    const MSwtPaletteData::TDirectData& aPalette)
+{
+    TUint pixel16;
+    pixel16  = (GetRed(aPixel, aPalette) & 0xF8) << 8;
+    pixel16 |= (GetGreen(aPixel, aPalette) & 0xFC) << 3;
+    pixel16 |= (GetBlue(aPixel, aPalette)) >> 3;
+
+    *reinterpret_cast<TUint16*&>(aPtr)++ = static_cast<TUint16>(pixel16);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::WritePixelTrueColor
+// ---------------------------------------------------------------------------
+//
+inline void CSwtImage::WritePixelTrueColor(TUint8*& aPtr, const TRgb& aColor, TBool a24Bit)
+{
+    *aPtr++ = static_cast<TUint8>(aColor.Blue());
+    *aPtr++ = static_cast<TUint8>(aColor.Green());
+    *aPtr++ = static_cast<TUint8>(aColor.Red());
+
+    if (!a24Bit)
+    {
+        // Since we don't get any alpha channel data for the 32-bit pixel,
+        // set it opaque.
+        *aPtr++ = 0xFF;
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::WritePixelTrueColor
+// ---------------------------------------------------------------------------
+//
+inline void CSwtImage::WritePixelTrueColor(TUint8*& aPtr, TUint aPixel,
+        const MSwtPaletteData::TDirectData& aPalette, TBool a24Bit)
+{
+    if (a24Bit)
+    {
+        *aPtr++ = static_cast<TUint8>(GetBlue(aPixel, aPalette));
+        *aPtr++ = static_cast<TUint8>(GetGreen(aPixel, aPalette));
+        *aPtr++ = static_cast<TUint8>(GetRed(aPixel, aPalette));
+    }
+    else
+    {
+        *aPtr++ = static_cast<TUint8>(GetBlue(aPixel, aPalette));
+        *aPtr++ = static_cast<TUint8>(GetGreen(aPixel, aPalette));
+        *aPtr++ = static_cast<TUint8>(GetRed(aPixel, aPalette));
+        // Alpha value is the last byte of the pixel.
+        *aPtr++ = static_cast<TUint8>(aPixel & 0xFF);
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::CopyData
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::CopyData(const CFbsBitmap& aBitmap, const TDesC8& aData,
+                         TInt aLineCount, TInt aDepth, TInt aBytesPerLine,
+                         const MSwtPaletteData* aPalette)
+{
+    aBitmap.LockHeap(EFalse);
+
+    const TUint8* srce = aData.Ptr();
+    TUint8* dest = reinterpret_cast<TUint8*>(aBitmap.DataAddress());
+
+    TDisplayMode mode(aBitmap.DisplayMode());
+    TInt destBytesPerLine = CFbsBitmap::ScanLineLength(
+                                aBitmap.SizeInPixels().iWidth, mode);
+
+    switch (mode)
+    {
+    case EGray2:
+        Copy1(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount);
+        break;
+    case EGray4:
+        Copy2(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount);
+        break;
+    case EGray16:
+        Copy4(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount);
+        break;
+    case EGray256:
+        Copy8(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount);
+        break;
+    case EColor64K:
+        ASSERT(aPalette);
+        Copy16(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount,
+               aPalette->DirectData());
+        break;
+    case EColor16M:
+    case EColor16MU:
+    case EColor16MA:
+    case EColor16MAP:
+        ASSERT(aPalette);
+        switch (aDepth)
+        {
+        case 1:
+            Copy1ToTrueColor(dest, destBytesPerLine, srce, aBytesPerLine,
+                             aLineCount, *aPalette->IndirectData(), mode == EColor16M);
+            break;
+        case 2:
+            Copy2ToTrueColor(dest, destBytesPerLine, srce, aBytesPerLine,
+                             aLineCount, *aPalette->IndirectData(), mode == EColor16M);
+            break;
+        case 4:
+            Copy4ToTrueColor(dest, destBytesPerLine, srce, aBytesPerLine,
+                             aLineCount, *aPalette->IndirectData(), mode == EColor16M);
+            break;
+        case 8:
+            if (aPalette->IsDirect())
+            {
+                Copy8ToTrueColor(dest, destBytesPerLine, srce, aBytesPerLine,
+                                 aLineCount, aPalette->DirectData(), mode == EColor16M);
+            }
+            else
+            {
+                Copy8ToTrueColor(dest, destBytesPerLine, srce, aBytesPerLine,
+                                 aLineCount, *aPalette->IndirectData(), mode == EColor16M);
+            }
+            break;
+        case 24:
+            Copy24(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount,
+                   aPalette->DirectData());
+            break;
+        case 32:
+            Copy32(dest, destBytesPerLine, srce, aBytesPerLine, aLineCount,
+                   aPalette->DirectData());
+            break;
+        default:
+            ASSERT(EFalse);
+            break;
+        }
+        break;
+    default:
+        ASSERT(EFalse);
+        break;
+    }
+
+    aBitmap.UnlockHeap();
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::CopyDataWithAlpha
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::AddMaskToAlphaChannel(const CFbsBitmap& aBitmap, const CFbsBitmap& aMask)
+{
+
+    ASSERT(aBitmap.DisplayMode() == EColor16MA
+           || aBitmap.DisplayMode() == EColor16MAP);
+    ASSERT(aMask.DisplayMode() == EGray256);
+
+    aBitmap.LockHeap(EFalse);
+    TUint8* dest = reinterpret_cast<TUint8*>(aBitmap.DataAddress());
+
+    TUint8* srce = reinterpret_cast<TUint8*>(aMask.DataAddress());
+
+
+
+    for (TInt i = 0; i < aMask.SizeInPixels().iHeight * aMask.SizeInPixels().iWidth; ++i)
+    {
+        // 1 byte = B; 2 byte = G; 3 byte = R; 4 byte = alpha
+        // skip rgb byte
+        dest++; // skip b
+        dest++; // skip g
+        dest++; // skip r
+
+        // copy alpha vaule
+        *dest = *srce;
+
+        // go next byte
+        srce++;
+        dest++;
+    }
+
+    aBitmap.UnlockHeap();
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy1
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy1(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                      TInt aBytesPerSrceLine, TInt aLineCount)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine);
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            aDest[x] = KBitReverseTable[aSrce[x]];
+        }
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy2
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy2(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                      TInt aBytesPerSrceLine, TInt aLineCount)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine);
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            TUint byte = aSrce[x];
+            aDest[x] = static_cast<TUint8>
+                       ((byte >> 6) |
+                        ((byte >> 2) & 0x0C) |
+                        ((byte << 2) & 0x30) |
+                        (byte << 6));
+        }
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy4
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy4(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                      TInt aBytesPerSrceLine, TInt aLineCount)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine);
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            TUint byte = aSrce[x];
+            aDest[x] = static_cast<TUint8>(byte >> 4 | byte << 4);
+        }
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy8
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy8(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                      TInt aBytesPerSrceLine, TInt aLineCount)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine);
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        Mem::Copy(aDest, aSrce, bytesToCopyPerLine);
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy16
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy16(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                       TInt aBytesPerSrceLine, TInt aLineCount, const MSwtPaletteData::TDirectData& aPalette)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine) & ~0x1;
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptr = aDest;
+
+        for (TInt x = 0; x < bytesToCopyPerLine; x+=2)
+        {
+            // Data in source buffer in stored LSB first
+            TUint pixel;
+            pixel  = static_cast<TUint>(aSrce[x]);
+            pixel |= static_cast<TUint>(aSrce[x+1]) << 8;
+
+            WritePixel16(ptr, pixel, aPalette);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy1To24
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy1ToTrueColor(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                                 TInt aBytesPerSrceLine, TInt aLineCount, const CPalette& aPalette, TBool a24Bit)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesPerPixel = a24Bit ? 3 : 4;
+    const TInt pixelsToCopyPerLine = Min(aBytesPerDestLine / bytesPerPixel,
+                                         aBytesPerSrceLine * 8);
+    const TInt bytesToCopyPerLine  = (pixelsToCopyPerLine + 7) / 8;
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptr = aDest;
+
+        TInt bitsLeftInLine = pixelsToCopyPerLine;
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            TUint8 byte = aSrce[x];
+            TInt bitsToCopy = Min(bitsLeftInLine, 8);
+            for (TInt i = 0; i < bitsToCopy; ++i)
+            {
+                WritePixelTrueColor(ptr, aPalette.GetEntry(byte >> 7), a24Bit);
+                byte <<= 1;
+            }
+            bitsLeftInLine -= 8;
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy2To24
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy2ToTrueColor(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                                 TInt aBytesPerSrceLine, TInt aLineCount, const CPalette& aPalette, TBool a24Bit)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesPerPixel = a24Bit ? 3 : 4;
+    const TInt pixelsToCopyPerLine = Min(aBytesPerDestLine / bytesPerPixel,
+                                         aBytesPerSrceLine*4);
+    const TInt bytesToCopyPerLine  = (pixelsToCopyPerLine + bytesPerPixel) / 4;
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptr = aDest;
+
+        TInt bitsLeftInLine = pixelsToCopyPerLine * 2;
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            TUint8 byte = aSrce[x];
+            TInt bitsToCopy = Min(bitsLeftInLine, 8);
+            for (TInt i = 0; i < bitsToCopy; i += 2)
+            {
+                WritePixelTrueColor(ptr, aPalette.GetEntry(byte >> 6), a24Bit);
+                byte <<= 2;
+            }
+            bitsLeftInLine -= 8;
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy4To24
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy4ToTrueColor(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                                 TInt aBytesPerSrceLine, TInt aLineCount, const CPalette& aPalette, TBool a24Bit)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesPerPixel = a24Bit ? 3 : 4;
+    const TInt pixelsToCopyPerLine = Min(aBytesPerDestLine / bytesPerPixel,
+                                         aBytesPerSrceLine * 2);
+    const TInt bytesToCopyPerLine = pixelsToCopyPerLine / 2;
+    const TInt remainderPerLine = pixelsToCopyPerLine % 2;
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptr = aDest;
+        TInt x;
+        for (x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            TUint8 byte = aSrce[x];
+            WritePixelTrueColor(ptr, aPalette.GetEntry(byte >> 4), a24Bit);
+            WritePixelTrueColor(ptr, aPalette.GetEntry(byte & 0x0F), a24Bit);
+        }
+
+        if (remainderPerLine != 0)
+        {
+            WritePixelTrueColor(ptr, aPalette.GetEntry(aSrce[x] >> 4), a24Bit);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy8To24
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy8ToTrueColor(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                                 TInt aBytesPerSrceLine, TInt aLineCount, const CPalette& aPalette, TBool a24Bit)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesPerPixel = a24Bit ? 3 : 4;
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine / bytesPerPixel,
+                                        aBytesPerSrceLine);
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptr = aDest;
+
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            WritePixelTrueColor(ptr, aPalette.GetEntry(aSrce[x]), a24Bit);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy8To24
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy8ToTrueColor(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                                 TInt aBytesPerSrceLine, TInt aLineCount, const MSwtPaletteData::TDirectData& aPalette,
+                                 TBool a24Bit)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    const TInt bytesPerPixel = a24Bit ? 3 : 4;
+    const TInt bytesToCopyPerLine = Min(aBytesPerDestLine / bytesPerPixel,
+                                        aBytesPerSrceLine);
+
+    const TUint redMax = BitShift(aPalette.iRedMask,  aPalette.iRedShift);
+    const TUint greenMax = BitShift(aPalette.iGreenMask, aPalette.iGreenShift);
+    const TUint blueMax = BitShift(aPalette.iBlueMask, aPalette.iBlueShift);
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptr = aDest;
+
+        for (TInt x = 0; x < bytesToCopyPerLine; ++x)
+        {
+            TUint red = (GetRed(aSrce[x], aPalette) * 255u) / redMax;
+            TUint green = (GetGreen(aSrce[x], aPalette) * 255u) / greenMax;
+            TUint blue = (GetBlue(aSrce[x], aPalette) * 255u) / blueMax;
+
+            TRgb color(red, green, blue);
+            WritePixelTrueColor(ptr, color, a24Bit);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy24
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy24(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                       TInt aBytesPerSrceLine, TInt aLineCount, const MSwtPaletteData::TDirectData& aPalette)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine);
+    bytesToCopyPerLine -= bytesToCopyPerLine % 3; // In order to have an integer number of pixels
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptrDest = aDest;
+
+        for (TInt x = 0; x < bytesToCopyPerLine; x += 3)
+        {
+            // Data in source buffer in stored MSB first
+            TUint pixel;
+            pixel = static_cast<TUint>(aSrce[x]) << 16;
+            pixel |= static_cast<TUint>(aSrce[x+1]) << 8;
+            pixel |= static_cast<TUint>(aSrce[x+2]);
+
+            WritePixelTrueColor(ptrDest, pixel, aPalette, ETrue);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Copy32
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Copy32(TUint8* aDest, TInt aBytesPerDestLine, const TUint8* aSrce,
+                       TInt aBytesPerSrceLine, TInt aLineCount, const MSwtPaletteData::TDirectData& aPalette)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    TInt bytesToCopyPerLine = Min(aBytesPerDestLine, aBytesPerSrceLine);
+    bytesToCopyPerLine -= bytesToCopyPerLine % 4; // In order to have an integer number of pixels
+
+    for (TInt y = 0; y < aLineCount; ++y)
+    {
+        TUint8* ptrDest = aDest;
+
+        for (TInt x = 0; x < bytesToCopyPerLine; x += 4)
+        {
+            TUint pixel = 0;
+
+            // Data in source buffer in stored MSB first
+            pixel = static_cast<TUint>(aSrce[x]) << 24;
+            pixel |= static_cast<TUint>(aSrce[x+1]) << 16;
+            pixel |= static_cast<TUint>(aSrce[x+2]) << 8;
+            pixel |= static_cast<TUint>(aSrce[x+3]);
+
+            WritePixelTrueColor(ptrDest, pixel, aPalette, EFalse);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetPixelDataLC
+// ---------------------------------------------------------------------------
+//
+HBufC8* CSwtImage::GetPixelDataLC(const CFbsBitmap& aBitmap)
+{
+    TSize size(aBitmap.SizeInPixels());
+    TDisplayMode mode(aBitmap.DisplayMode());
+    TInt depth = BitDepth(mode);
+    TInt bplSrce = CFbsBitmap::ScanLineLength(size.iWidth, mode);
+    TInt bplDest = BytesPerLine(size.iWidth, depth, ScanlinePadding(depth));
+    TInt bufLength = bplDest * size.iHeight;
+
+    HBufC8* buffer = HBufC8::NewLC(bufLength);
+    TPtr8 des(buffer->Des());
+    des.SetLength(bufLength);
+    TUint8* dest = const_cast<TUint8*>(des.Ptr());
+    Mem::FillZ(dest, bufLength);
+
+    aBitmap.LockHeapLC(ETrue);
+    const TUint8* srce = reinterpret_cast<TUint8*>(aBitmap.DataAddress());
+
+    switch (mode)
+    {
+    case EGray2:
+        Copy1(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EGray4:
+        Copy2(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EGray16:
+        Copy4(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EGray256:
+        /* This is workaround for case that the image width is not mutliple of four.
+           The symbian function CFbsBitmap::ScanLineLength() returns muplitple of
+           four and not the correct size. On the other hand BytesPerLine() returns
+           the correct size. When using the incorrect size the image is skewed.
+               Problem occured only on alpha bitmap with PNG images. This is the
+           reason, why this fix is present only in this switch. Also it does not
+           occur in 3.2 */
+#if defined( RD_SCALABLE_UI_V2 )
+        bplSrce = bplDest;
+#endif // RD_SCALABLE_UI_V2
+        Copy8(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EColor64K:
+        GetPixels16(dest, bplDest, srce, bplSrce, size);
+        break;
+    case EColor16M:
+        Copy8(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EColor16MU:
+        Copy8(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EColor16MA:
+        Copy8(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    case EColor16MAP:
+        Copy8(dest, bplDest, srce, bplSrce, size.iHeight);
+        break;
+    default:
+        __DEBUGGER();
+        User::Leave(KErrNotSupported);
+        break;
+    };
+
+    CleanupStack::PopAndDestroy(); // LockHeap
+
+    return buffer;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetPixels16
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::GetPixels16(TUint8* aDest, TInt aBytesPerDestLine,
+                            const TUint8* aSrce, TInt aBytesPerSrceLine, const TSize& aSize)
+{
+    ASSERT(aDest);
+    ASSERT(aSrce);
+
+    for (TInt y = 0; y<aSize.iHeight; ++y)
+    {
+        const TUint16* ptrSrce = reinterpret_cast<const TUint16*>(aSrce);
+        TUint8* ptrDest = aDest;
+
+        TInt x;
+        for (x = 0; x<aSize.iWidth; ++x)
+        {
+            TUint16 pixel = *ptrSrce++;
+
+            // Data in dest buffer in stored LSB first
+            *ptrDest++ = static_cast<TUint8>(pixel & 0x00FF);
+            *ptrDest++ = static_cast<TUint8>(pixel >> 8);
+        }
+
+        aDest += aBytesPerDestLine;
+        aSrce += aBytesPerSrceLine;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::NewGcL
+// From MSwtBitmapDrawable
+// ---------------------------------------------------------------------------
+//
+MSwtGc* CSwtImage::NewGcL()
+{
+    ASSERT(iDevice);
+    ASSERT(iDisplay);
+
+    CFbsBitGc* nativeGc = CFbsBitGc::NewL();
+    nativeGc->Activate(iBitmapDevice);
+
+    return iDisplay->Factory().NewBitmapGcL(*this, nativeGc,
+                                            DestroyNativeGc, KRgbBlack, KRgbWhite, *iDevice->GetSystemFont());
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GraphicsDevice
+// From MSwtBitmapDrawable
+// ---------------------------------------------------------------------------
+//
+CBitmapDevice& CSwtImage::GraphicsDevice()
+{
+    return *iBitmapDevice;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GraphicsDevice
+// From MSwtBitmapDrawable
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::HandleUpdate()
+{
+    if (iMaskType == EColorKey)
+    {
+        iMaskType = EDirtyColorKey;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::DestroyNativeGc
+// From MSwtBitmapDrawable
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::DestroyNativeGc(CBitmapContext* aGc)
+{
+    delete aGc;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetBitmap
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+CFbsBitmap& CSwtImage::GetBitmap() const
+{
+    return *iBitmap;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetSubBitmap
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+CFbsBitmap& CSwtImage::GetSubBitmap(const TSize& aSize) const
+{
+    ASSERT(iBitmap);
+
+    // For the original size return the main bitmap
+    if (iBitmap->SizeInPixels() == aSize)
+    {
+        return GetBitmap();
+    }
+
+    // Search scaled bitmap copy
+    CFbsBitmap* bmp = NULL;
+    TInt count = iScaledBitmaps.Count();
+    for (TInt i = 0; i < count; i++)
+    {
+        bmp = iScaledBitmaps[i];
+        if (bmp->SizeInPixels() == aSize)
+        {
+            return *bmp;
+        }
+    }
+
+    // Scaled bitmap copy not found, create one for aSize
+    TRAP_IGNORE(bmp = SwtControlHelper::GetCopyOfBitmapL(iBitmap, aSize));
+    if (bmp)
+    {
+        // Create also scaled mask copy for aSize
+        CFbsBitmap* mask = NULL;
+        CFbsBitmap* maski = NULL;
+        if (iMask)
+        {
+            TRAP_IGNORE(mask = SwtControlHelper::GetCopyOfBitmapL(iMask, aSize));
+            if (iMask->IsMonochrome())
+            {
+                TRAP_IGNORE(maski = SwtControlHelper::GetInvertedCopyOfMonoBitmapL(iMask, aSize));
+            }
+        }
+
+        // Update arrays
+
+        // NOTE! iScaledBitmapRefs, iScaledBitmaps, iScaledMasks and
+        // iScaledMasksInverted must always have the same number of entries.
+        // NOTE! iScaledMasksInverted entries are valid only if
+        // the main mask is monochrome. Otherwise they are NULL
+        // and iScaledMasks entries should be used instead.
+        iScaledBitmapRefs.Append(0);
+        iScaledBitmaps.Append(bmp);
+        iScaledMasks.Append(mask);
+        iScaledMasksInverted.Append(maski);
+    }
+    else
+    {
+        // In the case of no memory or whatever
+        ASSERT(EFalse);
+        bmp = &GetBitmap();
+    }
+
+    return *bmp;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::Dispose
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::Dispose()
+{
+    // Likely reasons for this assertion to fail:
+    //  - The SWT program disposing of its images before the objects that
+    //    reference them;
+    //  - Memory leak in one of the objects referencing the image ( AddRef() was
+    //    called but not RemoveRef() ).
+#ifdef ESWT_EARLY_DISPOSAL_CHECKING_ENABLED
+    ASSERT(RefCount() == 1);
+#endif // ESWT_EARLY_DISPOSAL_CHECKING_ENABLED
+    RemoveRef();
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::MaskBitmap
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+const CFbsBitmap* CSwtImage::MaskBitmap(TBool aInvertedIfMonochrome /*= EFalse*/) const
+{
+    EnsureMaskIsUpToDate();
+    CFbsBitmap* mask = iMask;
+    if (mask && aInvertedIfMonochrome && mask->IsMonochrome())
+    {
+        if (!iMaskInverted)
+        {
+            TRAP_IGNORE(iMaskInverted = SwtControlHelper::GetInvertedCopyOfMonoBitmapL(mask));
+        }
+        mask = iMaskInverted;
+    }
+    return mask;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::SubMaskBitmap
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+const CFbsBitmap* CSwtImage::SubMaskBitmap(const TSize& aSize,
+        TBool aInvertedIfMonochrome /*= EFalse*/) const
+{
+    ASSERT(iBitmap);
+
+    // For the original size return the main mask
+    if (iBitmap->SizeInPixels() == aSize)
+    {
+        return MaskBitmap(aInvertedIfMonochrome);
+    }
+
+    // Find scaled copy of the bitmap and return its scaled mask.
+    CFbsBitmap* bmp = NULL;
+    CFbsBitmap* mask = NULL;
+    TInt count = iScaledBitmaps.Count();
+    for (TInt i = 0; i < count; i++)
+    {
+        bmp = iScaledBitmaps[i];
+        if (bmp && bmp->SizeInPixels() == aSize)
+        {
+            mask = iScaledMasks[i];
+            if (mask && aInvertedIfMonochrome && mask->IsMonochrome())
+            {
+                // NOTE! iScaledMasksInverted entries are valid only if
+                // the main mask is monochrome. Otherwise they are NULL
+                // and iScaledMasks entries should be used instead.
+                mask = iScaledMasksInverted[i];
+            }
+            return mask;
+        }
+    }
+
+    return mask;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetBounds
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+TRect CSwtImage::GetBounds() const
+{
+    return TRect(iBitmap->SizeInPixels());
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::GetImageDataL
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+MSwtImageData* CSwtImage::GetImageDataL() const
+{
+    // Get the palette
+    CSwtGrPaletteData* paletteData = GetPaletteDataL();
+    CleanupStack::PushL(paletteData);
+
+    // Get the buffers
+    HBufC8* pixelData = GetPixelDataLC(*iBitmap);
+    HBufC8* maskData = NULL;
+    if (iMaskType == EBinaryMask)
+    {
+        ASSERT(iMask);
+        maskData = GetPixelDataLC(*iMask);
+    }
+
+    HBufC8* alphaData = NULL;
+    if (iMaskType == EAlphaMask)
+    {
+        ASSERT(iMask);
+        alphaData = GetPixelDataLC(*iMask);
+    }
+
+    // Prepare the information
+    MSwtImageData::TInfo info;
+    info.iSize = iInfo.iSize;
+    info.iDepth = BitDepth(iBitmap->DisplayMode());
+    info.iScanlinePad = ScanlinePadding(info.iDepth);
+    info.iBytesPerLine = BytesPerLine(info.iSize.iWidth, info.iDepth,
+                                      info.iScanlinePad);
+    info.iMaskPad = (maskData) ? ScanlinePadding(1) : 0;
+    info.iAlpha = iInfo.iAlpha;
+    info.iType = iInfo.iType;
+    info.iTopLeft = iInfo.iTopLeft;
+    info.iDisposalMethod = iInfo.iDisposalMethod;
+    info.iDelayTime = iInfo.iDelayTime;
+
+    if (!iColorKey)
+    {
+        info.iTransparentPixel = -1;
+    }
+    else
+    {
+        if (paletteData->IsDirect())
+        {
+            const MSwtPaletteData::TDirectData& directData =
+                paletteData->DirectData();
+            TUint r = BitShift(iColorKey->Red(),
+                               - directData.iRedShift) & directData.iRedMask;
+            TUint g = BitShift(iColorKey->Green(),
+                               - directData.iGreenShift) & directData.iGreenMask;
+            TUint b = BitShift(iColorKey->Blue(),
+                               - directData.iBlueShift) & directData.iBlueMask;
+            info.iTransparentPixel = r | g | b;
+        }
+        else
+        {
+            info.iTransparentPixel = paletteData->IndirectData()->
+                                     NearestIndex(*iColorKey);
+        }
+    }
+
+    if (alphaData)
+    {
+        CleanupStack::Pop(alphaData);
+    }
+    if (maskData)
+    {
+        CleanupStack::Pop(maskData);
+    }
+    CleanupStack::Pop(pixelData);
+    CleanupStack::Pop(paletteData);
+
+    return CSwtGrImageData::NewL(info, paletteData, pixelData, maskData, alphaData);
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::AddSubRef
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::AddSubRef(const TSize& aSize) const
+{
+    ASSERT(iBitmap);
+    if (iBitmap->SizeInPixels() == aSize)
+    {
+        AddRef();
+        return KErrNone;
+    }
+
+    CFbsBitmap* bmp = NULL;
+    TInt count = iScaledBitmaps.Count();
+    for (TInt i = 0; i < count; i++)
+    {
+        bmp = iScaledBitmaps[i];
+        if (bmp && bmp->SizeInPixels() == aSize)
+        {
+            iScaledBitmapRefs[i]++; // mutable
+            return KErrNone;
+        }
+    }
+    return KErrNotFound;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::RemoveSubRef
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::RemoveSubRef(const TSize& aSize) const
+{
+    ASSERT(iBitmap);
+    if (iBitmap->SizeInPixels() == aSize)
+    {
+        RemoveRef();
+        return KErrNone;
+    }
+
+    CFbsBitmap* bmp = NULL;
+    CFbsBitmap* mask = NULL;
+    CFbsBitmap* maski = NULL;
+    TInt count = iScaledBitmaps.Count();
+    for (TInt i = 0; i < count; i++)
+    {
+        // NOTE! iScaledBitmapRefs, iScaledBitmaps, iScaledMasks and
+        // iScaledMasksInverted must always have the same number of entries.
+        // NOTE! iScaledMasksInverted entries are valid only if
+        // the main mask is monochrome. Otherwise they are NULL
+        // and iScaledMasks entries should be used instead.
+        bmp = iScaledBitmaps[i];
+        mask = iScaledMasks[i];
+        maski = iScaledMasksInverted[i];
+        if (bmp && bmp->SizeInPixels() == aSize)
+        {
+            iScaledBitmapRefs[i]--; // mutable
+            if (iScaledBitmapRefs[i] == 0)
+            {
+                delete bmp;
+                delete mask;
+                delete maski;
+                iScaledMasks.Remove(i);
+                iScaledMasksInverted.Remove(i);
+                iScaledBitmaps.Remove(i);
+                iScaledBitmapRefs.Remove(i);
+            }
+            return KErrNone;
+        }
+    }
+    return KErrNotFound;
+}
+
+// ---------------------------------------------------------------------------
+// CSwtImage::SubRefCount
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+TInt CSwtImage::SubRefCount(const TSize& aSize) const
+{
+    ASSERT(iBitmap);
+    if (iBitmap->SizeInPixels() == aSize)
+    {
+        return RefCount();
+    }
+
+    CFbsBitmap* bmp = NULL;
+    TInt count = iScaledBitmaps.Count();
+    for (TInt i = 0; i < count; i++)
+    {
+        bmp = iScaledBitmaps[i];
+        if (bmp && bmp->SizeInPixels() == aSize)
+        {
+            return iScaledBitmapRefs[i];
+        }
+    }
+    return 0;
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::BitmapWithAlphaLC
+// From MSwtImage
+// ---------------------------------------------------------------------------
+//
+CFbsBitmap* CSwtImage::BitmapWithAlphaLC()
+{
+
+    ASSERT(iMask);
+    ASSERT(iBitmap);
+
+
+    // Create the bitmap
+    CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
+    CleanupStack::PushL(bitmap);
+#ifdef RD_JAVA_S60_RELEASE_9_2
+    User::LeaveIfError(bitmap->Create(iBitmap->SizeInPixels(), EColor16MAP));
+#else
+    User::LeaveIfError(bitmap->Create(iBitmap->SizeInPixels(), EColor16MA));
+#endif //RD_JAVA_S60_RELEASE_9_2
+
+
+    // Create bitmap mask
+    CFbsBitmap* mask = new(ELeave) CFbsBitmap;
+    CleanupStack::PushL(mask);
+    User::LeaveIfError(mask->Create(iMask->SizeInPixels(), EGray256));
+
+    // copy bitmap
+    CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap);
+    CleanupStack::PushL(bitmapDevice);
+    BitBltBitmapL(*bitmapDevice, *iBitmap);
+    CleanupStack::PopAndDestroy(bitmapDevice);
+
+    // copy bitmap mask
+    CFbsBitmapDevice* maskDevice = CFbsBitmapDevice::NewL(mask);
+    CleanupStack::PushL(maskDevice);
+    BitBltBitmapL(*maskDevice, *iMask);
+    CleanupStack::PopAndDestroy(maskDevice);
+
+    // add mask to alpha bitmap's alpha channel
+    AddMaskToAlphaChannel(*bitmap, *mask);
+    CleanupStack::PopAndDestroy(mask);
+    return bitmap;
+}
+
+
+// ---------------------------------------------------------------------------
+// CSwtImage::OfferResourceChangeL
+// From MSwtResourceChangeObserver
+// ---------------------------------------------------------------------------
+//
+void CSwtImage::OfferResourceChangeL(TInt /*aType*/)
+{
+    ASSERT(iDevice);
+
+    // We set new twips size of bitmap in case device resolution has changed
+    iBitmap->SetSizeInTwips(&(iDevice->GraphicsDevice()));
+}