os/graphics/fbs/fontandbitmapserver/sfbs/BitmapCompr.inl
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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