38 TRequestStatus* iRequestStatus; |
38 TRequestStatus* iRequestStatus; |
39 TInt iBitmapHandle; |
39 TInt iBitmapHandle; |
40 TInt iMaskHandle; |
40 TInt iMaskHandle; |
41 }; |
41 }; |
42 |
42 |
|
43 enum DecoderState {ENewDecodeRequest, EDecodeInProgress, EDecoderIdle}; |
43 class CSynDecoder : public CActive |
44 class CSynDecoder : public CActive |
44 { |
45 { |
45 public: // Constructors and destructor |
46 public: // Constructors and destructor |
46 static CSynDecoder* NewL(); |
47 static CSynDecoder* NewL(); |
47 virtual ~CSynDecoder(); |
48 virtual ~CSynDecoder(); |
48 |
49 |
49 public: |
50 public: |
50 TInt Open(BmElem* aElem); |
51 void Open(const TDesC8& aData, TRequestStatus *status); |
|
52 void Lock() { iDecoderLock.Wait(); } |
|
53 void Release() { iDecoderLock.Signal(); } |
51 |
54 |
52 private: // From base class CActive |
55 private: // From base class CActive |
53 void DoCancel(); |
56 void DoCancel(); |
54 void RunL(); |
57 void RunL(); |
55 TInt RunError( TInt aError ); |
58 TInt RunError( TInt aError ); |
56 void SignalParent( TInt aError ); |
59 void SignalParent( TInt aError ); |
|
60 void StartDecodeL(); |
|
61 void SetIdle(); |
57 |
62 |
58 private: // Private constructors |
63 private: // Private constructors |
59 CSynDecoder(); |
64 CSynDecoder(); |
60 void ConstructL() {} |
65 void ConstructL(); |
61 |
66 |
62 private: // Data |
67 private: // Data |
63 BmElem* iElem; // not owned |
68 BmElem iElem; |
64 CImageDecoder* iDecoder; // owned |
69 CImageDecoder* iDecoder; |
65 CMaskedBitmap* iBitmap; // owned |
70 CMaskedBitmap* iBitmap; |
|
71 RFastLock iDecoderLock; |
|
72 DecoderState iDecodeState; |
|
73 RThread syncThread; |
|
74 |
|
75 friend class CSynDecodeThread; |
66 }; |
76 }; |
67 |
77 |
68 // FORWARD DECLARATIONS |
78 // FORWARD DECLARATIONS |
|
79 CSynDecoder *CSynDecodeThread::iSyncDecoder = NULL; |
69 |
80 |
70 // ============================= LOCAL FUNCTIONS =============================== |
81 // ============================= LOCAL FUNCTIONS =============================== |
71 |
82 |
72 // ============================ MEMBER FUNCTIONS =============================== |
83 // ============================ MEMBER FUNCTIONS =============================== |
73 // ----------------------------------------------------------------------------- |
84 // ----------------------------------------------------------------------------- |
92 CSynDecoder::~CSynDecoder() |
109 CSynDecoder::~CSynDecoder() |
93 { |
110 { |
94 Cancel(); |
111 Cancel(); |
95 delete iDecoder; |
112 delete iDecoder; |
96 delete iBitmap; |
113 delete iBitmap; |
97 } |
114 iDecoderLock.Close(); |
98 |
115 } |
99 // ----------------------------------------------------------------------------- |
116 |
100 // OpenL |
117 // ----------------------------------------------------------------------------- |
101 // ----------------------------------------------------------------------------- |
118 // Decode - Decode request submitted from client thread |
102 TInt CSynDecoder::Open(BmElem* aElem) |
119 // ----------------------------------------------------------------------------- |
103 { |
120 void CSynDecoder::Open(const TDesC8& aData, TRequestStatus *status) |
104 iElem = aElem; |
121 { |
105 // reset decoder |
122 iElem.iRequestStatus = status; |
106 TRAPD( err, |
123 iElem.iData.Set(aData); |
107 iDecoder = CImageDecoder::DataNewL(CEikonEnv::Static()->FsSession(), iElem->iData); |
124 iElem.iParentThreadId = RThread().Id(); |
108 iBitmap = CMaskedBitmap::NewL(); |
125 iElem.iBitmapHandle = 0; |
109 ); |
126 iElem.iMaskHandle = 0; |
110 if( err != KErrNone ) |
127 iDecodeState = ENewDecodeRequest; |
111 return err; |
128 } |
112 |
129 |
|
130 void CSynDecoder::SetIdle() |
|
131 { |
|
132 iDecodeState = EDecoderIdle; |
|
133 if(!IsActive()) { |
|
134 iStatus = KRequestPending; |
|
135 SetActive(); |
|
136 } |
|
137 } |
|
138 |
|
139 void CSynDecoder::StartDecodeL() |
|
140 { |
|
141 if(iDecoder) { |
|
142 delete iDecoder; |
|
143 iDecoder = NULL; |
|
144 } |
|
145 if(iBitmap) { |
|
146 delete iBitmap; |
|
147 iBitmap = NULL; |
|
148 } |
|
149 |
|
150 iDecoder = CImageDecoder::DataNewL(CEikonEnv::Static()->FsSession(), iElem.iData); |
|
151 iBitmap = CMaskedBitmap::NewL(); |
|
152 |
113 TFrameInfo frameInfo = iDecoder->FrameInfo( 0 ); |
153 TFrameInfo frameInfo = iDecoder->FrameInfo( 0 ); |
114 |
154 TInt err = KErrNone; |
115 if( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) { |
155 if( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) { |
116 TDisplayMode maskmode = (frameInfo.iFlags & TFrameInfo::EAlphaChannel) ? EGray256 : EGray2; |
156 TDisplayMode maskmode = (frameInfo.iFlags & TFrameInfo::EAlphaChannel) ? EGray256 : EGray2; |
117 |
|
118 err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K, maskmode ); |
157 err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K, maskmode ); |
119 } |
158 } |
120 else |
159 else |
121 err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K ); |
160 err = iBitmap->Create( frameInfo.iOverallSizeInPixels, EColor64K ); |
122 // |
161 User::LeaveIfError(err); |
123 if( err != KErrNone ) |
162 |
124 return err; |
163 // start decoding |
125 // start decoding |
|
126 CFbsBitmap& dstBitmap = iBitmap->BitmapModifyable(); |
164 CFbsBitmap& dstBitmap = iBitmap->BitmapModifyable(); |
127 CFbsBitmap& dstMask = iBitmap->MaskModifyable(); |
165 CFbsBitmap& dstMask = iBitmap->MaskModifyable(); |
128 |
|
129 if( ( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) && dstMask.Handle() ) |
166 if( ( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) && dstMask.Handle() ) |
130 iDecoder->Convert( &iStatus, dstBitmap, dstMask, 0 ); |
167 iDecoder->Convert( &iStatus, dstBitmap, dstMask, 0 ); |
131 else { |
168 else { |
132 dstMask.Reset(); |
169 dstMask.Reset(); |
133 iDecoder->Convert( &iStatus, dstBitmap, 0 ); |
170 iDecoder->Convert( &iStatus, dstBitmap, 0 ); |
134 } |
171 } |
|
172 |
|
173 iDecodeState = EDecodeInProgress; |
135 SetActive(); |
174 SetActive(); |
136 return KErrNone; |
|
137 } |
175 } |
138 |
176 |
139 // ----------------------------------------------------------------------------- |
177 // ----------------------------------------------------------------------------- |
140 // CSynDecoder::DoCancel |
178 // CSynDecoder::DoCancel |
141 // ----------------------------------------------------------------------------- |
179 // ----------------------------------------------------------------------------- |
142 void CSynDecoder::DoCancel() |
180 void CSynDecoder::DoCancel() |
143 { |
181 { |
144 iDecoder->Cancel(); |
182 iDecoder->Cancel(); |
145 SignalParent( KErrCancel ); |
183 SignalParent( KErrCancel ); |
|
184 SetIdle(); |
146 } |
185 } |
147 |
186 |
148 // ----------------------------------------------------------------------------- |
187 // ----------------------------------------------------------------------------- |
149 // CSynDecoder::RunL |
188 // CSynDecoder::RunL |
150 // ----------------------------------------------------------------------------- |
189 // ----------------------------------------------------------------------------- |
151 void CSynDecoder::RunL() |
190 void CSynDecoder::RunL() |
152 { |
191 { |
153 SignalParent( iStatus.Int() ); |
192 switch(iDecodeState) |
154 |
193 { |
155 if( iStatus.Int() == KErrNone ) { |
194 case ENewDecodeRequest: |
156 iElem->iBitmapHandle = iBitmap->Bitmap().Handle(); |
195 StartDecodeL(); // start async decode |
157 iElem->iMaskHandle = iBitmap->Mask().Handle(); |
196 break; |
158 |
197 case EDecodeInProgress: |
159 RThread self; |
198 if( iStatus.Int() == KErrNone ) { |
160 self.Suspend(); |
199 iElem.iBitmapHandle = iBitmap->Bitmap().Handle(); |
161 self.Close(); |
200 iElem.iMaskHandle = iBitmap->Mask().Handle(); |
162 // destroy |
201 } |
163 CActiveScheduler::Stop(); |
202 |
164 } |
203 SignalParent(iStatus.Int()); |
|
204 SetIdle(); |
|
205 break; |
|
206 default: |
|
207 SetIdle(); |
|
208 } |
165 } |
209 } |
166 |
210 |
167 // ----------------------------------------------------------------------------- |
211 // ----------------------------------------------------------------------------- |
168 // CSynDecoder::RunError |
212 // CSynDecoder::RunError |
169 // ----------------------------------------------------------------------------- |
213 // ----------------------------------------------------------------------------- |
170 TInt CSynDecoder::RunError(TInt aError) |
214 TInt CSynDecoder::RunError(TInt aError) |
171 { |
215 { |
172 SignalParent( aError ); |
216 SignalParent(aError); |
|
217 SetIdle(); |
173 return KErrNone; |
218 return KErrNone; |
174 } |
219 } |
175 |
220 |
176 // ----------------------------------------------------------------------------- |
221 // ----------------------------------------------------------------------------- |
177 // CSynDecoder::RunError |
222 // CSynDecoder::RunError |
178 // ----------------------------------------------------------------------------- |
223 // ----------------------------------------------------------------------------- |
179 void CSynDecoder::SignalParent(TInt aError) |
224 void CSynDecoder::SignalParent(TInt aError) |
180 { |
225 { |
181 RThread parent; |
226 RThread parent; |
182 parent.Open(iElem->iParentThreadId); |
227 parent.Open(iElem.iParentThreadId); |
183 parent.RequestComplete(iElem->iRequestStatus, aError ); |
228 parent.RequestComplete(iElem.iRequestStatus, aError ); |
184 parent.Close(); |
229 parent.Close(); |
185 |
230 } |
186 if (aError != KErrNone) |
231 |
187 CActiveScheduler::Stop(); |
|
188 } |
|
189 |
232 |
190 CSynDecodeThread* CSynDecodeThread::NewL() |
233 CSynDecodeThread* CSynDecodeThread::NewL() |
191 { |
234 { |
192 CSynDecodeThread* self = new (ELeave) CSynDecodeThread(); |
235 CSynDecodeThread* self = new (ELeave) CSynDecodeThread(); |
193 CleanupStack::PushL(self); |
236 CleanupStack::PushL(self); |
199 CSynDecodeThread::CSynDecodeThread() |
242 CSynDecodeThread::CSynDecodeThread() |
200 { |
243 { |
201 } |
244 } |
202 |
245 |
203 CSynDecodeThread::~CSynDecodeThread() |
246 CSynDecodeThread::~CSynDecodeThread() |
204 { |
247 { |
205 if(iUp) { |
248 CActiveScheduler::Stop(); |
206 iDecoderThread.Resume(); |
249 iDecoderThread.Close(); |
207 iDecoderThread.Kill(KErrNone); |
250 } |
208 iDecoderThread.Close(); |
|
209 } |
|
210 delete iElem; |
|
211 } |
|
212 |
|
213 |
251 |
214 void CSynDecodeThread::ConstructL() |
252 void CSynDecodeThread::ConstructL() |
215 { |
253 { |
216 } |
254 _LIT(KThreadName, "ImgDecoder"); |
217 |
255 User::LeaveIfError(iDecoderThread.Create(KThreadName, CSynDecodeThread::ScaleInThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, NULL)); |
218 TInt CSynDecodeThread::Decode(const TDesC8& aData, TRequestStatus* aRequestStatus) |
256 iDecoderThread.SetPriority(EPriorityMore); |
219 { |
257 TRequestStatus status = KRequestPending; |
220 iElem = new (ELeave) BmElem; |
258 iDecoderThread.Rendezvous(status); |
221 iElem->iData.Set( aData ); |
259 iDecoderThread.Resume(); |
222 iElem->iParentThreadId = RThread().Id(); |
260 User::WaitForRequest(status); |
223 iElem->iRequestStatus = aRequestStatus; |
261 User::LeaveIfError(status.Int()); |
224 |
262 } |
225 TBuf<20> randName; |
263 |
226 TTime t; |
264 |
227 t.HomeTime(); |
265 TInt CSynDecodeThread::Decode(const TDesC8& aData) |
228 randName.Num( I64INT(t.Int64()) ); |
266 { |
229 |
267 iSyncDecoder->Lock(); |
230 TInt err = iDecoderThread.Create(randName, CSynDecodeThread::ScaleInThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, iElem); |
268 |
231 if (err==KErrNone) { |
269 //notify decoder thread about new request |
232 iUp = ETrue; |
270 TRequestStatus status = KRequestPending; |
233 iDecoderThread.SetPriority(EPriorityMore); |
271 iSyncDecoder->Open(aData, &status); |
234 *aRequestStatus = KRequestPending; |
272 TRequestStatus *ps = &(iSyncDecoder->iStatus); |
235 iDecoderThread.Resume(); |
273 iDecoderThread.RequestComplete(ps, KErrNone); |
236 } |
274 |
237 return err; |
275 //wait for decode complete |
|
276 User::WaitForRequest(status); |
|
277 |
|
278 iSyncDecoder->Release(); |
|
279 return status.Int(); |
238 } |
280 } |
239 |
281 |
240 void CSynDecodeThread::Handle(TInt& aBitmapHandle, TInt& aMaskHandle) |
282 void CSynDecodeThread::Handle(TInt& aBitmapHandle, TInt& aMaskHandle) |
241 { |
283 { |
242 aBitmapHandle = iElem->iBitmapHandle; |
284 aBitmapHandle = iSyncDecoder->iElem.iBitmapHandle; |
243 aMaskHandle = iElem->iMaskHandle; |
285 aMaskHandle = iSyncDecoder->iElem.iMaskHandle; |
244 } |
286 } |
245 |
287 |
246 TInt CSynDecodeThread::ScaleInThread(TAny *aPtr) |
288 TInt CSynDecodeThread::ScaleInThread(TAny *aPtr) |
247 { |
289 { |
248 CTrapCleanup* cleanup = CTrapCleanup::New(); |
290 CTrapCleanup* cleanup = CTrapCleanup::New(); |
249 CActiveScheduler* as = new CActiveScheduler; |
291 CActiveScheduler* as = new CActiveScheduler; |
250 CActiveScheduler::Install(as); |
292 CActiveScheduler::Install(as); |
251 |
|
252 CSynDecoder* decoder = NULL; |
|
253 |
|
254 RFbsSession fbs; |
293 RFbsSession fbs; |
255 fbs.Connect(); |
294 fbs.Connect(); |
256 |
295 |
257 BmElem* elem = (BmElem*)aPtr; |
296 // start event loop |
258 TRAPD(err, decoder = CSynDecoder::NewL()); |
297 TRAPD(err, iSyncDecoder = CSynDecoder::NewL()); |
259 |
298 if (err == KErrNone) { |
260 if (err == KErrNone && (err = decoder->Open(elem))== KErrNone ) |
299 // wait for decode request from client threads |
261 CActiveScheduler::Start(); |
300 RThread().Rendezvous(KErrNone); |
262 else { |
301 CActiveScheduler::Start(); |
263 RThread parent; |
302 } |
264 parent.Open(elem->iParentThreadId); |
303 else { |
265 parent.RequestComplete(elem->iRequestStatus, err); |
304 RThread().Rendezvous(err); |
266 parent.Close(); |
305 } |
267 } |
306 |
268 |
307 // thread shutdown |
269 delete as; |
308 delete as; |
270 delete decoder; |
309 delete iSyncDecoder; |
271 delete cleanup; |
310 delete cleanup; |
272 fbs.Disconnect(); |
311 fbs.Disconnect(); |
273 return err; |
312 return err; |
274 } |
313 } |