os/graphics/fbs/fontandbitmapserver/sfbs/BitmapCompr.inl
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/fbs/fontandbitmapserver/sfbs/BitmapCompr.inl	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,249 @@
     1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +/**
    1.20 + 
    1.21 + The created class instance doesn't take the ownership on aBase parameter.
    1.22 + @internalComponent
    1.23 + @pre aBase != NULL
    1.24 + @param aBase Points to the beginning of compressed bitmap data
    1.25 + @param aComprDataBytes Total amount of compressed bitmap bytes
    1.26 + @param aCanAdjustLineScanPos If not EFalse - scanline position can be adjusted calling
    1.27 + AdjustLineScanningPosition function.
    1.28 + @see AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, const TUint32* aBase, TInt aBitmapWidth, TInt aStartPos, TInt aCompressedDataBytes);
    1.29 +*/
    1.30 +template <TInt BPP, TInt BPP_DEST> 
    1.31 +TScanLineDecompressor<BPP, BPP_DEST>::TScanLineDecompressor(const TUint32* aBase, 
    1.32 +												  TInt aComprDataBytes, 
    1.33 +												  TBool aCanAdjustLineScanPos) :
    1.34 +	iBase(aBase),
    1.35 +	iComprDataBytes(aComprDataBytes),
    1.36 +	iCanAdjustLineScanPos(aCanAdjustLineScanPos)
    1.37 +	{
    1.38 +	}
    1.39 +
    1.40 +/**
    1.41 +The method calculates the start byte position (as a index) in decompressed bitmap data .
    1.42 +@internalComponent
    1.43 +@param aPixel The decompression starts from this pixel
    1.44 +@param aByteWidth Scanline width in bytes
    1.45 +@return Calculated start position.
    1.46 +*/
    1.47 +template <TInt BPP, TInt BPP_DEST> 
    1.48 +TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcStartPos(const TPoint& aPixel, TInt aByteWidth) const
    1.49 +	{
    1.50 +	return aPixel.iY * aByteWidth + aPixel.iX * BPP;
    1.51 +	}
    1.52 +
    1.53 +/**
    1.54 +The method calculates the start byte position (as a index) in decompressed bitmap data .
    1.55 +@internalComponent
    1.56 +@param aPixel The decompression starts from this pixel
    1.57 +@param aByteWidth Scanline width in bytes
    1.58 +@return Calculated start position.
    1.59 +*/
    1.60 +template <TInt BPP, TInt BPP_DEST> 
    1.61 +TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcDestStartPos(const TPoint& aPixel, TInt aByteWidth) const
    1.62 +	{
    1.63 +	return aPixel.iY * aByteWidth + aPixel.iX * BPP_DEST;
    1.64 +	}
    1.65 +
    1.66 +/**
    1.67 +The method calculates the end byte position (as a index) in decompressed bitmap data .
    1.68 +@internalComponent
    1.69 +@param aLength Length in pixels of bitmap data we want to decompress.
    1.70 +@param aPixel The decompression starts from this pixel
    1.71 +@param aByteWidth Scanline width in bytes
    1.72 +@return Calculated end position.
    1.73 +*/
    1.74 +template <TInt BPP, TInt BPP_DEST> 
    1.75 +TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcEndPos(TInt aLength, const TPoint& aPixel, 
    1.76 +											TInt aByteWidth) const
    1.77 +	{
    1.78 +	return aPixel.iY * aByteWidth + (aPixel.iX + aLength) * BPP_DEST;
    1.79 +	}
    1.80 +
    1.81 +/**
    1.82 +The method calculates a pointer to a place in aDestBuffer where the 
    1.83 +copying of decompressed bitmap data starts.
    1.84 +@internalComponent
    1.85 +@param aDestBuffer Points to the start of the destination buffer.
    1.86 +@param aPixel The decompression starts from this pixel
    1.87 +@return A pointer to a place in aDestBuffer where the 
    1.88 +copying of decompressed bitmap data starts.
    1.89 +*/
    1.90 +template <TInt BPP, TInt BPP_DEST> 
    1.91 +TUint8* TScanLineDecompressor<BPP, BPP_DEST>::CalcDestPtr(const TUint8* aDestBuffer, 
    1.92 +												const TPoint& aPixel) const
    1.93 +	{
    1.94 +	return const_cast <TUint8*> (aDestBuffer + aPixel.iX * BPP_DEST);
    1.95 +	}
    1.96 +
    1.97 +/**
    1.98 +The method calculates a pointer to a place in aDestBuffer where the copying
    1.99 +of the decompressed data stops.
   1.100 +@internalComponent
   1.101 +@param aDestPtr A pointer to a place in aDestBuffer where the 
   1.102 +copying of decompressed bitmap data starts - CalcDestPtr() return value.
   1.103 +@param aPixel The decompression starts from this pixel
   1.104 +@param aByteWidth Scanline width in bytes
   1.105 +@param aLength Length in pixels of bitmap data we want to decompress.
   1.106 +@param aStartPos CalcStartPos() method return value.
   1.107 +@return A pointer to a place in aDestBuffer where the 
   1.108 +copying of decompressed bitmap data stops.
   1.109 +@see CalcDestPtr
   1.110 +@see CalcStartPos
   1.111 +*/
   1.112 +template <TInt BPP, TInt BPP_DEST> 
   1.113 +TUint8* TScanLineDecompressor<BPP, BPP_DEST>::CalcDestPtrLimit(const TUint8* aDestPtr, 
   1.114 +													 const TPoint& aPixel, TInt aByteWidth, 
   1.115 +													 TInt aLength, TInt aStartPos) const
   1.116 +	{
   1.117 +	return const_cast <TUint8*> (aDestPtr + CalcEndPos(aLength, aPixel, aByteWidth) - aStartPos);
   1.118 +	}
   1.119 +
   1.120 +/**
   1.121 +The method performs a quick find of the correct start position.
   1.122 +It uses the fact that aLineScanPos parameter should be recalculated after each positioning 
   1.123 +in the compresed bitmap data and might be used in the next call of decompression methods.
   1.124 +@internalComponent
   1.125 +@param aLineScanPos Saved information about the last used position in the compressed data
   1.126 +@param aByteWidth Scanline width in bytes
   1.127 +@param aStartPos CalcStartPos() method return value.
   1.128 +@return A pointer to a position in compressed bitmap data, where the decompression  
   1.129 +starts from
   1.130 +@see CalcStartPos
   1.131 +*/
   1.132 +template <TInt BPP, TInt BPP_DEST> 
   1.133 +TUint8* TScanLineDecompressor<BPP, BPP_DEST>::AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, 
   1.134 +															   TInt aByteWidth, 
   1.135 +															   TInt aStartPos) const
   1.136 +	{
   1.137 +	TUint8* srcPtr = NULL;
   1.138 +	// Fast find the correct position to start	
   1.139 +	if(iCanAdjustLineScanPos)
   1.140 +		{
   1.141 +		::AdjustLineScanningPosition(aLineScanPos, iBase, aByteWidth, aStartPos, iComprDataBytes);
   1.142 +		}
   1.143 +	srcPtr = aLineScanPos.iSrcDataPtr;
   1.144 +	//Unfortunatelly we can't move fast srcPtr if aLineScanPos.iCursorPos > aStartPos, 
   1.145 +	//because we have 1 byte for the compressed data length and the data itself after the "length"
   1.146 +	//byte. With this information we can move srcPtr forward, not backward.
   1.147 +	if(aLineScanPos.iCursorPos > aStartPos) 
   1.148 +		{
   1.149 +		srcPtr = (TUint8*)iBase;
   1.150 +		aLineScanPos.iCursorPos = 0;
   1.151 +		}
   1.152 +	TInt count = TInt8(*srcPtr);//pixels count
   1.153 +	TInt length = (count < 0 ? -count : count + 1) * BPP;//length in bytes
   1.154 +	//If count < 0 - we have a sequence of abs(count) pixels - abs(count) * BPP bytes
   1.155 +	//If count >= 0 - we have (count + 1) pixels with the same color - (count + 1) * BPP bytes
   1.156 +	while((aLineScanPos.iCursorPos + length) <= aStartPos)
   1.157 +		{
   1.158 +		srcPtr += count < 0 ? length + 1 : (BPP + 1);//(BPP + 1) - bytes for the pixel + 1 byte for the length
   1.159 +		aLineScanPos.iCursorPos += length;
   1.160 +		count = TInt8(*srcPtr);
   1.161 +		length = (count < 0 ? -count : count + 1) * BPP;
   1.162 +		}
   1.163 +	//After executing of the previous "if" operator and "while" loop, srcPtr points to 
   1.164 +	//the nearest "length" byte before the start position in compressed bitmap data.
   1.165 +	return srcPtr;
   1.166 +	}
   1.167 +
   1.168 +/**
   1.169 +This overloaded "()" operator used for decompression of bitmap scan lines.
   1.170 +@internalComponent
   1.171 +@param aDestBuffer Points to the destination buffer. After the call it fill be filled
   1.172 +with the decomperssed data.
   1.173 +@param aPixel The decompression starts from this pixel
   1.174 +@param aLineScanPos Saved information about the last used position in the compressed data
   1.175 +@param aByteWidth Scanline width in bytes
   1.176 +@param aLength Length of requested decompressed data - in pixels
   1.177 +*/
   1.178 +template <TInt BPP, TInt BPP_DEST> 
   1.179 +void TScanLineDecompressor<BPP, BPP_DEST>::operator()(TUint8* aDestBuffer, const TPoint& aPixel, 
   1.180 +											TLineScanningPosition& aLineScanPos, 
   1.181 +											TInt aByteWidth, TInt aDestByteWidth, TInt aLength) const
   1.182 +	{
   1.183 +	TInt startPos = CalcStartPos(aPixel, aByteWidth);
   1.184 +	TInt destStartPos = CalcDestStartPos(aPixel, aDestByteWidth);
   1.185 +	TUint8* destPtr = CalcDestPtr(aDestBuffer, aPixel);
   1.186 +	const TUint8* destPtrLimit = CalcDestPtrLimit(destPtr, aPixel, aDestByteWidth, aLength, destStartPos);
   1.187 +	//Fast find the correct position to start	
   1.188 +	TUint8* srcPtr = AdjustLineScanningPosition(aLineScanPos, aByteWidth, startPos);
   1.189 +	//Decompress each slot of compressed data which has the following format:
   1.190 +	// ...|"length byte"| "pixel value(s)" |...
   1.191 +	while(destPtr < destPtrLimit)
   1.192 +		{
   1.193 +		TInt pixelsInTheSlot = TInt8(*srcPtr++);
   1.194 +		TInt availDestSpaceInBytes = destPtrLimit - destPtr;
   1.195 +		TInt skipBytes = startPos - aLineScanPos.iCursorPos;
   1.196 +		if(pixelsInTheSlot < 0)
   1.197 +			{//a sequence of abs(pixelsInTheSlot) pixels with different color values
   1.198 +			TInt bytesInTheSlot = -pixelsInTheSlot * BPP;
   1.199 +			TUint8* start_pos = srcPtr;
   1.200 +			TInt bytesToCopy = bytesInTheSlot;
   1.201 +			if(skipBytes > 0) //Skip the pixels before the start possition
   1.202 +				{
   1.203 +				bytesToCopy -= skipBytes;
   1.204 +				start_pos += skipBytes;
   1.205 +				}
   1.206 +			if(BPP == BPP_DEST)
   1.207 +				{
   1.208 +				destPtr = Mem::Copy(destPtr, start_pos, ::Min(bytesToCopy, availDestSpaceInBytes));
   1.209 +				}
   1.210 +			else
   1.211 +				{
   1.212 +				destPtr = CopyBlockPixel(destPtr, start_pos, ::Min(bytesToCopy / BPP, availDestSpaceInBytes / BPP_DEST));
   1.213 +				}	
   1.214 +			//Move to the next "length" byte only if everything, 
   1.215 +			//controlled by the current "length" byte, is copied
   1.216 +			if((bytesToCopy / BPP) <= (availDestSpaceInBytes / BPP_DEST))
   1.217 +				{
   1.218 +				srcPtr += bytesInTheSlot;
   1.219 +				aLineScanPos.iCursorPos += bytesInTheSlot;
   1.220 +				}
   1.221 +			else
   1.222 +				{
   1.223 +				srcPtr--;
   1.224 +				}
   1.225 +			}
   1.226 +		else//the "else" part of - if(pixelsInTheSlot < 0)
   1.227 +			{//(pixelsInTheSlot + 1) pixels with the same color
   1.228 +			TInt pixelsToCopy = pixelsInTheSlot + 1;
   1.229 +			TInt bytesInTheSlot = pixelsToCopy * BPP;
   1.230 +			if(skipBytes > 0) //Skip the pixels before the start possition
   1.231 +				{
   1.232 +				pixelsToCopy -= skipBytes / BPP;
   1.233 +				}
   1.234 +			destPtr = CopyPixel(destPtr, srcPtr, ::Min(pixelsToCopy, availDestSpaceInBytes / BPP_DEST));
   1.235 +			//Move to the next "length" byte only if everything, 
   1.236 +			//controlled by the current "length" byte, is copied
   1.237 +			if((pixelsToCopy * BPP) <= availDestSpaceInBytes)
   1.238 +				{
   1.239 +				srcPtr += BPP;// += BPP - we have (count + 1) pixels with the same color - only BPP bytes are used.
   1.240 +				aLineScanPos.iCursorPos += bytesInTheSlot;
   1.241 +				}
   1.242 +			else
   1.243 +				{
   1.244 +				srcPtr--;
   1.245 +				}
   1.246 +			}//end of - if(pixelsCnt < 0)
   1.247 +		}//end of - while(destPtr < destPtrLimit)
   1.248 +	aLineScanPos.iSrcDataPtr = srcPtr;//update aLineScanPos.iSrcDataPtr - it will be used 
   1.249 +									  //when the method is called again.
   1.250 +	}
   1.251 +
   1.252 +