--- /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()));
+}