|
1 /* |
|
2 * Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Provides moving layer(s) functionality. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include "AknsRlEffectPluginMovingLayers.h" |
|
21 |
|
22 // ================= INTERNAL IMPL. OF MOVING LAYERS =========================== |
|
23 class AknsRlMovingLayers |
|
24 { |
|
25 public: |
|
26 static void RenderTiled( CFbsBitGc& aBitGc, |
|
27 const TInt aX, const TInt aY, |
|
28 const TInt aW, const TInt aH, |
|
29 const CFbsBitmap& aBmp, |
|
30 const CFbsBitmap* aMask=NULL ) |
|
31 { |
|
32 if( 0 == aX && 0 == aY ) // Render 1:1 |
|
33 { |
|
34 if( aMask ) |
|
35 { |
|
36 aBitGc.BitBltMasked( TPoint( 0, 0 ), &aBmp, |
|
37 TRect( TPoint( 0, 0 ), |
|
38 TSize( aW, aH ) ), |
|
39 aMask, EFalse ); |
|
40 } |
|
41 else |
|
42 { |
|
43 aBitGc.BitBlt( TPoint( 0, 0 ), &aBmp, |
|
44 TRect( TPoint( 0, 0 ), |
|
45 TSize( aW, aH ) ) ); |
|
46 } |
|
47 } |
|
48 else // Draw tiled |
|
49 { |
|
50 /* |
|
51 Output Input |
|
52 --------- --------- |
|
53 |4' |3' | |1 |2 | |
|
54 |---o-----| | | | |
|
55 |2' |1' | | | | |
|
56 | | | | | | |
|
57 | | | |-----o---| |
|
58 | | | |3 |4 | |
|
59 --------- --------- |
|
60 |
|
61 Output rects: |
|
62 1' ( x, y, w - x, h - y ) |
|
63 2' ( 0, y, x, h - y ) |
|
64 3' ( x, 0, w - x, y ) |
|
65 4' ( 0, 0, x, y ) |
|
66 |
|
67 Input rects: |
|
68 1 ( 0, 0, w - x, h - y ) |
|
69 2 ( w - x, 0, x, h - y ) |
|
70 3 ( 0, h - y, w - x, y ) |
|
71 4 ( w - x, h - y, x, y ) |
|
72 |
|
73 */ |
|
74 TRect source; |
|
75 |
|
76 if( aMask ) |
|
77 { |
|
78 // Target top left ( 4 -> 4' ) |
|
79 source.SetRect( TPoint( aW - aX, aH - aY ), TSize( aX, aY ) ); |
|
80 aBitGc.BitBltMasked( TPoint( 0, 0 ), &aBmp, source, aMask, EFalse ); |
|
81 // Target top right ( 3 -> 3' ) |
|
82 source.SetRect( TPoint( 0, aH - aY ), TSize( aW - aX, aY ) ); |
|
83 aBitGc.BitBltMasked( TPoint( aX, 0 ), &aBmp, source, aMask, EFalse ); |
|
84 // Target bottom left ( 2 -> 2' ) |
|
85 source.SetRect( TPoint( aW - aX, 0 ), TSize( aX, aH - aY ) ); |
|
86 aBitGc.BitBltMasked( TPoint( 0, aY ), &aBmp, source, aMask, EFalse ); |
|
87 // Target bottom right ( 1 -> 1' ) |
|
88 source.SetRect( TPoint( 0, 0 ), TSize( aW - aX, aH - aY ) ); |
|
89 aBitGc.BitBltMasked( TPoint( aX, aY ), &aBmp, source, aMask, EFalse ); |
|
90 } |
|
91 else |
|
92 { |
|
93 // Target top left ( 4 -> 4' ) |
|
94 source.SetRect( TPoint( aW - aX, aH - aY ), TSize( aX, aY ) ); |
|
95 aBitGc.BitBlt( TPoint( 0, 0 ), &aBmp, source ); |
|
96 // Target top right ( 3 -> 3' ) |
|
97 source.SetRect( TPoint( 0, aH - aY ), TSize( aW - aX, aY ) ); |
|
98 aBitGc.BitBlt( TPoint( aX, 0 ), &aBmp, source ); |
|
99 // Target bottom left ( 2 -> 2' ) |
|
100 source.SetRect( TPoint( aW - aX, 0 ), TSize( aX, aH - aY ) ); |
|
101 aBitGc.BitBlt( TPoint( 0, aY ), &aBmp, source ); |
|
102 // Target bottom right ( 1 -> 1' ) |
|
103 source.SetRect( TPoint( 0, 0 ), TSize( aW - aX, aH - aY ) ); |
|
104 aBitGc.BitBlt( TPoint( aX, aY ), &aBmp, source ); |
|
105 } |
|
106 } |
|
107 } |
|
108 }; |
|
109 |
|
110 // ============================ MEMBER FUNCTIONS =============================== |
|
111 |
|
112 // ----------------------------------------------------------------------------- |
|
113 // CAknsRlEffectPluginMovingLayers::CAknsRlEffectPluginMovingLayers |
|
114 // C++ default constructor can NOT contain any code, that |
|
115 // might leave. |
|
116 // ----------------------------------------------------------------------------- |
|
117 // |
|
118 CAknsRlEffectPluginMovingLayers::CAknsRlEffectPluginMovingLayers() |
|
119 { |
|
120 } |
|
121 |
|
122 // ----------------------------------------------------------------------------- |
|
123 // Destructor |
|
124 // ----------------------------------------------------------------------------- |
|
125 // |
|
126 CAknsRlEffectPluginMovingLayers::~CAknsRlEffectPluginMovingLayers() |
|
127 { |
|
128 // The user of this plugin should call deactivate...but we ensure deletion |
|
129 // here (just in case). |
|
130 DeleteTempBitmap(); //lint !e1551 No exception thrown |
|
131 } |
|
132 |
|
133 // ----------------------------------------------------------------------------- |
|
134 // CAknsRlEffectPluginMovingLayers::EffectUid |
|
135 // ----------------------------------------------------------------------------- |
|
136 // |
|
137 TUid CAknsRlEffectPluginMovingLayers::EffectUid() const |
|
138 { |
|
139 return TUid::Uid( KAknsRlEffectPluginMovingLayersUID ); |
|
140 } |
|
141 |
|
142 // ----------------------------------------------------------------------------- |
|
143 // CAknsRlEffectPluginMovingLayers::Effect |
|
144 // ----------------------------------------------------------------------------- |
|
145 // |
|
146 MAknsRlEffect* CAknsRlEffectPluginMovingLayers::Effect( const TInt aInterface ) |
|
147 { |
|
148 if( aInterface == KAknsRlEffectPluginInterfaceEffect ) |
|
149 return this; |
|
150 return NULL; |
|
151 } |
|
152 |
|
153 // ----------------------------------------------------------------------------- |
|
154 // CAknsRlEffectPluginMovingLayers::InitializeL |
|
155 // ----------------------------------------------------------------------------- |
|
156 // |
|
157 void CAknsRlEffectPluginMovingLayers::InitializeL() |
|
158 { |
|
159 iContext = NULL; |
|
160 } |
|
161 |
|
162 // ----------------------------------------------------------------------------- |
|
163 // CAknsRlEffectPluginMovingLayers::Release |
|
164 // ----------------------------------------------------------------------------- |
|
165 // |
|
166 void CAknsRlEffectPluginMovingLayers::Release() |
|
167 { |
|
168 } |
|
169 |
|
170 // ----------------------------------------------------------------------------- |
|
171 // CAknsRlEffectPluginMovingLayers::ActivateL |
|
172 // ----------------------------------------------------------------------------- |
|
173 // |
|
174 void CAknsRlEffectPluginMovingLayers::ActivateL( MAknsRlEffectContext* aContext ) |
|
175 { |
|
176 if( !aContext ) // We absolutely need the context |
|
177 { |
|
178 User::Leave( KErrArgument ); |
|
179 } |
|
180 |
|
181 iContext = aContext; |
|
182 |
|
183 iAx = 0; |
|
184 iAy = 0; |
|
185 iBx = 0; |
|
186 iBy = 0; |
|
187 |
|
188 DeleteTempBitmap(); |
|
189 } |
|
190 |
|
191 // ----------------------------------------------------------------------------- |
|
192 // CAknsRlEffectPluginMovingLayers::Deactivate |
|
193 // ----------------------------------------------------------------------------- |
|
194 // |
|
195 void CAknsRlEffectPluginMovingLayers::Deactivate() |
|
196 { |
|
197 DeleteTempBitmap(); |
|
198 } |
|
199 |
|
200 // ----------------------------------------------------------------------------- |
|
201 // CAknsRlEffectPluginMovingLayers::SetParametersL |
|
202 // ----------------------------------------------------------------------------- |
|
203 // |
|
204 void CAknsRlEffectPluginMovingLayers::SetParametersL( MAknsRlParameterIterator& aParameters ) |
|
205 { |
|
206 // Iterate over available parameters |
|
207 while( aParameters.HasNext() ) |
|
208 { |
|
209 const TAknsRlParameterData* param = aParameters.NextL(); |
|
210 |
|
211 if( param->iName->Compare( KAknsRlEffectMovingLayersAX ) == 0 ) |
|
212 { |
|
213 if( param->iType != EAknsRlParameterTypeNumber ) |
|
214 User::Leave( KErrArgument ); |
|
215 |
|
216 iAx = param->iNumber; |
|
217 } |
|
218 else if( param->iName->Compare( KAknsRlEffectMovingLayersAY ) == 0 ) |
|
219 { |
|
220 if( param->iType != EAknsRlParameterTypeNumber ) |
|
221 User::Leave( KErrArgument ); |
|
222 |
|
223 iAy = param->iNumber; |
|
224 } |
|
225 else if( param->iName->Compare( KAknsRlEffectMovingLayersBX ) == 0 ) |
|
226 { |
|
227 if( param->iType != EAknsRlParameterTypeNumber ) |
|
228 User::Leave( KErrArgument ); |
|
229 |
|
230 iBx = param->iNumber; |
|
231 } |
|
232 else if( param->iName->Compare( KAknsRlEffectMovingLayersBY ) == 0 ) |
|
233 { |
|
234 if( param->iType != EAknsRlParameterTypeNumber ) |
|
235 User::Leave( KErrArgument ); |
|
236 |
|
237 iBy = param->iNumber; |
|
238 } |
|
239 else if( param->iName->Compare( KAknsRlEffectMovingLayersAXY ) == 0 ) |
|
240 { |
|
241 if( param->iType != EAknsRlParameterTypeString || !param->iString ) |
|
242 User::Leave( KErrArgument ); |
|
243 |
|
244 if( param->iString->Length() < 2 ) |
|
245 User::Leave( KErrArgument ); |
|
246 |
|
247 iAx = (*param->iString)[0]; |
|
248 iAy = (*param->iString)[1]; |
|
249 } |
|
250 else if( param->iName->Compare( KAknsRlEffectMovingLayersBXY ) == 0 ) |
|
251 { |
|
252 if( param->iType != EAknsRlParameterTypeString || !param->iString ) |
|
253 User::Leave( KErrArgument ); |
|
254 |
|
255 if( param->iString->Length() < 2 ) |
|
256 User::Leave( KErrArgument ); |
|
257 |
|
258 iBx = (*param->iString)[0]; |
|
259 iBy = (*param->iString)[1]; |
|
260 } |
|
261 } |
|
262 } |
|
263 |
|
264 // ----------------------------------------------------------------------------- |
|
265 // CAknsRlEffectPluginMovingLayers::GetCapabilities |
|
266 // ----------------------------------------------------------------------------- |
|
267 // |
|
268 void CAknsRlEffectPluginMovingLayers::GetCapabilities( TAknsRlEffectCaps& aCaps ) |
|
269 { |
|
270 aCaps.iOutputLayerSupport = KAknsRlLayerRGBOnly; |
|
271 aCaps.iInputLayerASupport = KAknsRlLayerRGBOnly; |
|
272 aCaps.iInputLayerBSupport = KAknsRlLayerNone | KAknsRlLayerRGBOnly | KAknsRlLayerRGBA; |
|
273 } |
|
274 |
|
275 // ----------------------------------------------------------------------------- |
|
276 // CAknsRlEffectPluginMovingLayers::Render |
|
277 // ----------------------------------------------------------------------------- |
|
278 // |
|
279 TInt CAknsRlEffectPluginMovingLayers::Render( const TAknsRlRenderOpParam& aParam ) |
|
280 { |
|
281 if( !iContext ) // We absolutely need the context |
|
282 { |
|
283 return KErrBadHandle; |
|
284 } |
|
285 |
|
286 TAknsRlLayerData dataT; |
|
287 TAknsRlLayerData dataA; |
|
288 TAknsRlLayerData dataB; |
|
289 |
|
290 // We need the output layer |
|
291 if( !( ( aParam.iOutputLayerStatus & KAknsRlLayerRGBOnly ) || |
|
292 ( aParam.iOutputLayerStatus & KAknsRlLayerRGBA ) ) ) |
|
293 return KErrArgument; // Output must be some sort of RGB layer |
|
294 |
|
295 TRAPD( err, iContext->GetLayerDataL( dataT, aParam.iOutputLayerIndex, |
|
296 aParam.iOutputLayerStatus, EFalse ) ); |
|
297 if( KErrNone != err ) |
|
298 return KErrArgument; |
|
299 |
|
300 if( !dataT.iRGBGc || !dataT.iRGBBitmap ) |
|
301 return KErrBadHandle; |
|
302 |
|
303 // We need the input layer A |
|
304 if( !( ( aParam.iInputLayerAStatus & KAknsRlLayerRGBOnly ) || |
|
305 ( aParam.iInputLayerAStatus & KAknsRlLayerRGBA ) ) ) |
|
306 return KErrArgument; // Input layer A must be some sort of RGB layer |
|
307 |
|
308 TRAP( err, iContext->GetLayerDataL( dataA, aParam.iInputLayerAIndex, |
|
309 aParam.iInputLayerAStatus, EFalse ) ); |
|
310 if( KErrNone != err ) |
|
311 return KErrArgument; |
|
312 |
|
313 if( !dataA.iRGBBitmap ) |
|
314 return KErrBadHandle; |
|
315 |
|
316 // Input layer B is optional |
|
317 if( ( aParam.iInputLayerBStatus & KAknsRlLayerRGBOnly ) || |
|
318 ( aParam.iInputLayerBStatus & KAknsRlLayerRGBA ) ) |
|
319 { |
|
320 // Input layer B is RGB layer |
|
321 TRAP( err, iContext->GetLayerDataL( dataB, aParam.iInputLayerBIndex, |
|
322 aParam.iInputLayerBStatus, EFalse ) ); |
|
323 if( KErrNone != err ) |
|
324 return KErrArgument; |
|
325 |
|
326 if( !dataB.iRGBBitmap ) |
|
327 return KErrBadHandle; |
|
328 } |
|
329 |
|
330 // If we got this far we have all the required devices for doing rendering. |
|
331 |
|
332 // Tiled rendering does not work correctly if one of the input layers is |
|
333 // the same as output layer. |
|
334 if( ( aParam.iInputLayerAIndex == aParam.iOutputLayerIndex && dataA.iRGBBitmap ) || |
|
335 ( aParam.iInputLayerBIndex == aParam.iOutputLayerIndex && dataB.iRGBBitmap ) ) |
|
336 { |
|
337 if( !iTempBitmap ) |
|
338 { |
|
339 err = CreateTempBitmap( *dataT.iRGBBitmap ); |
|
340 if( KErrNone != err ) |
|
341 return err; |
|
342 } |
|
343 else // Temp bitmap already exists |
|
344 { |
|
345 // Check if we can reuse the existing bitmap |
|
346 if( iTempBitmap->SizeInPixels() == dataT.iRGBBitmap->SizeInPixels() && |
|
347 iTempBitmap->DisplayMode() == dataT.iRGBBitmap->DisplayMode() ) |
|
348 { |
|
349 iTempContext->BitBlt( TPoint( 0, 0 ), dataT.iRGBBitmap ); |
|
350 } |
|
351 else |
|
352 { |
|
353 DeleteTempBitmap(); |
|
354 err = CreateTempBitmap( *dataT.iRGBBitmap ); |
|
355 if( KErrNone != err ) |
|
356 return err; |
|
357 } |
|
358 } |
|
359 } |
|
360 |
|
361 // Determine real coordinates (we do tiling) |
|
362 TSize size = iContext->LayerSize(); |
|
363 |
|
364 TInt ax = iAx % size.iWidth; |
|
365 TInt ay = iAy % size.iHeight; |
|
366 |
|
367 if( ax < 0 ) |
|
368 ax = ax + size.iWidth; |
|
369 if( ay < 0 ) |
|
370 ay = ay + size.iHeight; |
|
371 // ax, bx are now in range [0, size.iWidth - 1] |
|
372 |
|
373 TInt bx = iBx % size.iWidth; |
|
374 TInt by = iBy % size.iHeight; |
|
375 |
|
376 if( bx < 0 ) |
|
377 bx = bx + size.iWidth; |
|
378 if( by < 0 ) |
|
379 by = by + size.iHeight; |
|
380 // bx, by are now in range [0, size.iHeight - 1] |
|
381 |
|
382 // Render |
|
383 if( dataA.iRGBBitmap && !dataB.iRGBBitmap ) // Only A is available |
|
384 { |
|
385 if( aParam.iInputLayerAIndex == aParam.iOutputLayerIndex ) |
|
386 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
387 ax, ay, size.iWidth, size.iHeight, |
|
388 *iTempBitmap ); |
|
389 else |
|
390 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
391 ax, ay, size.iWidth, size.iHeight, |
|
392 *dataA.iRGBBitmap ); |
|
393 } |
|
394 // A, B and mask B available |
|
395 else if( dataA.iRGBBitmap && dataB.iRGBBitmap && dataB.iAlphaBitmap ) |
|
396 { |
|
397 if( aParam.iInputLayerAIndex == aParam.iOutputLayerIndex ) |
|
398 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
399 ax, ay, size.iWidth, size.iHeight, |
|
400 *iTempBitmap ); |
|
401 else |
|
402 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
403 ax, ay, size.iWidth, size.iHeight, |
|
404 *dataA.iRGBBitmap ); |
|
405 |
|
406 if( aParam.iInputLayerBIndex == aParam.iOutputLayerIndex ) |
|
407 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
408 bx, by, size.iWidth, size.iHeight, |
|
409 *iTempBitmap ); |
|
410 else |
|
411 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
412 bx, by, size.iWidth, size.iHeight, |
|
413 *dataB.iRGBBitmap, dataB.iAlphaBitmap ); |
|
414 } |
|
415 // A and B available, but no mask for B |
|
416 else if( dataA.iRGBBitmap && dataB.iRGBBitmap && !dataB.iAlphaBitmap ) |
|
417 { |
|
418 // Render B only |
|
419 if( aParam.iInputLayerBIndex == aParam.iOutputLayerIndex ) |
|
420 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
421 bx, by, size.iWidth, size.iHeight, |
|
422 *iTempBitmap ); |
|
423 else |
|
424 AknsRlMovingLayers::RenderTiled( *dataT.iRGBGc, |
|
425 bx, by, size.iWidth, size.iHeight, |
|
426 *dataB.iRGBBitmap, dataB.iAlphaBitmap ); |
|
427 } |
|
428 |
|
429 // Clear the target alpha if it exists |
|
430 if( dataT.iAlphaGc ) |
|
431 { |
|
432 dataT.iAlphaGc->SetBrushColor( KRgbWhite ); |
|
433 dataT.iAlphaGc->Clear(); |
|
434 } |
|
435 |
|
436 return KErrNone; |
|
437 } |
|
438 |
|
439 // ----------------------------------------------------------------------------- |
|
440 // CAknsRlEffectPluginMovingLayers::CreateTempBitmap |
|
441 // ----------------------------------------------------------------------------- |
|
442 // |
|
443 TInt CAknsRlEffectPluginMovingLayers::CreateTempBitmap( |
|
444 const CFbsBitmap& aBitmap ) |
|
445 { |
|
446 ASSERT( NULL == iTempBitmap ); |
|
447 ASSERT( NULL == iTempDevice ); |
|
448 ASSERT( NULL == iTempContext ); |
|
449 |
|
450 iTempBitmap = new CFbsBitmap(); // OOM returns NULL |
|
451 if( !iTempBitmap ) |
|
452 { |
|
453 DeleteTempBitmap(); |
|
454 return KErrNoMemory; |
|
455 } |
|
456 |
|
457 TInt err = iTempBitmap->Create( aBitmap.SizeInPixels(), aBitmap.DisplayMode() ); |
|
458 if( KErrNone != err ) |
|
459 { |
|
460 DeleteTempBitmap(); |
|
461 return err; |
|
462 } |
|
463 |
|
464 TRAP( err, iTempDevice = CFbsBitmapDevice::NewL( iTempBitmap ) ); |
|
465 if( KErrNone != err ) |
|
466 { |
|
467 DeleteTempBitmap(); |
|
468 return err; |
|
469 } |
|
470 |
|
471 err = iTempDevice->CreateContext( iTempContext ); |
|
472 if( KErrNone != err ) |
|
473 { |
|
474 DeleteTempBitmap(); |
|
475 return err; |
|
476 } |
|
477 |
|
478 // Temp bitmap and related objects created ok, just render the temp bitmap. |
|
479 iTempContext->BitBlt( TPoint( 0, 0 ), &aBitmap ); |
|
480 |
|
481 return KErrNone; |
|
482 } |
|
483 |
|
484 // ----------------------------------------------------------------------------- |
|
485 // CAknsRlEffectPluginMovingLayers::DeleteTempBitmap |
|
486 // ----------------------------------------------------------------------------- |
|
487 // |
|
488 void CAknsRlEffectPluginMovingLayers::DeleteTempBitmap() |
|
489 { |
|
490 delete iTempBitmap; |
|
491 iTempBitmap = NULL; |
|
492 delete iTempDevice; |
|
493 iTempDevice = NULL; |
|
494 delete iTempContext; |
|
495 iTempContext = NULL; |
|
496 } |
|
497 |
|
498 // End of File |
|
499 |