|
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 |