fbs/fontandbitmapserver/sfbs/BitmapCompr.cpp
author Faisal Memon <faisal.memon@nokia.com>
Fri, 25 Jun 2010 17:49:58 +0100
branchEGL_MERGE
changeset 105 158b2308cc08
parent 0 5d03bc08d59c
permissions -rw-r--r--
Fix def files so that the implementation agnostic interface definition has no non-standards defined entry points, and change the eglrefimpl specific implementation to place its private entry points high up in the ordinal order space in the implementation region, not the standards based entrypoints region.

// 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 the
nearest "length" byte before aStartPos.
Note: The method should be used only for compressed in RAM bitmaps for which
iPile != 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 times
to 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 times
to 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 times
to 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 times
to 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 times
to 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;
	}