// Copyright (c) 2003-2009 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 <e32base.h>#include <bitmap.h>#include "CompressionBookmark.h"#include "BitmapCompr.h"#include "UTILS.H"#include "bitmapconst.h"GLREF_C void Panic(TFbsPanic aPanic);/**The method recalculates aLineScanPos which is used for quick search of thenearest "length" byte before aStartPos.Note: The method should be used only for compressed in RAM bitmaps for whichiPile != NULL.@internalComponent@post aLineScanPos might be updated*/GLDEF_C void AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, const TUint32* aBase, TInt aBitmapWidth, TInt aStartPos, TInt aCompressedDataBytes) { TInt difference = ::Abs(aStartPos - aLineScanPos.iCursorPos); if(difference > aBitmapWidth && aCompressedDataBytes > KCompressionBookMarkThreshold) { const TCompressionBookMark* bookMarkPtr = (const TCompressionBookMark*)((const TUint8*)aBase + (aCompressedDataBytes + 3) / 4 * 4 + 4); if(bookMarkPtr->iSrcDataOffset && bookMarkPtr->IsCheckSumOk()) { TInt difference2 = ::Abs(aStartPos - bookMarkPtr->iCursorPos); if(difference2 < difference) { aLineScanPos.iCursorPos = bookMarkPtr->iCursorPos; aLineScanPos.iSrcDataPtr = ((TUint8*)aBase) + bookMarkPtr->iSrcDataOffset; } } } }/**The method gets the first 16 bpp pixel value pointed by aSrcPtr and copies it aCount timesto aDestPtr buffer.@internalComponent@pre aCount > 0@param aSrcPtr It points to the source pixel@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times@param aCount How many times the pixel value should be copied@return The updated aDestPtr*/template <> TUint8* TScanLineDecompressor<E2bpp, E2bpp>::CopyPixel(TUint8* aDestPtr, const TUint8* aSrcPtr, TInt aCount) const { //We can't access directly the 16 bits data chunk, because it may be located at an odd address and //THUMB build will fail with "KERNEL EXEC-3". TUint8 lsb = *aSrcPtr; TUint8 msb = *(aSrcPtr + 1); TUint16 data = TUint16(lsb | (TUint16(msb) << 8)); TUint32 data32 = TUint32(data | (TUint32(data) << 16)); if((TUint32(aDestPtr) & 0x2) && aCount) { *(TUint16*)aDestPtr = data; aDestPtr += 2;//+= 2 - the pixel color is coded into 16 bits - 2 bytes aCount--; } while(aCount > 1) { *(TUint32*)aDestPtr = data32; aDestPtr += 4;//+= 4 - the pixel color is coded into 16 bits - 2 x 2 bytes aCount -= 2; } if(aCount) { *(TUint16*)aDestPtr = data; aDestPtr += 2;//+= 2 - the pixel color is coded into 16 bits - 2 bytes } return aDestPtr; }/**The method gets the first 24 bpp pixel value pointed by aSrcPtr and copies it aCount timesto aDestPtr buffer.@internalComponent@pre aCount > 0@param aSrcPtr It points to the source pixel@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times@param aCount How many times the pixel value should be copied@return The updated aDestPtr*/template <> TUint8* TScanLineDecompressor<E3bpp, E3bpp>::CopyPixel(TUint8* aDestPtr, const TUint8* aSrcPtr, TInt aCount) const { const TUint8 b1 = *aSrcPtr; const TUint8 b2 = *(aSrcPtr + 1); const TUint8 b3 = *(aSrcPtr + 2); while(aCount--) { *aDestPtr++ = b1; *aDestPtr++ = b2; *aDestPtr++ = b3; } return aDestPtr; }/**The method gets the first 32 bpp pixel value pointed by aSrcPtr and copies it aCount timesto aDestPtr buffer.@internalComponent@pre aCount > 0@param aSrcPtr It points to the source pixel@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times@param aCount How many times the pixel value should be copied@return The updated aDestPtr*/template <> TUint8* TScanLineDecompressor<E4bpp, E4bpp>::CopyPixel(TUint8* aDestPtr, const TUint8* aSrcPtr, TInt aCount) const { __ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestPtr) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned const TUint8 b1 = *aSrcPtr; const TUint8 b2 = *(aSrcPtr + 1); const TUint8 b3 = *(aSrcPtr + 2); const TUint8 b4 = *(aSrcPtr + 3); if((reinterpret_cast<TUint32>(aDestPtr) & 0x3)== 0) // the start address is word aligned { const TUint32 pixel = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1; TUint32* destPtr32 = reinterpret_cast <TUint32*>(aDestPtr); TInt blocksOf16 = ((aCount + 0x0f) >> 4); // number of blocks of upto 16 words to write // the first iteration writes 1 to 15 words switch (aCount & 0x0f) { // note that case statements intentionally cascade case 0: do { // second and subsequent iterations always write 16 words *destPtr32++ = pixel; case 15: *destPtr32++ = pixel; case 14: *destPtr32++ = pixel; case 13: *destPtr32++ = pixel; case 12: *destPtr32++ = pixel; case 11: *destPtr32++ = pixel; case 10: *destPtr32++ = pixel; case 9: *destPtr32++ = pixel; case 8: *destPtr32++ = pixel; case 7: *destPtr32++ = pixel; case 6: *destPtr32++ = pixel; case 5: *destPtr32++ = pixel; case 4: *destPtr32++ = pixel; case 3: *destPtr32++ = pixel; case 2: *destPtr32++ = pixel; case 1: *destPtr32++ = pixel; } while(--blocksOf16 > 0); } return reinterpret_cast <TUint8*>(destPtr32); } while(aCount--) { *aDestPtr++ = b1; *aDestPtr++ = b2; *aDestPtr++ = b3; *aDestPtr++ = b4; } return aDestPtr; }/**The method gets the first 24 bpp pixel value pointed by aSrcPtr and copies it aCount timesto aDestPtr 32 bpp buffer.@internalComponent@pre aCount > 0@param aSrcPtr It points to the source pixel@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times@param aCount How many times the pixel value should be copied@return The updated aDestPtr*/template <> TUint8* TScanLineDecompressor<E3bpp, E4bpp>::CopyPixel(TUint8* aDestPtr, const TUint8* aSrcPtr, TInt aCount) const { const TUint8 b1 = *aSrcPtr; const TUint8 b2 = *(aSrcPtr + 1); const TUint8 b3 = *(aSrcPtr + 2); if((reinterpret_cast<TUint32>(aDestPtr) & 0x3)== 0) // the start address is word aligned { const TUint32 pixel = 0xFF000000 | (b3 << 16) | (b2 << 8) | b1; //it is more accurate to equalize to 0xff, //as top byte could correspond an alpha channel TUint32* destPtr32 = reinterpret_cast <TUint32*>(aDestPtr); TInt blocksOf16 = ((aCount + 0x0f) >> 4); // number of blocks of upto 16 words to write // the first iteration writes 1 to 15 words switch (aCount & 0x0f) { // note that case statements intentionally cascade case 0: do { // second and subsequent iterations always write 16 words *destPtr32++ = pixel; case 15: *destPtr32++ = pixel; case 14: *destPtr32++ = pixel; case 13: *destPtr32++ = pixel; case 12: *destPtr32++ = pixel; case 11: *destPtr32++ = pixel; case 10: *destPtr32++ = pixel; case 9: *destPtr32++ = pixel; case 8: *destPtr32++ = pixel; case 7: *destPtr32++ = pixel; case 6: *destPtr32++ = pixel; case 5: *destPtr32++ = pixel; case 4: *destPtr32++ = pixel; case 3: *destPtr32++ = pixel; case 2: *destPtr32++ = pixel; case 1: *destPtr32++ = pixel; } while(--blocksOf16 > 0); } return reinterpret_cast <TUint8*>(destPtr32); } while(aCount--) { *aDestPtr++ = b1; *aDestPtr++ = b2; *aDestPtr++ = b3; *aDestPtr++ = 0xff; //it is more accurate to equalize to 0xff, as top byte //could correspond an alpha channel } return aDestPtr; }/**The method gets the 24 bpp pixel value pointed by aSrcPtr and copies it aCount timesto aDestPtr 32 bpp buffer.@internalComponent@pre aCount > 0@param aSrcPtr It points to the source pixel@param aDestPtr It points to the destination buffer where the pixel should be copied aCount times@param aCount How many times the pixel value should be copied@return The updated aDestPtr*/template <> TUint8* TScanLineDecompressor<E3bpp, E4bpp>::CopyBlockPixel(TUint8* aDestPtr, const TUint8* aSrcPtr, TInt aCount) const { while(aCount--) { *aDestPtr++ = *aSrcPtr++; *aDestPtr++ = *aSrcPtr++; *aDestPtr++ = *aSrcPtr++; *aDestPtr++ = 0xff; //it is more accurate to equalize to 0xff, as top byte //could correspond an alpha channel } return aDestPtr; }/**The method should never be executed.Introduced to prevent CCover compiler from failing.@internalComponent@return The unchanged aDestPtr*/template <> TUint8* TScanLineDecompressor<E2bpp, E2bpp>::CopyBlockPixel(TUint8* aDestPtr, const TUint8* /*aSrcPtr*/, TInt /*aCount*/) const { return aDestPtr; }/**The method should never be executed.Introduced to prevent CCover compiler from failing.@internalComponent@return The unchanged aDestPtr*/template <> TUint8* TScanLineDecompressor<E3bpp, E3bpp>::CopyBlockPixel(TUint8* aDestPtr, const TUint8* /*aSrcPtr*/, TInt /*aCount*/) const { return aDestPtr; }/**The method should never be executed.Introduced to prevent CCover compiler from failing.@internalComponent@return The unchanged aDestPtr*/template <> TUint8* TScanLineDecompressor<E4bpp, E4bpp>::CopyBlockPixel(TUint8* aDestPtr, const TUint8* /*aSrcPtr*/, TInt /*aCount*/) const { return aDestPtr; }