fbs/fontandbitmapserver/sfbs/BitmapCompr.inl
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  
       
    18  The created class instance doesn't take the ownership on aBase parameter.
       
    19  @internalComponent
       
    20  @pre aBase != NULL
       
    21  @param aBase Points to the beginning of compressed bitmap data
       
    22  @param aComprDataBytes Total amount of compressed bitmap bytes
       
    23  @param aCanAdjustLineScanPos If not EFalse - scanline position can be adjusted calling
       
    24  AdjustLineScanningPosition function.
       
    25  @see AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, const TUint32* aBase, TInt aBitmapWidth, TInt aStartPos, TInt aCompressedDataBytes);
       
    26 */
       
    27 template <TInt BPP, TInt BPP_DEST> 
       
    28 TScanLineDecompressor<BPP, BPP_DEST>::TScanLineDecompressor(const TUint32* aBase, 
       
    29 												  TInt aComprDataBytes, 
       
    30 												  TBool aCanAdjustLineScanPos) :
       
    31 	iBase(aBase),
       
    32 	iComprDataBytes(aComprDataBytes),
       
    33 	iCanAdjustLineScanPos(aCanAdjustLineScanPos)
       
    34 	{
       
    35 	}
       
    36 
       
    37 /**
       
    38 The method calculates the start byte position (as a index) in decompressed bitmap data .
       
    39 @internalComponent
       
    40 @param aPixel The decompression starts from this pixel
       
    41 @param aByteWidth Scanline width in bytes
       
    42 @return Calculated start position.
       
    43 */
       
    44 template <TInt BPP, TInt BPP_DEST> 
       
    45 TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcStartPos(const TPoint& aPixel, TInt aByteWidth) const
       
    46 	{
       
    47 	return aPixel.iY * aByteWidth + aPixel.iX * BPP;
       
    48 	}
       
    49 
       
    50 /**
       
    51 The method calculates the start byte position (as a index) in decompressed bitmap data .
       
    52 @internalComponent
       
    53 @param aPixel The decompression starts from this pixel
       
    54 @param aByteWidth Scanline width in bytes
       
    55 @return Calculated start position.
       
    56 */
       
    57 template <TInt BPP, TInt BPP_DEST> 
       
    58 TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcDestStartPos(const TPoint& aPixel, TInt aByteWidth) const
       
    59 	{
       
    60 	return aPixel.iY * aByteWidth + aPixel.iX * BPP_DEST;
       
    61 	}
       
    62 
       
    63 /**
       
    64 The method calculates the end byte position (as a index) in decompressed bitmap data .
       
    65 @internalComponent
       
    66 @param aLength Length in pixels of bitmap data we want to decompress.
       
    67 @param aPixel The decompression starts from this pixel
       
    68 @param aByteWidth Scanline width in bytes
       
    69 @return Calculated end position.
       
    70 */
       
    71 template <TInt BPP, TInt BPP_DEST> 
       
    72 TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcEndPos(TInt aLength, const TPoint& aPixel, 
       
    73 											TInt aByteWidth) const
       
    74 	{
       
    75 	return aPixel.iY * aByteWidth + (aPixel.iX + aLength) * BPP_DEST;
       
    76 	}
       
    77 
       
    78 /**
       
    79 The method calculates a pointer to a place in aDestBuffer where the 
       
    80 copying of decompressed bitmap data starts.
       
    81 @internalComponent
       
    82 @param aDestBuffer Points to the start of the destination buffer.
       
    83 @param aPixel The decompression starts from this pixel
       
    84 @return A pointer to a place in aDestBuffer where the 
       
    85 copying of decompressed bitmap data starts.
       
    86 */
       
    87 template <TInt BPP, TInt BPP_DEST> 
       
    88 TUint8* TScanLineDecompressor<BPP, BPP_DEST>::CalcDestPtr(const TUint8* aDestBuffer, 
       
    89 												const TPoint& aPixel) const
       
    90 	{
       
    91 	return const_cast <TUint8*> (aDestBuffer + aPixel.iX * BPP_DEST);
       
    92 	}
       
    93 
       
    94 /**
       
    95 The method calculates a pointer to a place in aDestBuffer where the copying
       
    96 of the decompressed data stops.
       
    97 @internalComponent
       
    98 @param aDestPtr A pointer to a place in aDestBuffer where the 
       
    99 copying of decompressed bitmap data starts - CalcDestPtr() return value.
       
   100 @param aPixel The decompression starts from this pixel
       
   101 @param aByteWidth Scanline width in bytes
       
   102 @param aLength Length in pixels of bitmap data we want to decompress.
       
   103 @param aStartPos CalcStartPos() method return value.
       
   104 @return A pointer to a place in aDestBuffer where the 
       
   105 copying of decompressed bitmap data stops.
       
   106 @see CalcDestPtr
       
   107 @see CalcStartPos
       
   108 */
       
   109 template <TInt BPP, TInt BPP_DEST> 
       
   110 TUint8* TScanLineDecompressor<BPP, BPP_DEST>::CalcDestPtrLimit(const TUint8* aDestPtr, 
       
   111 													 const TPoint& aPixel, TInt aByteWidth, 
       
   112 													 TInt aLength, TInt aStartPos) const
       
   113 	{
       
   114 	return const_cast <TUint8*> (aDestPtr + CalcEndPos(aLength, aPixel, aByteWidth) - aStartPos);
       
   115 	}
       
   116 
       
   117 /**
       
   118 The method performs a quick find of the correct start position.
       
   119 It uses the fact that aLineScanPos parameter should be recalculated after each positioning 
       
   120 in the compresed bitmap data and might be used in the next call of decompression methods.
       
   121 @internalComponent
       
   122 @param aLineScanPos Saved information about the last used position in the compressed data
       
   123 @param aByteWidth Scanline width in bytes
       
   124 @param aStartPos CalcStartPos() method return value.
       
   125 @return A pointer to a position in compressed bitmap data, where the decompression  
       
   126 starts from
       
   127 @see CalcStartPos
       
   128 */
       
   129 template <TInt BPP, TInt BPP_DEST> 
       
   130 TUint8* TScanLineDecompressor<BPP, BPP_DEST>::AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos, 
       
   131 															   TInt aByteWidth, 
       
   132 															   TInt aStartPos) const
       
   133 	{
       
   134 	TUint8* srcPtr = NULL;
       
   135 	// Fast find the correct position to start	
       
   136 	if(iCanAdjustLineScanPos)
       
   137 		{
       
   138 		::AdjustLineScanningPosition(aLineScanPos, iBase, aByteWidth, aStartPos, iComprDataBytes);
       
   139 		}
       
   140 	srcPtr = aLineScanPos.iSrcDataPtr;
       
   141 	//Unfortunatelly we can't move fast srcPtr if aLineScanPos.iCursorPos > aStartPos, 
       
   142 	//because we have 1 byte for the compressed data length and the data itself after the "length"
       
   143 	//byte. With this information we can move srcPtr forward, not backward.
       
   144 	if(aLineScanPos.iCursorPos > aStartPos) 
       
   145 		{
       
   146 		srcPtr = (TUint8*)iBase;
       
   147 		aLineScanPos.iCursorPos = 0;
       
   148 		}
       
   149 	TInt count = TInt8(*srcPtr);//pixels count
       
   150 	TInt length = (count < 0 ? -count : count + 1) * BPP;//length in bytes
       
   151 	//If count < 0 - we have a sequence of abs(count) pixels - abs(count) * BPP bytes
       
   152 	//If count >= 0 - we have (count + 1) pixels with the same color - (count + 1) * BPP bytes
       
   153 	while((aLineScanPos.iCursorPos + length) <= aStartPos)
       
   154 		{
       
   155 		srcPtr += count < 0 ? length + 1 : (BPP + 1);//(BPP + 1) - bytes for the pixel + 1 byte for the length
       
   156 		aLineScanPos.iCursorPos += length;
       
   157 		count = TInt8(*srcPtr);
       
   158 		length = (count < 0 ? -count : count + 1) * BPP;
       
   159 		}
       
   160 	//After executing of the previous "if" operator and "while" loop, srcPtr points to 
       
   161 	//the nearest "length" byte before the start position in compressed bitmap data.
       
   162 	return srcPtr;
       
   163 	}
       
   164 
       
   165 /**
       
   166 This overloaded "()" operator used for decompression of bitmap scan lines.
       
   167 @internalComponent
       
   168 @param aDestBuffer Points to the destination buffer. After the call it fill be filled
       
   169 with the decomperssed data.
       
   170 @param aPixel The decompression starts from this pixel
       
   171 @param aLineScanPos Saved information about the last used position in the compressed data
       
   172 @param aByteWidth Scanline width in bytes
       
   173 @param aLength Length of requested decompressed data - in pixels
       
   174 */
       
   175 template <TInt BPP, TInt BPP_DEST> 
       
   176 void TScanLineDecompressor<BPP, BPP_DEST>::operator()(TUint8* aDestBuffer, const TPoint& aPixel, 
       
   177 											TLineScanningPosition& aLineScanPos, 
       
   178 											TInt aByteWidth, TInt aDestByteWidth, TInt aLength) const
       
   179 	{
       
   180 	TInt startPos = CalcStartPos(aPixel, aByteWidth);
       
   181 	TInt destStartPos = CalcDestStartPos(aPixel, aDestByteWidth);
       
   182 	TUint8* destPtr = CalcDestPtr(aDestBuffer, aPixel);
       
   183 	const TUint8* destPtrLimit = CalcDestPtrLimit(destPtr, aPixel, aDestByteWidth, aLength, destStartPos);
       
   184 	//Fast find the correct position to start	
       
   185 	TUint8* srcPtr = AdjustLineScanningPosition(aLineScanPos, aByteWidth, startPos);
       
   186 	//Decompress each slot of compressed data which has the following format:
       
   187 	// ...|"length byte"| "pixel value(s)" |...
       
   188 	while(destPtr < destPtrLimit)
       
   189 		{
       
   190 		TInt pixelsInTheSlot = TInt8(*srcPtr++);
       
   191 		TInt availDestSpaceInBytes = destPtrLimit - destPtr;
       
   192 		TInt skipBytes = startPos - aLineScanPos.iCursorPos;
       
   193 		if(pixelsInTheSlot < 0)
       
   194 			{//a sequence of abs(pixelsInTheSlot) pixels with different color values
       
   195 			TInt bytesInTheSlot = -pixelsInTheSlot * BPP;
       
   196 			TUint8* start_pos = srcPtr;
       
   197 			TInt bytesToCopy = bytesInTheSlot;
       
   198 			if(skipBytes > 0) //Skip the pixels before the start possition
       
   199 				{
       
   200 				bytesToCopy -= skipBytes;
       
   201 				start_pos += skipBytes;
       
   202 				}
       
   203 			if(BPP == BPP_DEST)
       
   204 				{
       
   205 				destPtr = Mem::Copy(destPtr, start_pos, ::Min(bytesToCopy, availDestSpaceInBytes));
       
   206 				}
       
   207 			else
       
   208 				{
       
   209 				destPtr = CopyBlockPixel(destPtr, start_pos, ::Min(bytesToCopy / BPP, availDestSpaceInBytes / BPP_DEST));
       
   210 				}	
       
   211 			//Move to the next "length" byte only if everything, 
       
   212 			//controlled by the current "length" byte, is copied
       
   213 			if((bytesToCopy / BPP) <= (availDestSpaceInBytes / BPP_DEST))
       
   214 				{
       
   215 				srcPtr += bytesInTheSlot;
       
   216 				aLineScanPos.iCursorPos += bytesInTheSlot;
       
   217 				}
       
   218 			else
       
   219 				{
       
   220 				srcPtr--;
       
   221 				}
       
   222 			}
       
   223 		else//the "else" part of - if(pixelsInTheSlot < 0)
       
   224 			{//(pixelsInTheSlot + 1) pixels with the same color
       
   225 			TInt pixelsToCopy = pixelsInTheSlot + 1;
       
   226 			TInt bytesInTheSlot = pixelsToCopy * BPP;
       
   227 			if(skipBytes > 0) //Skip the pixels before the start possition
       
   228 				{
       
   229 				pixelsToCopy -= skipBytes / BPP;
       
   230 				}
       
   231 			destPtr = CopyPixel(destPtr, srcPtr, ::Min(pixelsToCopy, availDestSpaceInBytes / BPP_DEST));
       
   232 			//Move to the next "length" byte only if everything, 
       
   233 			//controlled by the current "length" byte, is copied
       
   234 			if((pixelsToCopy * BPP) <= availDestSpaceInBytes)
       
   235 				{
       
   236 				srcPtr += BPP;// += BPP - we have (count + 1) pixels with the same color - only BPP bytes are used.
       
   237 				aLineScanPos.iCursorPos += bytesInTheSlot;
       
   238 				}
       
   239 			else
       
   240 				{
       
   241 				srcPtr--;
       
   242 				}
       
   243 			}//end of - if(pixelsCnt < 0)
       
   244 		}//end of - while(destPtr < destPtrLimit)
       
   245 	aLineScanPos.iSrcDataPtr = srcPtr;//update aLineScanPos.iSrcDataPtr - it will be used 
       
   246 									  //when the method is called again.
       
   247 	}
       
   248 
       
   249