|
1 // Copyright (c) 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 #include "openvgengine.h" |
|
18 #include "eglrendering.h" |
|
19 |
|
20 #include <eikenv.h> |
|
21 #include <e32math.h> |
|
22 |
|
23 |
|
24 _LIT(KCoverBitmaps, "z:\\resource\\apps\\covers.mbm"); |
|
25 |
|
26 |
|
27 GLDEF_D VGUErrorCode vguComputeWarpQuadToQuadProxy(VGfloat dx0, VGfloat dy0, |
|
28 VGfloat dx1, VGfloat dy1, |
|
29 VGfloat dx2, VGfloat dy2, |
|
30 VGfloat dx3, VGfloat dy3, |
|
31 VGfloat sx0, VGfloat sy0, |
|
32 VGfloat sx1, VGfloat sy1, |
|
33 VGfloat sx2, VGfloat sy2, |
|
34 VGfloat sx3, VGfloat sy3, |
|
35 VGfloat * matrix) |
|
36 { |
|
37 vguComputeWarpQuadToQuad( |
|
38 sx0, sy0, |
|
39 sx1, sy1, |
|
40 sx2, sy2, |
|
41 sx3, sy3, |
|
42 dx0, dy0, |
|
43 dx1, dy1, |
|
44 dx2, dy2, |
|
45 dx3, dy3, |
|
46 matrix); |
|
47 return VGU_NO_ERROR; |
|
48 } |
|
49 |
|
50 COpenVGEngine* COpenVGEngine::NewL(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) |
|
51 { |
|
52 COpenVGEngine* self = new(ELeave) COpenVGEngine(aWindow, aDisplay, aSurface, aContext); |
|
53 return self; |
|
54 } |
|
55 |
|
56 COpenVGEngine::COpenVGEngine(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) : |
|
57 iWindow(aWindow), iDisplay(aDisplay), iSurface(aSurface), iContext(aContext), iWantedCover(20), |
|
58 iHasPendingDraw(EFalse), iShowCoverImage(EFalse), iSpeedOffset(0), iShowMirror(ETrue), iSpeed(0), |
|
59 iCurrentImageIndex(0) |
|
60 { |
|
61 #ifdef PORTRAIT_MODE |
|
62 iSurfaceSize.iWidth = iWindow.Size().iHeight; |
|
63 iSurfaceSize.iHeight = iWindow.Size().iWidth; |
|
64 #else |
|
65 iSurfaceSize = iWindow.Size(); |
|
66 #endif |
|
67 // initiate the location of each cover & make the wanted one the cover at the opposite end |
|
68 for(TInt i = 0; i < KMaxCoversExample3; ++i) |
|
69 { |
|
70 iCoverLocation[i] = i; |
|
71 } |
|
72 } |
|
73 |
|
74 COpenVGEngine::~COpenVGEngine() |
|
75 { |
|
76 Deactivate(); |
|
77 } |
|
78 |
|
79 TInt COpenVGEngine::GetSpeed() |
|
80 { |
|
81 return static_cast<TInt>(iSpeed * 100000); |
|
82 } |
|
83 |
|
84 TBool COpenVGEngine::IsPending() |
|
85 { |
|
86 return iHasPendingDraw; |
|
87 } |
|
88 |
|
89 void COpenVGEngine::ActivateL() |
|
90 { |
|
91 CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); |
|
92 |
|
93 // Setup initial OpenVG context state |
|
94 VGfloat clearColour[] = { 0.1f, 0.1f, 0.2f, 1.0f }; |
|
95 vgSetfv(VG_CLEAR_COLOR, 4, clearColour); |
|
96 vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED); |
|
97 vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED); |
|
98 vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); |
|
99 |
|
100 CFbsBitmap* bitmap = new(ELeave) CFbsBitmap(); |
|
101 CleanupStack::PushL(bitmap); |
|
102 TInt idx = 0; |
|
103 while(bitmap->Load(KCoverBitmaps, idx++) == KErrNone) |
|
104 { |
|
105 VGint width = bitmap->SizeInPixels().iWidth; |
|
106 VGint height = bitmap->SizeInPixels().iHeight; |
|
107 // Crate VGImage |
|
108 VGImage image = vgCreateImage(VG_sRGB_565, width, height, VG_IMAGE_QUALITY_NONANTIALIASED); |
|
109 CEGLRendering::VGCheckError(); |
|
110 //Load Symbian bitmap into VGImage |
|
111 vgImageSubData(image, bitmap->DataAddress(), bitmap->DataStride(), VG_sRGB_565, 0, 0, width, height); |
|
112 CEGLRendering::VGCheckError(); |
|
113 iImages.AppendL(image); |
|
114 } |
|
115 CleanupStack::PopAndDestroy(bitmap); |
|
116 iHasPendingDraw = ETrue; |
|
117 |
|
118 //Checks if any images were loaded |
|
119 if(iImages.Count() == 0) |
|
120 { |
|
121 User::Leave(KErrNotFound); |
|
122 } |
|
123 |
|
124 iShadowPaint = vgCreatePaint(); |
|
125 CEGLRendering::VGCheckError(); |
|
126 if (iShadowPaint != VG_INVALID_HANDLE) |
|
127 { |
|
128 VGfloat paintColour[4] = { 0.4f, 0.4f, 0.6f, 1.0f }; |
|
129 vgSetParameterfv(iShadowPaint, VG_PAINT_COLOR, 4, paintColour); |
|
130 CEGLRendering::VGCheckError(); |
|
131 } |
|
132 } |
|
133 |
|
134 void COpenVGEngine::Deactivate() |
|
135 { |
|
136 CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); |
|
137 for (TInt i = iImages.Count() - 1; i >= 0; --i) |
|
138 { |
|
139 vgDestroyImage(iImages[i]); |
|
140 } |
|
141 vgDestroyPaint(iShadowPaint); |
|
142 eglWaitClient(); |
|
143 iImages.Reset(); |
|
144 iHasPendingDraw = EFalse; |
|
145 } |
|
146 |
|
147 void COpenVGEngine::Step() |
|
148 { |
|
149 CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); |
|
150 |
|
151 #ifdef PORTRAIT_MODE |
|
152 vgClear(0, 0, iSurfaceSize.iHeight, iSurfaceSize.iWidth); |
|
153 #else |
|
154 vgClear(0, 0, iSurfaceSize.iWidth, iSurfaceSize.iHeight); |
|
155 #endif |
|
156 |
|
157 if (Abs(iCoverLocation[iWantedCover]) < 0.03) |
|
158 { |
|
159 iSpeed = 0.0f; |
|
160 iHasPendingDraw = EFalse; |
|
161 } |
|
162 else if (Abs(iCoverLocation[iWantedCover]) < 0.5) |
|
163 { |
|
164 iSpeed *= 0.7; |
|
165 } |
|
166 else |
|
167 { |
|
168 iSpeed = 0.05 * (2 + Abs(iCoverLocation[iWantedCover]) + (Abs(iCoverLocation[iWantedCover]) + 1) |
|
169 * (Abs(iCoverLocation[iWantedCover]) + 1) / 2); |
|
170 } |
|
171 // For each Cover, update its location in the correct direction |
|
172 // Check if the wanted cover is already at the CenterStage point |
|
173 |
|
174 VGfloat moveEachCover = iSpeed; |
|
175 if (iCoverLocation[iWantedCover] > 0.0) |
|
176 { |
|
177 moveEachCover *= -1; |
|
178 } |
|
179 |
|
180 for (TInt i = 0; i < KMaxCoversExample3; ++i) |
|
181 { |
|
182 iCoverLocation[i] += moveEachCover; |
|
183 } |
|
184 |
|
185 TInt coverClippingCount = 10; |
|
186 TInt middleCoverPos = 0; |
|
187 VGfloat threshold = 0.50f; |
|
188 |
|
189 while(Abs(iCoverLocation[middleCoverPos]) > threshold) |
|
190 { |
|
191 ++middleCoverPos; |
|
192 } |
|
193 |
|
194 |
|
195 //left |
|
196 TInt cutOff = middleCoverPos - coverClippingCount; |
|
197 if (cutOff <0 ) |
|
198 { |
|
199 cutOff = 0; |
|
200 } |
|
201 for (TInt i = cutOff; i < middleCoverPos; ++i) |
|
202 { |
|
203 DrawCover(i); |
|
204 } |
|
205 |
|
206 //right |
|
207 cutOff = coverClippingCount + middleCoverPos; |
|
208 if (cutOff >= KMaxCoversExample3) |
|
209 { |
|
210 cutOff = KMaxCoversExample3-1; |
|
211 } |
|
212 |
|
213 for (TInt j = cutOff; j >= middleCoverPos; --j) |
|
214 { |
|
215 DrawCover(j); |
|
216 } |
|
217 |
|
218 static TInt dir = 1; |
|
219 if (iWantedCover == (KMaxCoversExample3 - 1)) |
|
220 { |
|
221 dir = -1; |
|
222 } |
|
223 else if (iWantedCover == 0) |
|
224 { |
|
225 dir = 1; |
|
226 } |
|
227 |
|
228 iWantedCover += dir; |
|
229 iHasPendingDraw = ETrue; |
|
230 } |
|
231 |
|
232 void COpenVGEngine::DrawCover(TInt coverIndex) |
|
233 { |
|
234 VGImage image = iImages[coverIndex % iImages.Count()]; |
|
235 // Starting at the outside, render each visible (+/- KMaxDisplayCoversExample3/2) Cover |
|
236 // Calculate its path |
|
237 vgLoadIdentity(); |
|
238 #ifdef PORTRAIT_MODE |
|
239 vgTranslate(iSurfaceSize.iHeight, 0); |
|
240 vgRotate(90); |
|
241 #endif |
|
242 VGfloat coverPosition = iCoverLocation[coverIndex]; |
|
243 VGfloat tempMatrix[3][3]; |
|
244 |
|
245 //flip coords |
|
246 VGfloat flipmatrix[] = |
|
247 { |
|
248 1.0f, 0.0f, 0.0f, |
|
249 0.0f, -1.0f, 0.0f, |
|
250 0.0f, 0.0f, 1.0f |
|
251 }; |
|
252 vgMultMatrix(flipmatrix); |
|
253 VGint imageWidth = vgGetParameteri(image, VG_IMAGE_WIDTH); |
|
254 VGint imageHeight = vgGetParameteri(image, VG_IMAGE_HEIGHT); |
|
255 |
|
256 //VGint yTrans = -200; |
|
257 |
|
258 //factors which must be multiplied with side of image which will be projected towards back |
|
259 //valid if projecting right image side to back |
|
260 //opposite is (1 - factor) for projecting left image side. |
|
261 |
|
262 VGfloat bottomProjectXFactor= (0.75f); |
|
263 VGfloat bottomProjectYFactor = (0.20f); |
|
264 |
|
265 VGfloat topProjectXFactor = (0.75f); |
|
266 VGfloat topProjectYFactor = (0.90f); |
|
267 |
|
268 VGfloat imageSpacingFactor = 0.16; |
|
269 |
|
270 VGfloat translationOffset = 0.0; |
|
271 |
|
272 |
|
273 //float yscale = 1.7; |
|
274 //float xscale = 4.4; |
|
275 //imageHeight = Min(iSurfaceSize.iWidth/xscale, iSurfaceSize.iHeight/yscale); |
|
276 //imageWidth = imageHeight; |
|
277 //TInt KImageSize = imageHeight/1.125; |
|
278 //VGint yTrans = iSurfaceSize.iHeight/-1.2; |
|
279 |
|
280 TInt KImageSize = (imageHeight * 8) / 9; //KImageSize - secondary covers should be 8/9 of the size of the middle cover |
|
281 //VGint yTrans = -200; |
|
282 VGint yTrans = - (iWindow.Size().iHeight * 5) / 6; |
|
283 |
|
284 |
|
285 VGfloat middleTranslationOffset = KImageSize / 2; |
|
286 VGfloat coverProjectionLimit = 10; |
|
287 |
|
288 if (coverPosition >= 1) |
|
289 { |
|
290 //if considering an image on the right side, this is offset from middle to place image on screen |
|
291 translationOffset = middleTranslationOffset- KImageSize/2 + KImageSize*imageSpacingFactor * (coverPosition -1); |
|
292 |
|
293 //left side of image goes back. |
|
294 vguComputeWarpQuadToQuadProxy(0.0f, 0.0f, |
|
295 imageWidth, 0.0f, |
|
296 0.0f, imageHeight, |
|
297 imageWidth, imageHeight, |
|
298 KImageSize * (1 - bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)),KImageSize * bottomProjectYFactor,//left vertex |
|
299 KImageSize, 0.0f, |
|
300 KImageSize * (1 - topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)), KImageSize * topProjectYFactor,//left vertex |
|
301 KImageSize, KImageSize, |
|
302 &tempMatrix[0][0]); |
|
303 } |
|
304 else if (coverPosition < -1) |
|
305 { |
|
306 //must move an extra image width from center , as coordinates from bottom left corner of image. |
|
307 translationOffset = - (middleTranslationOffset + (KImageSize * imageSpacingFactor) * ( -coverPosition - 1) + KImageSize/2) ; |
|
308 |
|
309 vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, |
|
310 imageWidth, 0.0f, |
|
311 0.0f, imageHeight, |
|
312 imageWidth, imageHeight, |
|
313 |
|
314 0.0f, 0.0f, |
|
315 (bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit))* KImageSize, bottomProjectYFactor * KImageSize, //Right Vertex |
|
316 0.0f, (KImageSize), |
|
317 (topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)) * KImageSize, topProjectYFactor * KImageSize, //Right Vertex |
|
318 |
|
319 &tempMatrix[0][0]); |
|
320 } |
|
321 else if((coverPosition > -1) && (coverPosition <= 0))// -0.07)) |
|
322 { |
|
323 translationOffset = -middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ; |
|
324 |
|
325 vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, |
|
326 imageWidth, 0.0f, |
|
327 0.0f, imageHeight, |
|
328 imageWidth, imageHeight, |
|
329 0.0f, 0.0f, |
|
330 KImageSize * (1 - (1-bottomProjectXFactor) * Abs(coverPosition)), KImageSize * bottomProjectYFactor * Abs(coverPosition), |
|
331 0.0f, KImageSize, |
|
332 (KImageSize * (1 - ( 1 - topProjectXFactor) * Abs(coverPosition))) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)), |
|
333 &tempMatrix[0][0]); |
|
334 } |
|
335 else if ((coverPosition >=0) && (coverPosition <= 1)) |
|
336 { |
|
337 translationOffset = middleTranslationOffset * Abs(coverPosition) - KImageSize / 2; |
|
338 vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, |
|
339 imageWidth, 0.0f, |
|
340 0.0f, imageHeight, |
|
341 imageWidth, imageHeight, |
|
342 KImageSize * (1-bottomProjectXFactor)* (coverPosition), KImageSize * (bottomProjectYFactor) * (coverPosition), |
|
343 KImageSize, 0, |
|
344 KImageSize * ( 1 - topProjectXFactor) * (coverPosition) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)), |
|
345 KImageSize, KImageSize, |
|
346 &tempMatrix[0][0]); |
|
347 } |
|
348 iSpeedOffset = 140*(iSpeed)*(iSpeed); |
|
349 if (iCoverLocation[iWantedCover] < 0) |
|
350 { |
|
351 iSpeedOffset *= -1; |
|
352 } |
|
353 vgTranslate(iWindow.Size().iWidth/2 + translationOffset + iSpeedOffset, yTrans); |
|
354 |
|
355 vgMultMatrix(&tempMatrix[0][0]); |
|
356 if (Abs(coverPosition) <= 1) |
|
357 { |
|
358 VGfloat scale = GetMiddleCoverScalingFactor(coverPosition); |
|
359 vgScale(scale,scale); |
|
360 vgTranslate(-(scale-1)/2 * KImageSize,-(scale-1)/2 * KImageSize); |
|
361 } |
|
362 vgDrawImage(image); |
|
363 CEGLRendering::VGCheckError(); |
|
364 if (iShowMirror) |
|
365 { |
|
366 vgScale(1,-1); |
|
367 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); |
|
368 vgTranslate(0,-4*KImageSize+226); |
|
369 //vgTranslate(0,iSurfaceSize.iHeight/-.839); |
|
370 |
|
371 vgSetPaint(iShadowPaint, VG_FILL_PATH); |
|
372 vgDrawImage(image); |
|
373 CEGLRendering::VGCheckError(); |
|
374 |
|
375 vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL); |
|
376 } |
|
377 } |
|
378 |
|
379 TKeyResponse COpenVGEngine::HandleKeyEventL(const TKeyEvent& aKeyEvent) |
|
380 { |
|
381 TKeyResponse response = EKeyWasConsumed; |
|
382 switch (aKeyEvent.iCode) |
|
383 { |
|
384 case EKeyRightArrow: |
|
385 NextCover(); |
|
386 break; |
|
387 case EKeyLeftArrow: |
|
388 PreviousCover(); |
|
389 break; |
|
390 case EKeyBackspace: |
|
391 ToggleCoverReflection(); |
|
392 break; |
|
393 default: |
|
394 response = EKeyWasNotConsumed; |
|
395 break; |
|
396 }; |
|
397 return response; |
|
398 } |
|
399 |
|
400 void COpenVGEngine::NextCover() |
|
401 { |
|
402 if (iWantedCover < (KMaxCoversExample3 - 1)) |
|
403 { |
|
404 ++iWantedCover; |
|
405 iHasPendingDraw = ETrue; |
|
406 } |
|
407 } |
|
408 |
|
409 void COpenVGEngine::PreviousCover() |
|
410 { |
|
411 if (iWantedCover > 0) |
|
412 { |
|
413 --iWantedCover; |
|
414 iHasPendingDraw = ETrue; |
|
415 } |
|
416 } |
|
417 |
|
418 void COpenVGEngine::ToggleCoverReflection() |
|
419 { |
|
420 iShowMirror = !iShowMirror; |
|
421 } |
|
422 |
|
423 VGfloat COpenVGEngine::GetMiddleCoverScalingFactor(VGfloat aCoverPosition) |
|
424 { |
|
425 if(Abs(aCoverPosition) > 1) |
|
426 { |
|
427 return 0.0f; |
|
428 } |
|
429 return (-0.125 * Abs(aCoverPosition) + 1.125); |
|
430 } |
|
431 |
|
432 void COpenVGEngine::Refresh() |
|
433 { |
|
434 iHasPendingDraw = ETrue; |
|
435 } |