diff -r ae942d28ec0e -r 2455ef1f5bbc javauis/lcdui_akn/lcdgr/src/LcdFbsImage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/lcdgr/src/LcdFbsImage.cpp Wed Sep 01 12:33:18 2010 +0100 @@ -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 +#include +#include +#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