|
1 /* |
|
2 * Copyright (c) 2009 Sony Ericsson Mobile Communications AB |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Sony Ericsson Mobile Communications AB - initial contribution. |
|
11 * Nokia Corporation - additional changes. |
|
12 * |
|
13 * Contributors: |
|
14 * |
|
15 * Description: |
|
16 * Implements the Enhanced SMS Animation Information Element. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 /** |
|
22 * @file |
|
23 * |
|
24 * Implements CEmsPreDefAnimationIE and CEmsAnimationIE classes |
|
25 */ |
|
26 |
|
27 #include <emsanimationie.h> |
|
28 #include <w32std.h> |
|
29 |
|
30 /** |
|
31 * Creates a new Predifined animation class. |
|
32 * @param aAnimValue number of the predefined animations |
|
33 */ |
|
34 EXPORT_C CEmsPreDefAnimationIE* CEmsPreDefAnimationIE::NewL(TAnimType aAnimValue) |
|
35 /** |
|
36 * @capability None |
|
37 */ |
|
38 { |
|
39 if(aAnimValue > EDevil)User::Leave(KErrArgument); |
|
40 CEmsPreDefAnimationIE* self = new (ELeave) CEmsPreDefAnimationIE(aAnimValue); |
|
41 return self; |
|
42 } |
|
43 |
|
44 EXPORT_C CEmsInformationElement* CEmsPreDefAnimationIE::DuplicateL() const |
|
45 /** |
|
46 * @capability None |
|
47 */ |
|
48 { |
|
49 CEmsPreDefAnimationIE* copy = new (ELeave) CEmsPreDefAnimationIE(); |
|
50 CleanupStack::PushL(copy); |
|
51 copy->CopyL(*this); |
|
52 CleanupStack::Pop(copy); |
|
53 return copy; |
|
54 } |
|
55 |
|
56 EXPORT_C void CEmsPreDefAnimationIE::CopyL(const CEmsPreDefAnimationIE& aSrc) |
|
57 /** |
|
58 * @capability None |
|
59 */ |
|
60 { |
|
61 CEmsInformationElement::CopyL(aSrc); |
|
62 iAnimNumber = aSrc.iAnimNumber; |
|
63 } |
|
64 |
|
65 EXPORT_C CEmsPreDefAnimationIE::TAnimType CEmsPreDefAnimationIE::Animation() const |
|
66 /** |
|
67 * @capability None |
|
68 */ |
|
69 { |
|
70 return iAnimNumber; |
|
71 } |
|
72 |
|
73 EXPORT_C void CEmsPreDefAnimationIE::SetAnimationL(TAnimType aValue) |
|
74 /** |
|
75 * @capability None |
|
76 */ |
|
77 { |
|
78 if(aValue > EDevil)User::Leave(KErrArgument); |
|
79 iAnimNumber = aValue; |
|
80 } |
|
81 |
|
82 |
|
83 CEmsPreDefAnimationIE::CEmsPreDefAnimationIE(TAnimType aAnimValue) : |
|
84 CEmsInformationElement(CSmsInformationElement::ESmsEnhancedPredefinedAnimation), iAnimNumber(aAnimValue) |
|
85 { |
|
86 iEncodedBodyLength=EIESize; |
|
87 } |
|
88 |
|
89 CEmsPreDefAnimationIE::CEmsPreDefAnimationIE() : |
|
90 CEmsInformationElement(CSmsInformationElement::ESmsEnhancedPredefinedAnimation) |
|
91 { |
|
92 iEncodedBodyLength=EIESize; |
|
93 } |
|
94 |
|
95 /** |
|
96 * Encodes the raw Ems information element into a data buffer that can be use to create a normal information element. |
|
97 * |
|
98 * @param aPtr the buffer to be used which is to contain the data |
|
99 * @param TBool boolean to indicate if it is for serialisation or encoding |
|
100 */ |
|
101 void CEmsPreDefAnimationIE::EncodeBodyL(TPtr8 aPtr, TBool) const |
|
102 { |
|
103 // We don't need to worry about the aIsForSerialisation flag since |
|
104 // encoding and serialisation will result in the same data |
|
105 aPtr.Append(static_cast<TUint8>(iAnimNumber)); |
|
106 } |
|
107 |
|
108 /** |
|
109 * Decodes the raw data out of an information element into this class. |
|
110 * |
|
111 * @param aPtr The raw predefined animation data |
|
112 * @param TBool boolean to indicate if it is from serialisation |
|
113 * @leave KErrargument If the size of the data does not match what is expected. |
|
114 */ |
|
115 void CEmsPreDefAnimationIE::DecodeBodyL(const TPtrC8 aPtr, TBool) |
|
116 { |
|
117 __ASSERT_ALWAYS(aPtr.Length()==EIESize, User::Leave(KErrArgument)); |
|
118 iAnimNumber = static_cast<TAnimType>(aPtr[0]); |
|
119 __ASSERT_DEBUG(iAnimNumber<=EDevil, User::Leave(KErrArgument)); |
|
120 } |
|
121 |
|
122 // -------------------------------------------------------------------------------------------- |
|
123 |
|
124 /** |
|
125 * Creates a new of an animation object. |
|
126 * |
|
127 * @return CEmsAnimationIE* the newly created object. |
|
128 */ |
|
129 CEmsAnimationIE* CEmsAnimationIE::NewL() |
|
130 { |
|
131 CEmsAnimationIE* self = new (ELeave) CEmsAnimationIE(); |
|
132 return self; |
|
133 } |
|
134 |
|
135 /** |
|
136 * Creates a new EMS animation object from a given bitmap |
|
137 * |
|
138 * @param aBitmap a 4 frame Bitmap that is converted into an EMS animation type. |
|
139 * @return CEmsAnimationIE* the newly created object. |
|
140 * @leave KErrTooBig if the animation does not match the size of a Small/Large animation. |
|
141 */ |
|
142 EXPORT_C CEmsAnimationIE* CEmsAnimationIE::NewL(const CFbsBitmap& aBitmap) |
|
143 /** |
|
144 * @capability None |
|
145 */ |
|
146 { |
|
147 CEmsAnimationIE* self = new (ELeave) CEmsAnimationIE(); |
|
148 CleanupStack::PushL(self); |
|
149 self->ConstructL(aBitmap); |
|
150 CleanupStack::Pop(self); |
|
151 return self; |
|
152 } |
|
153 |
|
154 /** |
|
155 * Creates a Copy of the object. |
|
156 * |
|
157 * @return CEmsAnimationIE* the newly created object. |
|
158 */ |
|
159 EXPORT_C CEmsInformationElement* CEmsAnimationIE::DuplicateL() const |
|
160 /** |
|
161 * @capability None |
|
162 */ |
|
163 { |
|
164 CEmsAnimationIE* copy = new (ELeave) CEmsAnimationIE(); |
|
165 CleanupStack::PushL(copy); |
|
166 copy->CopyL(*this); |
|
167 CleanupStack::Pop(copy); |
|
168 return copy; |
|
169 } |
|
170 |
|
171 /** |
|
172 * Copys the information element out of the source into this object. |
|
173 * |
|
174 * @param aSrc the source object to copy from. |
|
175 */ |
|
176 EXPORT_C void CEmsAnimationIE::CopyL(const CEmsAnimationIE& aSrc) |
|
177 /** |
|
178 * @capability None |
|
179 */ |
|
180 { |
|
181 __ASSERT_ALWAYS(aSrc.iData, User::Leave(KErrCorrupt)); |
|
182 CEmsInformationElement::CopyL(aSrc); |
|
183 delete iData; |
|
184 iData=NULL; |
|
185 iData = aSrc.iData->AllocL(); |
|
186 } |
|
187 |
|
188 CEmsAnimationIE::CEmsAnimationIE() : CEmsInformationElement(CSmsInformationElement::ESmsEnhancedLargeAnimation) {}; |
|
189 |
|
190 EXPORT_C CEmsAnimationIE::~CEmsAnimationIE() |
|
191 /** |
|
192 * @capability None |
|
193 */ |
|
194 { |
|
195 delete iData; |
|
196 } |
|
197 |
|
198 /** |
|
199 * Constructs the object from the given FbsBitmap |
|
200 * Will convert colour bitmaps into the correct format. |
|
201 * |
|
202 * @see |
|
203 * @param aBitmap the source bitmap containing the 4 frames. |
|
204 * @leave KErrTooBig if the animation will not fit within a single pdu. |
|
205 * @leave KErrTooBig if the animation is not one of the Two animation sizes. |
|
206 */ |
|
207 void CEmsAnimationIE::ConstructL(const CFbsBitmap& aBitmap) |
|
208 { |
|
209 __ASSERT_ALWAYS(aBitmap.SizeInPixels().iWidth%8==0, User::Leave(KErrCorrupt)); |
|
210 |
|
211 TSize frameSize = aBitmap.SizeInPixels(); |
|
212 |
|
213 //////////////////////////////////////////////////// |
|
214 |
|
215 frameSize.iWidth /= EFramesPerMsg; |
|
216 __ASSERT_ALWAYS(frameSize==KSmallAnimSize || frameSize==KLargeAnimSize, User::Leave(KErrTooBig)); |
|
217 if(frameSize==KSmallAnimSize) |
|
218 { |
|
219 iEncodedBodyLength = EIESmallSize; |
|
220 } |
|
221 else |
|
222 { |
|
223 iEncodedBodyLength = EIELargeSize; |
|
224 } |
|
225 |
|
226 iIdentifier = (frameSize == KSmallAnimSize) ? CSmsInformationElement::ESmsEnhancedSmallAnimation : CSmsInformationElement::ESmsEnhancedLargeAnimation; |
|
227 |
|
228 |
|
229 iData = HBufC8::NewL(frameSize.iWidth*frameSize.iHeight/2); // div PixelsPerByte * NumFrames = /2 |
|
230 |
|
231 CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; |
|
232 CleanupStack::PushL(bitmap); |
|
233 User::LeaveIfError(bitmap->Create(frameSize, EGray2)); |
|
234 |
|
235 // create an off-screen device and context |
|
236 CGraphicsContext* bitGc; |
|
237 CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(bitmap); |
|
238 CleanupStack::PushL(dev); |
|
239 User::LeaveIfError(dev->CreateContext(bitGc)); |
|
240 CleanupStack::PushL(bitGc); |
|
241 |
|
242 for (TInt frame=0; frame<EFramesPerMsg; ++frame) |
|
243 { |
|
244 TRect srcRect(TPoint(0,0),frameSize); |
|
245 TRect dstRect(TPoint(frameSize.iWidth*frame,0), frameSize); |
|
246 bitGc->DrawBitmap(srcRect, &aBitmap, dstRect); |
|
247 HBufC8* pictureData = CEmsPictureIE::CreatePictureBufferL(*bitmap); |
|
248 CleanupStack::PushL(pictureData); |
|
249 iData->Des().Append(*pictureData); |
|
250 CleanupStack::PopAndDestroy(pictureData); |
|
251 } |
|
252 |
|
253 CleanupStack::PopAndDestroy(3, bitmap); |
|
254 } |
|
255 |
|
256 /** |
|
257 * Encodes the animation object into its raw format. (no IE id) |
|
258 * |
|
259 * @param aPtr the buffer to be used which is to contain the data |
|
260 * @param TBool boolean to indicate if it is for serialisation or encoding |
|
261 */ |
|
262 void CEmsAnimationIE::EncodeBodyL(TPtr8 aPtr, TBool) const |
|
263 { |
|
264 aPtr.Append(*iData); |
|
265 } |
|
266 |
|
267 /** |
|
268 * Decodes the raw data out of an information element into this class. |
|
269 * |
|
270 * @param aPtr The raw predefined animation data |
|
271 * @param TBool boolean to indicate if it is from serialisation |
|
272 * @leave KErrargument If the size of the data does not match what is expected. |
|
273 */ |
|
274 void CEmsAnimationIE::DecodeBodyL(const TPtrC8 aPtr, TBool) |
|
275 { |
|
276 __ASSERT_ALWAYS(aPtr.Length()==EIESmallSize || aPtr.Length()==EIELargeSize, User::Leave(KErrCorrupt)); |
|
277 |
|
278 delete iData; |
|
279 iData = NULL; |
|
280 iData = aPtr.AllocL(); |
|
281 } |
|
282 |
|
283 |
|
284 EXPORT_C CFbsBitmap* CEmsAnimationIE::GetBitmapL() const |
|
285 /** |
|
286 * @capability None |
|
287 */ |
|
288 { |
|
289 TSize size; |
|
290 if (iData->Length()==EIESmallSize) |
|
291 size = KSmallAnimSize; |
|
292 else |
|
293 size = KLargeAnimSize; |
|
294 //////////////////////////////////// |
|
295 __ASSERT_ALWAYS(size.iWidth*size.iHeight*EFramesPerMsg==iData->Length()*8, User::Leave(KErrCorrupt)); |
|
296 TInt frameDataLength = iData->Length()/EFramesPerMsg; |
|
297 |
|
298 CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; |
|
299 CleanupStack::PushL(bitmap); |
|
300 User::LeaveIfError(bitmap->Create(TSize(size.iWidth*EFramesPerMsg, size.iHeight), EGray2)); |
|
301 |
|
302 // create an off-screen device and context |
|
303 CFbsBitGc* bitGc; |
|
304 CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(bitmap); |
|
305 CleanupStack::PushL(dev); |
|
306 User::LeaveIfError(dev->CreateContext(bitGc)); |
|
307 CleanupStack::PushL(bitGc); |
|
308 |
|
309 bitGc->SetBrushColor(KRgbBlack); |
|
310 bitGc->SetPenColor(KRgbBlack); |
|
311 bitGc->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
312 bitGc->SetDrawMode(CGraphicsContext::EDrawModePEN); |
|
313 |
|
314 // Draw all frames into the master bitmap |
|
315 for (TInt frame=0; frame<EFramesPerMsg; frame++) |
|
316 { |
|
317 TPtrC8 frameData(iData->Mid(frame*frameDataLength, frameDataLength)); |
|
318 |
|
319 CFbsBitmap* pic; |
|
320 pic = GetBitmapL(size, frameData); |
|
321 |
|
322 TPoint topLeft(size.iWidth*frame,0); |
|
323 bitGc->BitBlt(topLeft,pic); |
|
324 delete pic; |
|
325 }; |
|
326 |
|
327 CleanupStack::PopAndDestroy(2, dev); |
|
328 CleanupStack::Pop(bitmap); |
|
329 return bitmap; |
|
330 } |
|
331 |
|
332 CFbsBitmap* CEmsAnimationIE::GetBitmapL(const TSize& aSize, const TDesC8& aDataBuf)const |
|
333 { |
|
334 // bitmap must have a width that is a x of 8. |
|
335 __ASSERT_ALWAYS(aSize.iWidth%8==0, User::Leave(KErrCorrupt)); |
|
336 CFbsBitmap* bitmap = new (ELeave) CFbsBitmap(); |
|
337 CleanupStack::PushL(bitmap); |
|
338 |
|
339 TInt numLineBytes = aSize.iWidth/8; |
|
340 User::LeaveIfError(bitmap->Create(aSize,EGray2)); |
|
341 |
|
342 HBufC8* working = HBufC8::NewLC(numLineBytes); |
|
343 |
|
344 TPtr8 convertedScanLine(working->Des()); |
|
345 convertedScanLine.SetLength(numLineBytes); |
|
346 |
|
347 |
|
348 TUint8 byte = 0; |
|
349 const TUint8* adr=NULL; |
|
350 |
|
351 for (TInt line =0; line < aSize.iHeight; line++) |
|
352 { |
|
353 adr = &(aDataBuf[(numLineBytes) * line]); |
|
354 TPtrC8 scanLine(adr, numLineBytes); |
|
355 |
|
356 for (TInt word=0; word<numLineBytes; word++) |
|
357 { |
|
358 // Convert EMS Black=1 to Epoc Black=0 |
|
359 // and Convert little endean to big. |
|
360 byte = 0; |
|
361 for (TInt bit=0; bit<8; bit++) |
|
362 byte |= (scanLine[word] & (1<<bit)) ? 0 : (1<<(7-bit)); |
|
363 |
|
364 convertedScanLine[word] = byte; |
|
365 } |
|
366 |
|
367 bitmap->SetScanLine(convertedScanLine, line); |
|
368 } |
|
369 |
|
370 CleanupStack::PopAndDestroy(working); |
|
371 CleanupStack::Pop(bitmap); |
|
372 return bitmap; |
|
373 } |