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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 The created class instance doesn't take the ownership on aBase parameter.
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);
27 template <TInt BPP, TInt BPP_DEST>
28 TScanLineDecompressor<BPP, BPP_DEST>::TScanLineDecompressor(const TUint32* aBase,
30 TBool aCanAdjustLineScanPos) :
32 iComprDataBytes(aComprDataBytes),
33 iCanAdjustLineScanPos(aCanAdjustLineScanPos)
38 The method calculates the start byte position (as a index) in decompressed bitmap data .
40 @param aPixel The decompression starts from this pixel
41 @param aByteWidth Scanline width in bytes
42 @return Calculated start position.
44 template <TInt BPP, TInt BPP_DEST>
45 TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcStartPos(const TPoint& aPixel, TInt aByteWidth) const
47 return aPixel.iY * aByteWidth + aPixel.iX * BPP;
51 The method calculates the start byte position (as a index) in decompressed bitmap data .
53 @param aPixel The decompression starts from this pixel
54 @param aByteWidth Scanline width in bytes
55 @return Calculated start position.
57 template <TInt BPP, TInt BPP_DEST>
58 TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcDestStartPos(const TPoint& aPixel, TInt aByteWidth) const
60 return aPixel.iY * aByteWidth + aPixel.iX * BPP_DEST;
64 The method calculates the end byte position (as a index) in decompressed bitmap data .
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.
71 template <TInt BPP, TInt BPP_DEST>
72 TInt TScanLineDecompressor<BPP, BPP_DEST>::CalcEndPos(TInt aLength, const TPoint& aPixel,
73 TInt aByteWidth) const
75 return aPixel.iY * aByteWidth + (aPixel.iX + aLength) * BPP_DEST;
79 The method calculates a pointer to a place in aDestBuffer where the
80 copying of decompressed bitmap data starts.
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.
87 template <TInt BPP, TInt BPP_DEST>
88 TUint8* TScanLineDecompressor<BPP, BPP_DEST>::CalcDestPtr(const TUint8* aDestBuffer,
89 const TPoint& aPixel) const
91 return const_cast <TUint8*> (aDestBuffer + aPixel.iX * BPP_DEST);
95 The method calculates a pointer to a place in aDestBuffer where the copying
96 of the decompressed data stops.
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.
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
114 return const_cast <TUint8*> (aDestPtr + CalcEndPos(aLength, aPixel, aByteWidth) - aStartPos);
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.
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
129 template <TInt BPP, TInt BPP_DEST>
130 TUint8* TScanLineDecompressor<BPP, BPP_DEST>::AdjustLineScanningPosition(TLineScanningPosition& aLineScanPos,
132 TInt aStartPos) const
134 TUint8* srcPtr = NULL;
135 // Fast find the correct position to start
136 if(iCanAdjustLineScanPos)
138 ::AdjustLineScanningPosition(aLineScanPos, iBase, aByteWidth, aStartPos, iComprDataBytes);
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)
146 srcPtr = (TUint8*)iBase;
147 aLineScanPos.iCursorPos = 0;
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)
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;
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.
166 This overloaded "()" operator used for decompression of bitmap scan lines.
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
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
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)
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
200 bytesToCopy -= skipBytes;
201 start_pos += skipBytes;
205 destPtr = Mem::Copy(destPtr, start_pos, ::Min(bytesToCopy, availDestSpaceInBytes));
209 destPtr = CopyBlockPixel(destPtr, start_pos, ::Min(bytesToCopy / BPP, availDestSpaceInBytes / BPP_DEST));
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))
215 srcPtr += bytesInTheSlot;
216 aLineScanPos.iCursorPos += bytesInTheSlot;
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
229 pixelsToCopy -= skipBytes / BPP;
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)
236 srcPtr += BPP;// += BPP - we have (count + 1) pixels with the same color - only BPP bytes are used.
237 aLineScanPos.iCursorPos += bytesInTheSlot;
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.