diff -r 000000000000 -r 05e9090e2422 uigraphics/AknIcon/SvgtFbsRasterizer/src/SvgtFbsRasterizer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uigraphics/AknIcon/SvgtFbsRasterizer/src/SvgtFbsRasterizer.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,675 @@ +/* +* 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: CSvgtFbsRasterizer implementation. +* +*/ + +#include "svgtfbsrasterizer.h" +#include "fbsrasterizerpanics.h" +#include "SvgtRegisteredBitmap.h" +#include "svgtgraphicsinterface.h" +#include +#include +#include +#include +#include + +#include +#include + +TBool operator==(const CFbsRasterizer::TBitmapDesc& aBitmapDesc1, + const CFbsRasterizer::TBitmapDesc& aBitmapDesc2) + { + return ((&aBitmapDesc1 == &aBitmapDesc2) + || (aBitmapDesc1.iSizeInPixels == aBitmapDesc2.iSizeInPixels + && aBitmapDesc1.iDispMode == aBitmapDesc2.iDispMode + && aBitmapDesc1.iDataType == aBitmapDesc2.iDataType + && aBitmapDesc1.iData == aBitmapDesc2.iData + && aBitmapDesc1.iDataSize == aBitmapDesc2.iDataSize)); + } + +void CleanupVGImage( TAny* aObj ) + { + VGImage * imageToDestroy = reinterpret_cast(aObj); + if (imageToDestroy && *imageToDestroy != VG_INVALID_HANDLE) + { + vgDestroyImage(*imageToDestroy); + } + } + +/** Create a new rasterizer. +@return A pointer to a newly constructed CFbsRasterizer object if successful, +or NULL if no memory is available. + */ +EXPORT_C CFbsRasterizer* CSvgtFbsRasterizer::New() + { + CSvgtFbsRasterizer* self = new CSvgtFbsRasterizer; + if ( self ) + { + self->InitializeRasterizer(); + } + return self; + } + +/** Constructor */ +CSvgtFbsRasterizer::CSvgtFbsRasterizer() + :iRegisteredBmps(_FOFF(CSvgtRegisteredBitmap, iLink)), iRecentBmps(_FOFF(CSvgtRegisteredBitmap, iLink)) + { + RProcess currentProcess; + TFileName exeFileName = currentProcess.FileName(); + exeFileName.Copy(exeFileName.Mid(11)); + exeFileName.Copy(exeFileName.Left(exeFileName.Length()-4)); + + if(exeFileName.Compare(_L("peninputserver"))==0) + { + iCacheLimit = 0x133333; + iSpecialProcess = TRUE; + } + else + { + iCacheLimit = KMaxRecentBmpCacheSize; + iSpecialProcess = FALSE; + } + } + +CSvgtFbsRasterizer::~CSvgtFbsRasterizer() + { + while (!iRegisteredBmps.IsEmpty()) + { + delete iRegisteredBmps.First(); + } + while (!iRecentBmps.IsEmpty()) + { + delete iRecentBmps.First(); + } + delete iIdle; + + delete iNvgEngine; + delete iGraphicsInterface; + if ( iMatricesUpdated ) + { + RestoreMatrices(); + } + } + +/** Register a bitmap with this rasterizer for rendering. In this example the extended +bitmap data is just a buffer that is copied when BeginBitmap() is called and deleted when +EndBitmap() is called for the same bitmap. The only display modes supported by this example +raterizer are EColor16MU and EColor16MA +*/ +void CSvgtFbsRasterizer::BeginBitmap(TInt64 aBitmapId, const TBitmapDesc& aBitmapDesc, const TRegion* aRegionOfInterest) + { + TRAPD(beginErr, DoBeginBitmapL(aBitmapId, aBitmapDesc, aRegionOfInterest)); + // If there is error in begin, the consecutive fulction calls should be invalid. + iIsRasterizerValidState = ( beginErr == KErrNone); + } + +void CSvgtFbsRasterizer::DoBeginBitmapL(TInt64 aBitmapId, const TBitmapDesc& aBitmapDesc, + const TRegion* /* aRegionOfInterest */) + { + // Check that the passed extended bitmap description is valid + if ((aBitmapDesc.iSizeInPixels.iWidth <= 0) || (aBitmapDesc.iSizeInPixels.iHeight <= 0) + || (aBitmapDesc.iDataType != KUidNvgProprietaryFormat) + || (!aBitmapDesc.iData ) + || (aBitmapDesc.iDataSize <= 0)) + { + return; + } + // Check if the bitmap is already registered + CSvgtRegisteredBitmap* foundRegBmp = RegisteredBitmap(aBitmapId); + if (!foundRegBmp) + { + // Not registered: check if the bitmap is in the cache of recently used bitmaps + foundRegBmp = RecentBitmap(aBitmapId); + if (foundRegBmp) + { + // Take the bitmap out of the cache and put it in the list of registered bitmaps + foundRegBmp->iLink.Deque(); + iTotalRecentBmpSize -= foundRegBmp->DataSize(); + iRegisteredBmps.AddLast(*foundRegBmp); + } + } + if (foundRegBmp) + { + // This bitmap is already registered, just increment its reference count and return + foundRegBmp->iRefCount++; + return; + } + + CSvgtRegisteredBitmap* regBmp = new CSvgtRegisteredBitmap(aBitmapId); + if (!regBmp) + { + return; + } + TRAPD(err, RenderL(aBitmapDesc, *regBmp)); + if (err != KErrNone) + { + delete regBmp; + return; + } + // Success + iRegisteredBmps.AddLast(*regBmp); + regBmp->iRefCount = 1; + } + +/** Unregister an extended bitmap from this rasterizer. +@see CFbsRasterizer::EndBitmap() +@see BeginBitmap() + */ +void CSvgtFbsRasterizer::EndBitmap(TInt64 aBitmapId) + { + CSvgtRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId); + if (regBmp) + { + if (--regBmp->iRefCount == 0) + { + // Put unregistered bitmap in the cache of recently used bitmaps if wholly pre-rendered + // and there is an active scheduler to add the idle-time clean-up active object to + if (CActiveScheduler::Current()) + { + if (!iIdle) + { + iIdle = CIdle::New(CActive::EPriorityIdle); + if (!iIdle) + { + delete regBmp; + return; + } + } + regBmp->iLink.Deque(); + if (regBmp->DataSize() <= iCacheLimit) + { + iRecentBmps.AddFirst(*regBmp); + iTotalRecentBmpSize += regBmp->DataSize(); + } + // Delete the least recently used bitmaps if the maximum size of the cache is exceeded + while (iTotalRecentBmpSize > iCacheLimit) + { + regBmp = iRecentBmps.Last(); + iTotalRecentBmpSize -= regBmp->DataSize(); + delete regBmp; + } + // If the cache is not empty make sure the idle-time clean-up active object is scheduled to run + if (!iRecentBmps.IsEmpty() && !iIdle->IsActive()) + { + iIdle->Start(TCallBack(IdleFunction, this)); + } + } + else + { + delete regBmp; + } + } + } + } + +/** Return a scanline from the passed extended bitmap given it's bitmap id. + */ +const TUint32* CSvgtFbsRasterizer::ScanLine(TInt64 aBitmapId, const TPoint& aPixel, TInt aLength) + { + CSvgtRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId); + if (!regBmp) + { + return NULL; + } + if (!TRect(regBmp->SizeInPixels()).Contains(aPixel) + || (aLength > (regBmp->SizeInPixels().iWidth - aPixel.iX))) + { + return NULL; + } + + return PtrAdd(regBmp->DataAddress(), aPixel.iY * regBmp->DataStride()); + } + +/** No extension interaces are available, KErrNotSupported for all aInterfaceId passed. +@see CFbsRasterizer::GetInterface() + */ +TInt CSvgtFbsRasterizer::GetInterface(TUid /*aInterfaceId*/, TAny*& aInterface) + { + aInterface = NULL; + return KErrExtensionNotSupported; + } + + +/** Gets a bitmap that has been registered with this rasterizer. + +@param aBitmapId The ID of the bitmap to check for. + +@return A pointer to the registered bitmap if found, NULL otherwise. + */ +CSvgtRegisteredBitmap* CSvgtFbsRasterizer::RegisteredBitmap(TInt64 aBitmapId) + { + TDblQueIter iter(iRegisteredBmps); + while (CSvgtRegisteredBitmap* regBmp = iter++) + { + if (regBmp->iBitmapId == aBitmapId) + { + return regBmp; + } + } + return NULL; + } + +/** Gets a bitmap that has been recently used with this rasterizer. + +@param aBitmapId The ID of the bitmap to check for. + +@return A pointer to the recently used bitmap if found, NULL otherwise. + */ +CSvgtRegisteredBitmap* CSvgtFbsRasterizer::RecentBitmap(TInt64 aBitmapId) + { + TDblQueIter iter(iRecentBmps); + while (CSvgtRegisteredBitmap* regBmp = iter++) + { + if (regBmp->iBitmapId == aBitmapId) + { + return regBmp; + } + } + return NULL; + } + +TInt CSvgtFbsRasterizer::IdleFunction(TAny* aPtr) + { + CSvgtFbsRasterizer* self = static_cast(aPtr); + if(self->iSpecialProcess!=true) + { + + while (!self->iRecentBmps.IsEmpty()) + { + delete self->iRecentBmps.First(); + } + self->iTotalRecentBmpSize = 0; + } + return 0; + } + +void CSvgtFbsRasterizer::InitializeRasterizer() + { + } + +void CSvgtFbsRasterizer::RenderBitmapL(CSvgtRegisteredBitmap& aPixMap, CFbsBitmap * aMask, + const TBitmapDesc& aBitmapDesc, TPtr8& aDataPtr8, TAknIconHeader& aIconHeader) + { + TSize newSize = aBitmapDesc.iSizeInPixels; + UpdateMatrices(); + iMatricesUpdated = ETrue; + TBool isMargin = aIconHeader.IsMarginCorrection(); + + VGImage vgImage = VG_INVALID_HANDLE; + + if (isMargin) + { + vgImage = vgCreateImage((VGImageFormat) VG_sRGBA_8888_PRE , aBitmapDesc.iSizeInPixels.iWidth, + aBitmapDesc.iSizeInPixels.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); + if (vgImage == VG_INVALID_HANDLE) + { + User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); + } + CleanupStack::PushL( TCleanupItem( CleanupVGImage, &vgImage ) ); + iGraphicsInterface->BindClientBuffer(vgImage); + } + User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, newSize, &aPixMap, aMask)); + + if(isMargin) + { + iGraphicsInterface->UnBindClientBuffer(); + newSize = ApplyMarginL(vgImage, aBitmapDesc.iSizeInPixels); + if(newSize!=aBitmapDesc.iSizeInPixels) + { + User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, newSize, &aPixMap, aMask)); + } + else + { + vgDrawImage(vgImage); + User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); + } + + CleanupStack::PopAndDestroy(); + } + iGraphicsInterface->CopyBitmapL(&aPixMap, aMask); + + TUint32 iconColor = aIconHeader.GetIconColor(); + + if (iconColor & 0xFFFFFF) + { + CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( &aPixMap ); + CleanupStack::PushL( dev ); + CFbsBitGc* gc = NULL; + User::LeaveIfError( dev->CreateContext( gc ) ); + CleanupStack::PushL( gc ); + TRgb color(iconColor); + gc->SetBrushColor( color ); + gc->SetPenStyle( CGraphicsContext::ENullPen ); + gc->SetBrushStyle( CGraphicsContext::ESolidBrush ); + // Fill icon with the given color, mask defines the icon shape. + TPoint origin(0, 0); + if (newSize != aBitmapDesc.iSizeInPixels) + { + origin = TPoint((aBitmapDesc.iSizeInPixels.iWidth - newSize.iWidth)/2 , (aBitmapDesc.iSizeInPixels.iHeight - newSize.iHeight)/2 ); + } + gc->DrawRect( TRect( origin, newSize ) ); + CleanupStack::PopAndDestroy( 2 ); // dev, gc + } + } + +void CSvgtFbsRasterizer::RenderMaskL(CSvgtRegisteredBitmap& aPixMap, CFbsBitmap * aMask, + const TBitmapDesc& aBitmapDesc, TPtr8& aDataPtr8, TAknIconHeader& aIconHeader) + { + UpdateMatrices(); + iMatricesUpdated = ETrue; + TBool isMargin = aIconHeader.IsMarginCorrection(); + + VGImage vgImage = VG_INVALID_HANDLE; + if (isMargin) + { + vgImage = vgCreateImage((VGImageFormat) VG_sRGBA_8888_PRE , aBitmapDesc.iSizeInPixels.iWidth, + aBitmapDesc.iSizeInPixels.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); + if (vgImage == VG_INVALID_HANDLE) + { + User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); + } + CleanupStack::PushL( TCleanupItem( CleanupVGImage, &vgImage ) ); + iGraphicsInterface->BindClientBuffer(vgImage); + } + + VGfloat color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vgSeti(VG_SCISSORING, VG_FALSE); + vgSetfv(VG_CLEAR_COLOR, 4, color); + vgClear(0, 0, aBitmapDesc.iSizeInPixels.iWidth, aBitmapDesc.iSizeInPixels.iHeight); + + User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, aBitmapDesc.iSizeInPixels, &aPixMap, aMask)); + if (isMargin) + { + iGraphicsInterface->UnBindClientBuffer(); + TSize newSize = ApplyMarginL(vgImage, aBitmapDesc.iSizeInPixels); + if(newSize!=aBitmapDesc.iSizeInPixels) + { + User::LeaveIfError(iNvgEngine->DrawNvg(aDataPtr8, newSize, &aPixMap, aMask)); + } + else + { + vgDrawImage(vgImage); + User::LeaveIfError(MapOpenVgErrorCodeToSymbian(vgGetError())); + } + CleanupStack::PopAndDestroy(); + } + + TSize bitmapSize = aPixMap.SizeInPixels(); + + const TInt KOriginalFilterMasks = vgGeti( VG_FILTER_CHANNEL_MASK ); + vgSeti( VG_FILTER_CHANNEL_MASK, VG_ALPHA ); + + const TInt KStride = CFbsBitmap::ScanLineLength(bitmapSize.iWidth, aPixMap.DisplayMode()); + VGImageFormat format = ( aPixMap.DisplayMode() == EGray256 ) ? VG_A_8 : VG_BW_1; + + aPixMap.BeginDataAccess(); + TUint * data = (TUint*)((TUint)aPixMap.DataAddress() + ( KStride * ( aPixMap.SizeInPixels().iHeight - 1 ) ) ); + vgReadPixels( data, -KStride, format, 0, 0, bitmapSize.iWidth, bitmapSize.iHeight ); + aPixMap.EndDataAccess(); + + vgSeti( VG_FILTER_CHANNEL_MASK, KOriginalFilterMasks ); + + } + +void CSvgtFbsRasterizer::RenderL( const TBitmapDesc& aBitmapDesc, CSvgtRegisteredBitmap& aBitmap ) + { + + iIsRasterizerValidState = EFalse; + + User::LeaveIfError(aBitmap.Create(aBitmapDesc.iSizeInPixels, aBitmapDesc.iDispMode)); + + if (!iGraphicsInterface) + { + iGraphicsInterface = CSvgtGraphicsInterface::CreateImplementationL(); + } + + iGraphicsInterface->InitializeL(aBitmapDesc.iSizeInPixels); + iIsRasterizerValidState = ETrue; + + TPtr8 bmpDataPtr8((TUint8*)aBitmapDesc.iData, aBitmapDesc.iDataSize); + + if (!iNvgEngine) + { + iNvgEngine = CNvgEngine::NewL(); + } + + iNvgEngine->SetVGImageBinder(iGraphicsInterface); + + TUint8 *temp = (TUint8 *)bmpDataPtr8.Ptr(); + TPtr8 IconHeaderPtr(temp, KIconHeaderLength, KIconHeaderLength); + + TAknIconHeader iconheader(IconHeaderPtr); + //skipping header bytes + temp = temp + KIconHeaderLength; + TPtr8 newDataPtr8(temp, (bmpDataPtr8.MaxLength() - KIconHeaderLength), (bmpDataPtr8.MaxLength() - KIconHeaderLength)); + + CFbsBitmap* mask = NULL; + + VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; + vgSeti(VG_SCISSORING, VG_FALSE); + vgSetfv(VG_CLEAR_COLOR, 4, color); + vgClear(0, 0, aBitmapDesc.iSizeInPixels.iWidth, aBitmapDesc.iSizeInPixels.iHeight); + TInt rotAngle = iconheader.GetRotation(); + // setting the rotation angle + iNvgEngine->Rotate(-rotAngle, aBitmapDesc.iSizeInPixels.iWidth >> 1,aBitmapDesc.iSizeInPixels.iHeight >>1); + + //setting preserve aspect ratio + TNvgAlignStatusType alignTypeValue = ENvgPreserveAspectRatio_XmidYmid; + TNvgMeetOrSliceType meetOrSliceTypeValue = ENvgMeet; + + switch ( iconheader.GetScaleMode() ) + { + case EAspectRatioPreserved: // fall through + { + // use default + break; + } + // Ensures NVG content fully covers the area of the icon whilst preserving aspect ratio. + case EAspectRatioPreservedSlice: + { + // alignTypeValue use default + meetOrSliceTypeValue = ENvgSlice; + break; + } + /* EAspectRatioPreservedAndUnusedSpaceRemoved is mapped to the same values as EAspectRatioNotPreserved + * because we already have a frame buffer with the dimensions that preserves the aspect ratio. + * This mapping ensures that NVG engine does not calculate aspect ratio twice and potentially resulting in precision loss.*/ + case EAspectRatioPreservedAndUnusedSpaceRemoved: + case EAspectRatioNotPreserved: + { + alignTypeValue = ENvgPreserveAspectRatio_None; + // meetOrSliceTypeValue use default + break; + } + default: + { + User::Leave(KErrCorrupt); + } + } + iNvgEngine->SetPreserveAspectRatio(alignTypeValue, meetOrSliceTypeValue); + + iMatricesUpdated = EFalse; + if (iconheader.IsMask()) + { + RenderMaskL(aBitmap, mask, aBitmapDesc, newDataPtr8, iconheader); + } + else + { + RenderBitmapL(aBitmap, mask, aBitmapDesc, newDataPtr8, iconheader); + } + + if ( iMatricesUpdated ) + { + RestoreMatrices(); + iMatricesUpdated = EFalse; + } + } + +void CSvgtFbsRasterizer::UpdateMatrices() + { + iUserStrokePaint = vgGetPaint(VG_STROKE_PATH); + + iUserFillPaint = vgGetPaint(VG_FILL_PATH); + + iMatrixMode = vgGeti(VG_MATRIX_MODE); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + + vgGetMatrix(iPathMatrix); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + + vgGetMatrix(iImageMatrix); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); + + vgGetMatrix(iFillPaintMatrix); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER); + + vgGetMatrix(iStrokePaintMatrix); + + vgSeti(VG_MATRIX_MODE, iMatrixMode); + + } + +void CSvgtFbsRasterizer::RestoreMatrices() + { + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + + vgLoadMatrix(iPathMatrix); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + + vgLoadMatrix(iImageMatrix); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); + + vgLoadMatrix(iFillPaintMatrix); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER); + + vgLoadMatrix(iStrokePaintMatrix); + + vgSeti(VG_MATRIX_MODE, iMatrixMode); + + vgSetPaint(iUserStrokePaint, VG_STROKE_PATH); + + vgSetPaint(iUserFillPaint, VG_FILL_PATH); + } + + +TSize CSvgtFbsRasterizer::ApplyMarginL(VGImage aVgImage, TSize aSize) + { + HBufC8* buf = HBufC8::NewL(aSize.iWidth* sizeof(TUint32)); + TUint32* ptr = (TUint32*)(buf->Des()).Ptr(); + + const TInt validMargin = aSize.iHeight * 12 / 100; + + const TInt Ha = aSize.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; + + const TInt lastColumn = aSize.iHeight - 1; + for ( TInt curRow = 0; curRow < validMargin; curRow++ ) + { + const TInt y = (aSize.iHeight - 1) - curRow; // h - 1 is the last line + + vgGetImageSubData(aVgImage, ptr, sizeof(TUint)*aSize.iWidth, VG_sRGBA_8888_PRE, 0, y, aSize.iWidth, 1); + + for ( TInt s = lastColumn; s >= 0; --s ) + { + if ( ptr[s] & 0x000000FF ) + { + 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; + curRow = validMargin; // to exit the outer loop + break; // to exit the inner + } + + } + } + + delete buf; + + if(aSize.iHeight > HaN) + { + + VGfloat color[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; + + vgSetfv(VG_CLEAR_COLOR, 4, color); + vgClear(0, 0, aSize.iWidth,aSize.iHeight); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + VGfloat Hr = (VGfloat)HaN/(aSize.iHeight); + + TInt WaN = aSize.iWidth*Hr; + + VGfloat Tx = (aSize.iHeight-HaN)/2; + VGfloat Ty = (aSize.iWidth-WaN)/2; + vgTranslate(Tx,Ty); + + return( TSize(HaN,WaN)); + } + return aSize; + + } + + + +TInt CSvgtFbsRasterizer::MapOpenVgErrorCodeToSymbian(TInt aErrorCode) + { + switch( aErrorCode ) + { + case VGI_OK: + return KErrNone; + + case VGI_ERROR_OUT_OF_MEMORY: + return KErrNoMemory; + + case VGI_ERROR_INVALID_ARGUMENTS: + return KErrArgument; + + case VGI_ERROR_ALREADY_EXISTS: + return KErrAlreadyExists; + + case VGI_ERROR_COLORSPACE_NOT_SUPPORTED: + return KErrNotSupported; + + case VGI_ERROR_NOT_SUPPORTED: + return KErrNotSupported; + + case VGI_ERROR_ILLEGAL_IMAGE_HANDLE: + return KErrBadHandle; + + case VGI_ERROR_IMAGE_IN_USE: + return KErrInUse; + + case VGI_ERROR_ILLEGAL_OPERATION: + return KErrPermissionDenied; + + default: + return KErrUnknown; + } + + } +