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 +