--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdgr/src/LcdFbsImage.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,480 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+#include <bitdev.h>
+#include <bitstd.h>
+#include <lcdgdrv.h>
+#include "LcdFbsImage.h"
+
+#ifdef LCDGR_ACCELERATED_BITGDI
+const TUid KJvmExeUid = { 0x102033E6 };
+#endif
+
+/**
+ * Copy bitmap data from (aColorBitmap,aAlphaBitmap) to aFbsImage.
+ */
+extern void CopyBitmapsL
+(
+ CLcdGraphicsDriver& /* aDriver */, // not used yet
+ CLcdFbsImage& aFbsImage,
+ CFbsBitmap* aColorBitmap,
+ CFbsBitmap* aAlphaBitmap,
+ TBool aInvertMask
+);
+
+/**
+ * Create a CFbsBitmap of size aSize in displaymode aMode
+ */
+LOCAL_C CFbsBitmap* CreateBitmapL(const TSize& aSize, TDisplayMode aMode);
+
+/**
+ * Set alpha channel in EColor16MA mode aBitmap from aAlphaBitmap. If aAlphaBitmap is
+ * in a mode other than EGray256 this procedure will create a temporary bitmap in
+ * EGray256 mode and copy pixels from aAlphaBitmap into that first. It is expected
+ * that aAlphaBitmap would be a binary mask.
+ */
+LOCAL_C void SetAlphaChannelL(CFbsBitmap* aBitmap, CFbsBitmap* aAlphaBitmap, TBool aInvert);
+
+/**
+ * Set the alpha channel in an EColor16MA mode aBitmap from an EGray256 mode
+ * aGray256Bitmap.
+ */
+LOCAL_C void SetAlphaChannel(CFbsBitmap* aBitmap, CFbsBitmap* aGray256Bitmap, TBool aInvert);
+
+/**
+ * Copy alpha information from EColor16MA bitmap aSource, into EGray2 or EGray256
+ * bitmap aTarget.
+ */
+LOCAL_C void GetAlphaChannelL(CFbsBitmap* aTarget, CFbsBitmap* aSource, TBool aInvert);
+
+/**
+ * Copy alpha channel from EColor16MA bitmap into an EGray256 bitmap
+ */
+LOCAL_C void GetAlphaChannel(CFbsBitmap* aTargetGray256, CFbsBitmap* aSourceColor16MA, TBool aInvert);
+
+#ifdef _DEBUG
+//
+// debug only - check that EColor16MA aBitmap is fully opaque
+//
+LOCAL_C TBool CheckOpaque(CFbsBitmap* aBitmap);
+#endif
+
+
+/*************************************************************
+ *
+ * CLcdFbsImage potentially public bitmapped image class.
+ *
+ ************************************************************/
+
+CLcdFbsImage* CLcdFbsImage::NewL(const TSize& aSize, TDisplayMode aColorMode, TDisplayMode aAlphaMode)
+{
+ CLcdFbsImage* image = new(ELeave) CLcdFbsImage;
+ CleanupStack::PushL(image);
+ image->iColorBitmap = CreateBitmapL(aSize, aColorMode);
+ if (aAlphaMode)
+ {
+ image->iAlphaBitmap = CreateBitmapL(aSize, aAlphaMode);
+ }
+ CleanupStack::Pop(image);
+ return image;
+}
+
+CLcdFbsImage* CLcdFbsImage::NewL(CFbsBitmap* aColorBitmap, CFbsBitmap* aAlphaBitmap)
+{
+ CLcdFbsImage* image = new(ELeave) CLcdFbsImage;
+
+ CleanupStack::PushL(image);
+ image->iColorBitmap = DuplicateBitmapL(aColorBitmap);
+ if (aAlphaBitmap)
+ {
+ image->iAlphaBitmap = DuplicateBitmapL(aAlphaBitmap);
+ }
+ CleanupStack::Pop(image);
+
+ return image;
+}
+
+CLcdFbsImage::~CLcdFbsImage()
+{
+ ASSERT(0 == iRefCount);
+ delete iAlphaBitmap;
+ delete iColorBitmap;
+}
+
+TSize CLcdFbsImage::Size() const
+{
+ return iColorBitmap->SizeInPixels();
+}
+
+void CLcdFbsImage::AddRef()
+{
+ ++iRefCount;
+}
+
+void CLcdFbsImage::RemoveRef()
+{
+ --iRefCount;
+ if (iRefCount == 0)
+ {
+ delete this;
+ }
+}
+
+/**
+ *@return the color bitmap
+ */
+CFbsBitmap* CLcdFbsImage::ColorBitmap() const
+{
+ return iColorBitmap;
+}
+
+/**
+ *@return the alpha bitmap if any
+ */
+CFbsBitmap* CLcdFbsImage::AlphaBitmap() const
+{
+ return iAlphaBitmap;
+}
+
+void CLcdFbsImage::CreateAlphaBitmapL()
+{
+ if (iAlphaBitmap)
+ {
+ User::Leave(KErrAlreadyExists);
+ }
+
+ iAlphaBitmap = CreateBitmapL(Size(), EGray256);
+}
+
+/**
+ * Create a bitmap of size aSize in display mode aMode.
+ */
+LOCAL_C CFbsBitmap* CreateBitmapL(const TSize& aSize, TDisplayMode aMode)
+{
+ TInt err = KErrNotSupported;
+
+ CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
+ CleanupStack::PushL(bitmap);
+
+#ifdef LCDGR_ACCELERATED_BITGDI
+ //
+ // Attempt to create hardware bitmap which can be used with a
+ // hardware graphics accelerator. Very few if any devices
+ // appear to support RHardwareBitmap so this is very unlikely
+ // to be used.
+ //
+ err = bitmap->CreateHardwareBitmap(aSize, aMode, KJvmExeUid);
+#endif
+
+ if (err != KErrNone)
+ {
+ //
+ // Fallback to software only bitmap if hardware unavailable/not supported.
+ //
+ err = bitmap->Create(aSize, aMode);
+ }
+
+ User::LeaveIfError(err);
+
+ CleanupStack::Pop(bitmap);
+
+ return bitmap;
+}
+
+/**
+ * Create a new bitmap in a given mode and copy the data.
+ * Slowish closest match copy. We could use lcd graphics driver for some
+ * of these copies but is good enough for now.
+ */
+CFbsBitmap* CLcdFbsImage::CopyBitmapL(CFbsBitmap* aBitmap, TDisplayMode aMode, TBool aInvert)
+{
+ CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
+ CleanupStack::PushL(bitmap);
+ User::LeaveIfError(bitmap->Create(aBitmap->SizeInPixels(), aMode));
+ CopyBitmapL(bitmap, aBitmap, aInvert);
+ CleanupStack::Pop(bitmap);
+ return bitmap;
+}
+
+/**
+ * Copy bitmap content from aSource to aTarget optionally inverting.
+ */
+void CLcdFbsImage::CopyBitmapL(CFbsBitmap* aTarget, CFbsBitmap* aSource, TBool aInvert)
+{
+ CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(aTarget);
+ CleanupStack::PushL(device);
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(device->CreateContext(gc));
+
+ // Don't alpha blend (Either copy the alpha component or write opaque pixels)
+ TInt drawMode = CGraphicsContext::EDrawModeWriteAlpha;
+ if (aInvert)
+ {
+ // Invert pixel values - only really makes sense for binary masks
+ // For EColor16MA images the alpha component is not inverted
+ drawMode |= CGraphicsContext::EInvertPen;
+ }
+
+ gc->SetDrawMode(CGraphicsContext::TDrawMode(drawMode));
+ gc->BitBlt(TPoint(), aSource);
+ delete gc;
+ CleanupStack::PopAndDestroy(device);
+}
+
+/**
+ * Dup the handle. This requires an FBSERV ipc.
+ */
+CFbsBitmap* CLcdFbsImage::DuplicateBitmapL(CFbsBitmap* aBitmap)
+{
+ CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
+ CleanupStack::PushL(bitmap);
+ User::LeaveIfError(bitmap->Duplicate(aBitmap->Handle()));
+ CleanupStack::Pop(bitmap);
+ return bitmap;
+}
+
+/**
+ * Copy bitmap data from (aColorBitmap,aAlphaBitmap) to aFbsImage.
+ */
+extern void CopyBitmapsL
+(
+ CLcdGraphicsDriver& /* aDriver */, // not used yet
+ CLcdFbsImage& aFbsImage,
+ CFbsBitmap* aColorBitmap,
+ CFbsBitmap* aAlphaBitmap,
+ TBool aInvertMask
+)
+{
+ //
+ // First copy the the pixel color data.
+ //
+ CLcdFbsImage::CopyBitmapL(aFbsImage.ColorBitmap(), aColorBitmap, EFalse);
+
+ //
+ // If target colour bitmap contains alpha channel, copy any alpha data
+ // into it.
+ //
+ if (aFbsImage.ColorBitmap()->DisplayMode() == EColor16MA)
+ {
+ ASSERT(NULL == aFbsImage.AlphaBitmap());
+ if (aAlphaBitmap)
+ {
+ SetAlphaChannelL(aFbsImage.ColorBitmap(), aAlphaBitmap, aInvertMask);
+ }
+#ifdef _DEBUG
+ else
+ {
+ ASSERT(CheckOpaque(aFbsImage.ColorBitmap()));
+ }
+#endif
+ }
+ else if (aFbsImage.AlphaBitmap())
+ {
+ if (aAlphaBitmap)
+ {
+ CLcdFbsImage::CopyBitmapL(aFbsImage.AlphaBitmap(), aAlphaBitmap, EFalse);
+ }
+ else if (aColorBitmap->DisplayMode() == EColor16MA)
+ {
+ GetAlphaChannelL(aFbsImage.AlphaBitmap(), aColorBitmap, aInvertMask);
+ }
+ }
+}
+
+
+//
+// Set the alpha channel in a bitmap in a mode that contains alpha
+// information from an alpha bitmap.
+//
+// Not the cheapest, but this is hopefully an edge case.
+//
+// EColor16M,Gray256 is the most likely format, so a dedicated blitter
+// could help.
+//
+LOCAL_C void SetAlphaChannelL(CFbsBitmap* aBitmap, CFbsBitmap* aAlphaBitmap, TBool aInvert)
+{
+ ASSERT(aBitmap->DisplayMode() == EColor16MA);
+ if (aAlphaBitmap->DisplayMode() != EGray256)
+ {
+ CFbsBitmap* alpha = CLcdFbsImage::CopyBitmapL(aAlphaBitmap, EGray256, EFalse);
+ SetAlphaChannel(aBitmap, alpha, aInvert);
+ delete alpha;
+ }
+ else
+ {
+ SetAlphaChannel(aBitmap, aAlphaBitmap, aInvert);
+ }
+}
+
+//
+// Set the alpha channel in an EColor16MA bitmap from an EGray256
+// bitmap.
+//
+LOCAL_C void SetAlphaChannel(CFbsBitmap* aBitmap, CFbsBitmap* aGray256Bitmap, TBool aInvert)
+{
+ ASSERT(aBitmap->DisplayMode() == EColor16MA);
+ ASSERT(aGray256Bitmap->DisplayMode() == EGray256);
+
+ TAcceleratedBitmapSpec targetSpec(aBitmap);
+ TAcceleratedBitmapInfo target;
+ TAcceleratedBitmapSpec sourceSpec(aGray256Bitmap);
+ TAcceleratedBitmapInfo source;
+ TBitmapLockCount count;
+
+ targetSpec.Lock(count);
+ sourceSpec.Lock(count);
+
+ targetSpec.GetInfo(target);
+ sourceSpec.GetInfo(source);
+
+ ASSERT(target.iSize == source.iSize);
+
+ TUint8* tgtAddress = target.iAddress;
+ TInt tgtLinePitch = target.iLinePitch;
+ TUint8* srcAddress = source.iAddress;
+ TInt srcLinePitch = source.iLinePitch;
+
+ TUint32 mask = aInvert ? 0xff:0x00;
+ for (TInt h=target.iSize.iHeight; --h>=0;)
+ {
+ TUint8* src = srcAddress;
+ TUint32* tgt = (TUint32*)tgtAddress;
+ TUint32* end = tgt + target.iSize.iWidth;
+ while (tgt < end)
+ {
+ TUint32 alpha = (*src) ^ mask;
+ TUint32 pixel = *tgt;
+ pixel &= 0x00ffffff;
+ pixel |= (alpha << 24);
+ *tgt = pixel;
+ ++src;
+ ++tgt;
+ }
+ tgtAddress += tgtLinePitch;
+ srcAddress += srcLinePitch;
+ }
+
+ sourceSpec.Unlock(count);
+ targetSpec.Unlock(count);
+}
+
+
+//
+// Copy alpha information from EColor16MA bitmap aSource, into EGray2 or EGray256
+// bitmap aTarget.
+//
+LOCAL_C void GetAlphaChannelL(CFbsBitmap* aTarget, CFbsBitmap* aSource, TBool aInvert)
+{
+ ASSERT(aTarget->DisplayMode() == EGray2 || aTarget->DisplayMode() == EGray256);
+ if (aTarget->DisplayMode() == EGray2)
+ {
+ TSize size = aSource->SizeInPixels();
+ CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
+ CleanupStack::PushL(bitmap);
+ User::LeaveIfError(bitmap->Create(size, EGray256));
+ GetAlphaChannel(bitmap, aSource, aInvert);
+ CFbsBitmapDevice* device = CFbsBitmapDevice::NewL(aTarget);
+ CleanupStack::PushL(device);
+ CFbsBitGc* context = NULL;
+ User::LeaveIfError(device->CreateContext(context));
+ context->BitBlt(TPoint(), bitmap);
+ delete context;
+ CleanupStack::PopAndDestroy(device);
+ CleanupStack::PopAndDestroy(bitmap);
+ }
+ else
+ {
+ GetAlphaChannel(aTarget, aSource, aInvert);
+ }
+}
+
+//
+// Copy alpha channel from EColor16MA bitmap into an EGray256 bitmap
+//
+LOCAL_C void GetAlphaChannel(CFbsBitmap* aTargetGray256, CFbsBitmap* aSourceColor16MA, TBool aInvert)
+{
+ ASSERT(aTargetGray256->DisplayMode() == EGray256);
+ ASSERT(aSourceColor16MA->DisplayMode() == EColor16MA);
+
+ TAcceleratedBitmapSpec targetSpec(aTargetGray256);
+ TAcceleratedBitmapInfo target;
+ TAcceleratedBitmapSpec sourceSpec(aSourceColor16MA);
+ TAcceleratedBitmapInfo source;
+ TBitmapLockCount count;
+
+ targetSpec.Lock(count);
+ sourceSpec.Lock(count);
+
+ targetSpec.GetInfo(target);
+ sourceSpec.GetInfo(source);
+
+ ASSERT(target.iSize == source.iSize);
+
+ TUint8* tgtAddress = target.iAddress;
+ TInt tgtLinePitch = target.iLinePitch;
+ TUint8* srcAddress = source.iAddress;
+ TInt srcLinePitch = source.iLinePitch;
+
+ TUint32 mask = aInvert ? 0xff:0x00;
+ for (TInt h=target.iSize.iHeight; --h>=0;)
+ {
+ TUint32* src = (TUint32*)srcAddress;
+ TUint8* tgt = (TUint8*)tgtAddress;
+ TUint8* end = tgt + target.iSize.iWidth;
+ while (tgt < end)
+ {
+ *tgt++ = (TUint8)(((*src++)>>24)^mask);
+ }
+ tgtAddress += tgtLinePitch;
+ srcAddress += srcLinePitch;
+ }
+
+ sourceSpec.Unlock(count);
+ targetSpec.Unlock(count);
+}
+
+#ifdef _DEBUG
+LOCAL_C TBool CheckOpaque(CFbsBitmap* aBitmap)
+{
+ ASSERT(aBitmap->DisplayMode() == EColor16MA);
+ TAcceleratedBitmapSpec spec(aBitmap);
+ TAcceleratedBitmapInfo info;
+ TBitmapLockCount count;
+
+ spec.Lock(count);
+ spec.GetInfo(info);
+
+ TUint8* address = info.iAddress;
+ TInt linePitch = info.iLinePitch;
+ TUint32 accum = 0xff000000;
+
+ for (TInt h=info.iSize.iHeight; --h>=0;)
+ {
+ TUint32* src = (TUint32*)address;
+ TUint32* end = src + info.iSize.iWidth;
+ while (src < end)
+ {
+ accum &= *src++;
+ }
+ address += linePitch;
+ }
+
+ spec.Unlock(count);
+
+ return (accum == 0xff000000);
+}
+#endif