--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uigraphics/AknIcon/srvsrc/AknIconSrvUtils.cpp Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,641 @@
+/*
+* Copyright (c) 2002 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: Implementation of class AknIconSrvUtils.
+*
+*/
+
+
+
+// INCLUDE FILES
+
+#include <fbs.h>
+#include <gdi.h>
+#include <bitdev.h>
+#include <mifconvdefs.h>
+
+#include "AknIconSrvUtils.h"
+#include "AknIconFormatHandler.h"
+#include "AknIconLoader.h"
+#include "AknIconSrv.h"
+#include "AknIconFormatHandlerFactory.h"
+#include "AknIconSrvDef.h"
+
+#include "AknBitmap.h"
+// CONSTANTS
+
+// ================= MEMBER FUNCTIONS ==========================================
+
+TPtrC8 AknIconSrvUtils::InitIconDataAndHandlerLC(
+ CAknIconLoader* aLoader,
+ RPointerArray<MAknIconFormatHandler>& aHandlerList,
+ MAknIconFormatHandler*& aHandler,
+ const TAknIconParams& aParams,
+ TBool aAnimated )
+ {
+ CleanupStack::PushL( TCleanupItem( CleanupFreeIcon, aLoader ) );
+
+ if ( aLoader->IconAnimatedL( aParams.iBitmapId ) && !aAnimated )
+ {
+ User::Leave( KAknIconSrvCodeAnimated );
+ }
+
+ TInt type = aLoader->IconTypeL( aParams.iBitmapId );
+
+#ifdef _NGATESTING
+ type = aLoader->GetDerivedIconTypeL(type, aParams.iFileName);
+#endif
+
+ // Check if handler is already present, if so then return with same pointer
+ for ( TInt lIndex = 0; lIndex < aHandlerList.Count(); lIndex++ )
+ {
+ if ( aHandlerList[ lIndex ]->IconFormatType() == type )
+ {
+ aHandler = aHandlerList[ lIndex ];
+ break;
+ }
+ }
+
+ // No Handler found, create one and add to list
+ if ( !aHandler )
+ {
+ aHandler = AknIconFormatHandlerFactory::NewIconFormatHandlerL( type );
+ aHandlerList.Append( aHandler );
+ aHandler->SetAnimated( aAnimated );
+ }
+
+ return aLoader->IconL( aParams.iBitmapId );
+ }
+
+TPtrC8 AknIconSrvUtils::InitIconDataAndHandlerLC(
+ CAknIconLoader* aLoader,
+ MAknIconFormatHandler*& aHandler,
+ TInt aIconId,
+ TBool aAnimated )
+ {
+ CleanupStack::PushL( TCleanupItem( CleanupFreeIcon, aLoader ) );
+
+ if ( aLoader->IconAnimatedL( aIconId ) && !aAnimated )
+ {
+ User::Leave( KAknIconSrvCodeAnimated );
+ }
+
+ TInt type = aLoader->IconTypeL( aIconId );
+
+ if ( !aHandler )
+ {
+ aHandler = AknIconFormatHandlerFactory::NewIconFormatHandlerL( type );
+ aHandler->SetAnimated( aAnimated );
+ }
+
+ return aLoader->IconL( aIconId );
+ }
+
+// -----------------------------------------------------------------------------
+// AknIconSrvUtils::RenderPreparedIconL
+// -----------------------------------------------------------------------------
+//
+TAknContentDimensions AknIconSrvUtils::RenderPreparedIconL(
+ MAknIconFormatHandler& aHandler,
+ CFbsBitmap* aBitmap,
+ CFbsBitmap* aMask, // may be NULL
+ TDisplayMode aBitmapDepth,
+ TDisplayMode aPreferredDepth,
+ const TSize& aSize,
+ TScaleMode aMode,
+ TInt aRotationAngle,
+ TRgb aColor,
+ TInt /*aBitmapId*/,
+ TInt /*aMaskId*/,
+ TBool isAppIcon)
+ {
+ TSize resultSize( aSize );
+ CAknBitmap* aknIcon = CAknBitmap::DynamicCast(aBitmap);
+
+ TAknContentDimensions dimensions;
+ TBool dimensionsRetrieved = EFalse;
+
+ if ( aMode == EAspectRatioPreservedAndUnusedSpaceRemoved )
+ {
+ if ( !resultSize.iWidth || !resultSize.iHeight )
+ {
+ resultSize.iWidth = 0;
+ resultSize.iHeight = 0;
+ }
+ else
+ {
+ aHandler.GetContentDimensionsL( dimensions );
+ dimensionsRetrieved = ETrue;
+ GetAspectRatioPreservedSize( dimensions, resultSize );
+ }
+ }
+
+ TDisplayMode definedDepth = aBitmapDepth;
+ // Change display mode to the closest one supported by the engine.
+ aHandler.SupportedDisplayMode( aBitmapDepth, aPreferredDepth );
+
+ CFbsBitmap* renderBitmap = aBitmap;
+
+ // If EGray256 mode was defined, and the engine did not support it,
+ // render the icon first in a temporary bitmap.
+
+ if ( definedDepth == EGray256 && definedDepth != aBitmapDepth )
+ {
+ renderBitmap = new( ELeave ) CFbsBitmap;
+ CleanupStack::PushL( renderBitmap );
+ }
+
+ User::LeaveIfError( renderBitmap->Create( resultSize, aBitmapDepth ) );
+ if ( aMask )
+ {
+ // Always use soft masks with SVGs.
+ User::LeaveIfError( aMask->Create( resultSize, EGray256 ) );
+ }
+
+ aHandler.SetScaleMode( aMode );
+ aHandler.SetRotation( aRotationAngle );
+ aknIcon = CAknBitmap::DynamicCast(aBitmap);
+ aHandler.RenderPreparedIconL(renderBitmap, aMask ,resultSize, aBitmapDepth, EGray256,aColor, isAppIcon);
+
+ // Copy from temp. render bitmap to real bitmap,
+ // and convert display depth to EGray256.
+ if ( renderBitmap != aBitmap )
+ {
+ User::LeaveIfError( aBitmap->Create( resultSize, EGray256 ) );
+
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( aBitmap );
+ CleanupStack::PushL( dev );
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError( dev->CreateContext( gc ) );
+ CleanupStack::PushL( gc );
+
+ gc->BitBlt( TPoint( 0, 0 ), renderBitmap );
+
+ CleanupStack::PopAndDestroy( 3 ); // renderBitmap, dev, gc
+ }
+
+ if ( !dimensionsRetrieved )
+ {
+ aHandler.GetContentDimensionsL( dimensions );
+ }
+
+ return dimensions;
+ }
+
+// -----------------------------------------------------------------------------
+// AknIconSrvUtils::GetAspectRatioPreservedSize
+// -----------------------------------------------------------------------------
+//
+void AknIconSrvUtils::GetAspectRatioPreservedSize(
+ const TAknContentDimensions& aDimensions,
+ TSize& aSize )
+ {
+ if ( !aDimensions.iWidth || !aDimensions.iHeight )
+ {
+ aSize.iWidth = 0;
+ aSize.iHeight = 0;
+ }
+ else
+ {
+ if ( aSize.iWidth > KMaxTInt16 )
+ {
+ aSize.iWidth = KMaxTInt16;
+ }
+ if ( aSize.iHeight > KMaxTInt16 )
+ {
+ aSize.iHeight = KMaxTInt16;
+ }
+
+ TReal32 xScaleFactor = (TReal32)(aSize.iWidth) / aDimensions.iWidth;
+ TReal32 yScaleFactor = (TReal32)(aSize.iHeight) / aDimensions.iHeight;
+
+ if ( xScaleFactor > yScaleFactor )
+ {
+ TReal32 width = aDimensions.iWidth * yScaleFactor;
+ aSize.iWidth = width;
+ if ( width - aSize.iWidth > 0 ) //rounding
+ {
+ aSize.iWidth++;
+ }
+ }
+ else
+ {
+ TReal32 height = aDimensions.iHeight * xScaleFactor;
+ aSize.iHeight = height;
+ if ( height - aSize.iHeight > 0 ) //rounding
+ {
+ aSize.iHeight++;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// AknIconSrvUtils::GetAspectRatioPreservedSize
+// -----------------------------------------------------------------------------
+//
+void AknIconSrvUtils::GetAspectRatioPreservedSize(
+ const TSize& aDimensions,
+ TSize& aSize,
+ TBool aFitToOriginalSize )
+ {
+ if ( !aDimensions.iWidth || !aDimensions.iHeight )
+ {
+ aSize.iWidth = 0;
+ aSize.iHeight = 0;
+ }
+ else
+ {
+ if ( aSize.iWidth > KMaxTInt16 )
+ {
+ aSize.iWidth = KMaxTInt16;
+ }
+ if ( aSize.iHeight > KMaxTInt16 )
+ {
+ aSize.iHeight = KMaxTInt16;
+ }
+
+ TInt xScaleFactor = (aSize.iWidth << 16) / aDimensions.iWidth;
+ TInt yScaleFactor = (aSize.iHeight << 16) / aDimensions.iHeight;
+
+
+ TBool chooseWidthScaling = (xScaleFactor > yScaleFactor);
+
+ if (!aFitToOriginalSize)
+ {
+ chooseWidthScaling = !chooseWidthScaling;
+ }
+
+ if ( chooseWidthScaling )
+ {
+ aSize.iWidth = aDimensions.iWidth * yScaleFactor;
+ TBool rounding = aSize.iWidth & 0x8000;
+
+ aSize.iWidth >>= 16;
+ if ( rounding )
+ {
+ aSize.iWidth++;
+ }
+ }
+ else
+ {
+ aSize.iHeight = aDimensions.iHeight * xScaleFactor;
+ TBool rounding = aSize.iHeight & 0x8000;
+
+ aSize.iHeight >>= 16;
+ if ( rounding )
+ {
+ aSize.iHeight++;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// AknIconSrvUtils::ScaleBitmapIconL
+// -----------------------------------------------------------------------------
+//
+TBool AknIconSrvUtils::ScaleBitmapIconL(
+ const TSize& aSize,
+ const TScaleMode aMode,
+ const TInt aAngle,
+ const TRgb aColor,
+ CFbsBitmap* aSourceBitmap,
+ CFbsBitmap* aSourceMask,
+ CFbsBitmap* aTargetBitmap,
+ CFbsBitmap* aTargetMask )
+ {
+ TSize scaledSize( aSize );
+ TSize originalSize(aSourceBitmap->SizeInPixels());
+ TBool colorIcon = aColor != KColorNotDefined;
+
+ // Find out the scaled size according to the given scale mode.
+ // Note:In scaling mode EAspectRatioPreservedSlice no need to calculate scaledSize for color icons.
+ if ( aMode != EAspectRatioNotPreserved && (aMode != EAspectRatioPreservedSlice || !colorIcon))
+ {
+ AknIconSrvUtils::GetAspectRatioPreservedSize( originalSize, scaledSize, aMode != EAspectRatioPreservedSlice );
+ }
+
+ const TSize& bitmapSize =
+ aMode == EAspectRatioPreservedAndUnusedSpaceRemoved ?
+ scaledSize : aSize;
+
+ TDisplayMode colorDepth = colorIcon ?
+ EColor64K : aSourceBitmap->DisplayMode();
+
+ User::LeaveIfError( aTargetBitmap->Create( bitmapSize, colorDepth ) );
+
+ // Icon should be centered, so calculate x and y margins.
+ TInt xMargin = ( bitmapSize.iWidth - scaledSize.iWidth ) / 2;
+ TInt yMargin = ( bitmapSize.iHeight - scaledSize.iHeight ) / 2;
+
+ // Target rect inside the target bitmap.
+ TRect targetRect( xMargin, yMargin,
+ xMargin + scaledSize.iWidth, yMargin + scaledSize.iHeight );
+
+ // Decide if fallback should be forced in ScaleBitmapExtL calls
+ TBool forceFallBack = EFalse;
+ if ( !colorIcon && aSourceBitmap && !aAngle )
+ {
+ forceFallBack = AknIconUtils::DoesScaleBitmapUseFallBack( aSourceBitmap );
+ }
+ if ( aSourceMask && aTargetMask && !aAngle )
+ {
+ forceFallBack = forceFallBack || AknIconUtils::DoesScaleBitmapUseFallBack( aSourceMask );
+ }
+
+ // If color icon, just fill the bitmap with the defined color.
+ if ( colorIcon )
+ {
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( aTargetBitmap );
+ CleanupStack::PushL( dev );
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError( dev->CreateContext( gc ) );
+ CleanupStack::PushL( gc );
+
+ gc->SetBrushColor( aColor );
+ gc->SetPenStyle( CGraphicsContext::ENullPen );
+ gc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+ // Fill icon with the given color, mask defines the icon shape.
+ gc->DrawRect( TRect( TPoint( 0, 0 ), bitmapSize ) );
+
+ CleanupStack::PopAndDestroy( 2 ); // dev, gc
+ }
+
+ // Otherwise, perform bitmap scaling and rotation as required.
+ else
+ {
+ if ( !aAngle )
+ {
+ AknIconUtils::ScaleBitmapExtL( targetRect, aTargetBitmap, aSourceBitmap, forceFallBack );
+ }
+ else
+ {
+ AknIconUtils::RotateAndScaleBitmapL(
+ targetRect,
+ aTargetBitmap,
+ aSourceBitmap,
+ aAngle );
+ }
+ }
+
+ // Optional mask is always scaled and rotated as required.
+ if ( aSourceMask && aTargetMask)
+ {
+ User::LeaveIfError(aTargetMask->Create( bitmapSize, aSourceMask->DisplayMode() ) );
+
+
+ // If target mode is EAspectRatioPreserved, there may be unused parts
+ // in the bitmap, so need to initialize soft masks black before scaling.
+ if ( aMode == EAspectRatioPreserved && aTargetMask->DisplayMode() == EGray256 )
+ {
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( aTargetMask );
+ CleanupStack::PushL( dev );
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError( dev->CreateContext( gc ) );
+ CleanupStack::PushL( gc );
+ gc->SetBrushColor( KRgbBlack );
+ gc->SetBrushStyle( CGraphicsContext::ESolidBrush );
+ gc->Clear();
+ CleanupStack::PopAndDestroy(2); // dev, gc
+ }
+
+ if ( !aAngle )
+ {
+ AknIconUtils::ScaleBitmapExtL( targetRect, aTargetMask, aSourceMask, forceFallBack );
+ }
+ else
+ {
+ AknIconUtils::RotateAndScaleBitmapL(
+ targetRect,
+ aTargetMask,
+ aSourceMask,
+ aAngle );
+ }
+ }
+
+ return colorIcon;
+ }
+
+
+LOCAL_C TInt CheckTransparency(const CFbsBitmap* aBmp, TDes8& aBuffer, TInt aMask, TDisplayMode aMode)
+ {
+ // Note: The following calculations use the below notation.
+ //
+ // Ha = Actual height of the bitmap
+ // hTa = Height of the transparent region at the bottom of the bitmap
+ // hNT = Height of the non-transparent region in the bitmap
+ // Therefore, Ha = hNT + 2 * hTa
+ //
+ // hNTN = New height of the non-transparent region after accomodating
+ // for the 12% transparent margins(bottom)
+ // HaN = New needed height of the bitmap to adjust the transparent area
+ // at the bottom to 12%
+ // R = Ratio of hNTN / hNT
+ // C = 2 * hTa
+ // HaN = Ha * R - C * R + C
+ //
+ // This means that if the transparent margins are already 12% then
+ // R becomes 1 in the above equation and it reduces to
+ // HaN = Ha
+ // If R becomes > 1 i.e. hNTN > hNT, then it would be clipped to 1.
+ const TSize& sz = aBmp->SizeInPixels();
+ const TInt lValidMargin = sz.iHeight * 12 / 100;
+
+ const TInt Ha = sz.iHeight;
+ TInt hTa = 0;
+ TInt hNT = 0;
+ TInt C = 0;
+ TInt hNTN = Ha - 2.0 * 0.12 * Ha;
+ TReal R = 1.0;
+ TInt HaN = Ha;
+
+ switch(aMode)
+ {
+ case EGray256: // for mask
+ {
+ const TInt lastColumn = sz.iWidth - 1;
+ const TUint8* ptr8 = reinterpret_cast<const TUint8*> (aBuffer.Ptr());
+ for ( TInt curRow = 0; curRow < lValidMargin; curRow++ )
+ {
+ const TInt y = (sz.iHeight - 1) - curRow; // h - 1 is the last line
+ aBmp->GetScanLine(aBuffer, TPoint(0, y), sz.iWidth, aMode);
+ for ( TInt s = lastColumn; s >= 0; --s )
+ {
+ TUint8 lPixel = aBuffer[s];
+ if ( aBuffer[s] & (TUint8)aMask ) //note that mask is inverted
+ {
+ hTa = curRow;
+ hNT = Ha - 2 * hTa;
+ C = 2 * hTa;
+ R = ( ( (TReal)hNTN / (TReal)hNT ) > 1.0 ) ? 1 : (TReal)hNTN / (TReal)hNT;
+ HaN = Ha * R - C * R + C;
+ // HaN =( 0.88 * Ha) + hTa;
+ return( HaN );
+ }
+ }
+ }
+ }
+
+ break;
+ case EColor16MA:
+ {
+ const TInt lastColumn = aBuffer.MaxLength() / sizeof(TUint32) - 1;
+ const TUint32* ptr = reinterpret_cast<const TUint32*> (aBuffer.Ptr());
+ for ( TInt curRow = 0; curRow < lValidMargin; curRow++ )
+ {
+ const TInt y = (sz.iHeight - 1) - curRow; // h - 1 is the last line
+ aBmp->GetScanLine(aBuffer, TPoint(0, y), sz.iWidth, aMode);
+ for ( TInt s = lastColumn; s >= 0; --s )
+ {
+ if ( ptr[s] & aMask ) //note that mask is inverted
+ {
+ hTa = curRow;
+ hNT = Ha - 2 * hTa;
+ C = 2 * hTa;
+ R = ( ( (TReal)hNTN / (TReal)hNT ) > 1.0 ) ? 1 : (TReal)hNTN / (TReal)hNT;
+ HaN = Ha * R - C * R + C;
+ // HaN =( 0.88 * Ha) + hTa;
+ return( HaN );
+ }
+ }
+ }
+
+ }
+ break;
+ default:
+ break;
+
+ }
+
+ return HaN;
+ }
+
+
+TInt AknIconSrvUtils::CheckMaskTransparencyL(const CFbsBitmap* aBmp)
+ {
+ const TSize& sz = aBmp->SizeInPixels();
+ HBufC8* buffer = HBufC8::NewLC(sz.iWidth);
+ TPtr8 ptr = buffer->Des();
+ const TInt h = CheckTransparency(aBmp, ptr, 0xFF, EGray256);
+ CleanupStack::PopAndDestroy();
+ return h;
+ }
+
+TInt AknIconSrvUtils::CheckAlphaTransparencyL(const CFbsBitmap* aBmp)
+ {
+ const TSize& sz = aBmp->SizeInPixels();
+ HBufC8* buffer = HBufC8::NewLC(sz.iWidth * sizeof(TUint32));
+ TPtr8 ptr = buffer->Des();
+ const TInt h = CheckTransparency(aBmp, ptr, 0xFF000000, EColor16MA);
+ CleanupStack::PopAndDestroy();
+ return h;
+ }
+
+LOCAL_C void ScaleL(const TRect& aRect, CFbsBitmap* aBmp, TUint32 aFillColor, TBool aForceFb)
+ {
+ CFbsBitmap* bmp = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(bmp);
+ User::LeaveIfError(bmp->Create(aRect.Size(), aBmp->DisplayMode()));
+ AknIconUtils::ScaleBitmapExtL(
+ TRect(TPoint(0, 0), aRect.Size()),
+ bmp,
+ aBmp,
+ aForceFb);
+
+
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(aBmp);
+ CleanupStack::PushL(dev);
+ CFbsBitGc* con = NULL;
+ dev->CreateContext(con);
+ CleanupStack::PushL(con);
+ con->SetBrushColor( 0 );
+ con->Clear();
+ con->SetPenStyle(CGraphicsContext::ESolidPen);
+ con->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ con->SetPenColor(aFillColor);
+ con->SetBrushColor(aFillColor);
+ const TSize sz = aBmp->SizeInPixels();
+ con->DrawRect(TRect(TPoint(0, 0), aBmp->SizeInPixels()));
+ con->BitBlt(aRect.iTl, bmp);
+ CleanupStack::PopAndDestroy(3);
+ }
+
+
+
+
+void AknIconSrvUtils::EnsureValidSizeL( CFbsBitmap* aBitmap, CFbsBitmap* aMask )
+ {
+ if ( aBitmap == NULL )
+ return;
+ CFbsBitmap* iBitmap = aBitmap;
+ CFbsBitmap* iMask = NULL;
+ if ( aMask )
+ {
+ iMask = aMask;
+ }
+ TInt validHeight;
+ if(iMask != NULL)
+ {
+ SEpocBitmapHeader lBmpHeaderMask = iMask->Header();
+ if ( lBmpHeaderMask.iBitsPerPixel != 8 )
+ {
+ return;
+ }
+ validHeight = CheckMaskTransparencyL(iMask);
+ }
+ else
+ {
+ SEpocBitmapHeader lBmpHeaderBitmap = iBitmap->Header();
+ if ( lBmpHeaderBitmap.iBitsPerPixel != 32 )
+ {
+ return;
+ }
+ validHeight = CheckAlphaTransparencyL(iBitmap);
+ }
+
+ const TSize& size = iBitmap->SizeInPixels();
+
+ if(validHeight == size.iHeight)
+ return;
+
+ const TInt KOffSet = 16;
+
+ //scale image down, leaving margins on sides
+ //then using fixed point math to get width
+ const TInt hmul = (validHeight << KOffSet) / size.iHeight;
+ const TInt validWidth = (size.iWidth * hmul + (1 << (KOffSet - 1))) >> KOffSet; // sz * mul + 0.5
+ const TSize sz(validWidth, validHeight);
+
+ //centrify it
+ TRect rect(TPoint((size.iWidth - sz.iWidth) >> 1, (size.iHeight - sz.iHeight) >> 1), sz);
+
+ //it look better if even when centrified
+ rect.iTl.iX &= ~1;
+ rect.iBr.iX |= 1;
+
+ TBool forceFb =
+ AknIconUtils::DoesScaleBitmapUseFallBack( iBitmap );
+
+ if(iMask != NULL)
+ {
+ forceFb = forceFb || AknIconUtils::DoesScaleBitmapUseFallBack( iMask );
+ const TUint32 maskBytes = iMask->DisplayMode() != EGray256 ? 0xFFFFFFFFF : 0x0;
+ ::ScaleL(rect, iMask, maskBytes, forceFb);
+ }
+
+ ::ScaleL(rect, iBitmap, 0xFF000000, forceFb);
+
+ }
+
+// End of File