sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: sl@0: #include "openvgengine.h" sl@0: #include "eglrendering.h" sl@0: sl@0: #include sl@0: #include sl@0: sl@0: sl@0: _LIT(KCoverBitmaps, "z:\\resource\\apps\\covers.mbm"); sl@0: sl@0: sl@0: GLDEF_D VGUErrorCode vguComputeWarpQuadToQuadProxy(VGfloat dx0, VGfloat dy0, sl@0: VGfloat dx1, VGfloat dy1, sl@0: VGfloat dx2, VGfloat dy2, sl@0: VGfloat dx3, VGfloat dy3, sl@0: VGfloat sx0, VGfloat sy0, sl@0: VGfloat sx1, VGfloat sy1, sl@0: VGfloat sx2, VGfloat sy2, sl@0: VGfloat sx3, VGfloat sy3, sl@0: VGfloat * matrix) sl@0: { sl@0: vguComputeWarpQuadToQuad( sl@0: sx0, sy0, sl@0: sx1, sy1, sl@0: sx2, sy2, sl@0: sx3, sy3, sl@0: dx0, dy0, sl@0: dx1, dy1, sl@0: dx2, dy2, sl@0: dx3, dy3, sl@0: matrix); sl@0: return VGU_NO_ERROR; sl@0: } sl@0: sl@0: COpenVGEngine* COpenVGEngine::NewL(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) sl@0: { sl@0: COpenVGEngine* self = new(ELeave) COpenVGEngine(aWindow, aDisplay, aSurface, aContext); sl@0: return self; sl@0: } sl@0: sl@0: COpenVGEngine::COpenVGEngine(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) : sl@0: iWindow(aWindow), iDisplay(aDisplay), iSurface(aSurface), iContext(aContext), iWantedCover(20), sl@0: iHasPendingDraw(EFalse), iShowCoverImage(EFalse), iSpeedOffset(0), iShowMirror(ETrue), iSpeed(0), sl@0: iCurrentImageIndex(0) sl@0: { sl@0: #ifdef PORTRAIT_MODE sl@0: iSurfaceSize.iWidth = iWindow.Size().iHeight; sl@0: iSurfaceSize.iHeight = iWindow.Size().iWidth; sl@0: #else sl@0: iSurfaceSize = iWindow.Size(); sl@0: #endif sl@0: // initiate the location of each cover & make the wanted one the cover at the opposite end sl@0: for(TInt i = 0; i < KMaxCoversExample3; ++i) sl@0: { sl@0: iCoverLocation[i] = i; sl@0: } sl@0: } sl@0: sl@0: COpenVGEngine::~COpenVGEngine() sl@0: { sl@0: Deactivate(); sl@0: } sl@0: sl@0: TInt COpenVGEngine::GetSpeed() sl@0: { sl@0: return static_cast(iSpeed * 100000); sl@0: } sl@0: sl@0: TBool COpenVGEngine::IsPending() sl@0: { sl@0: return iHasPendingDraw; sl@0: } sl@0: sl@0: void COpenVGEngine::ActivateL() sl@0: { sl@0: CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); sl@0: sl@0: // Setup initial OpenVG context state sl@0: VGfloat clearColour[] = { 0.1f, 0.1f, 0.2f, 1.0f }; sl@0: vgSetfv(VG_CLEAR_COLOR, 4, clearColour); sl@0: vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED); sl@0: vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED); sl@0: vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); sl@0: sl@0: CFbsBitmap* bitmap = new(ELeave) CFbsBitmap(); sl@0: CleanupStack::PushL(bitmap); sl@0: TInt idx = 0; sl@0: while(bitmap->Load(KCoverBitmaps, idx++) == KErrNone) sl@0: { sl@0: VGint width = bitmap->SizeInPixels().iWidth; sl@0: VGint height = bitmap->SizeInPixels().iHeight; sl@0: // Crate VGImage sl@0: VGImage image = vgCreateImage(VG_sRGB_565, width, height, VG_IMAGE_QUALITY_NONANTIALIASED); sl@0: CEGLRendering::VGCheckError(); sl@0: //Load Symbian bitmap into VGImage sl@0: vgImageSubData(image, bitmap->DataAddress(), bitmap->DataStride(), VG_sRGB_565, 0, 0, width, height); sl@0: CEGLRendering::VGCheckError(); sl@0: iImages.AppendL(image); sl@0: } sl@0: CleanupStack::PopAndDestroy(bitmap); sl@0: iHasPendingDraw = ETrue; sl@0: sl@0: //Checks if any images were loaded sl@0: if(iImages.Count() == 0) sl@0: { sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: sl@0: iShadowPaint = vgCreatePaint(); sl@0: CEGLRendering::VGCheckError(); sl@0: if (iShadowPaint != VG_INVALID_HANDLE) sl@0: { sl@0: VGfloat paintColour[4] = { 0.4f, 0.4f, 0.6f, 1.0f }; sl@0: vgSetParameterfv(iShadowPaint, VG_PAINT_COLOR, 4, paintColour); sl@0: CEGLRendering::VGCheckError(); sl@0: } sl@0: } sl@0: sl@0: void COpenVGEngine::Deactivate() sl@0: { sl@0: CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); sl@0: for (TInt i = iImages.Count() - 1; i >= 0; --i) sl@0: { sl@0: vgDestroyImage(iImages[i]); sl@0: } sl@0: vgDestroyPaint(iShadowPaint); sl@0: eglWaitClient(); sl@0: iImages.Reset(); sl@0: iHasPendingDraw = EFalse; sl@0: } sl@0: sl@0: void COpenVGEngine::Step() sl@0: { sl@0: CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); sl@0: sl@0: #ifdef PORTRAIT_MODE sl@0: vgClear(0, 0, iSurfaceSize.iHeight, iSurfaceSize.iWidth); sl@0: #else sl@0: vgClear(0, 0, iSurfaceSize.iWidth, iSurfaceSize.iHeight); sl@0: #endif sl@0: sl@0: if (Abs(iCoverLocation[iWantedCover]) < 0.03) sl@0: { sl@0: iSpeed = 0.0f; sl@0: iHasPendingDraw = EFalse; sl@0: } sl@0: else if (Abs(iCoverLocation[iWantedCover]) < 0.5) sl@0: { sl@0: iSpeed *= 0.7; sl@0: } sl@0: else sl@0: { sl@0: iSpeed = 0.05 * (2 + Abs(iCoverLocation[iWantedCover]) + (Abs(iCoverLocation[iWantedCover]) + 1) sl@0: * (Abs(iCoverLocation[iWantedCover]) + 1) / 2); sl@0: } sl@0: // For each Cover, update its location in the correct direction sl@0: // Check if the wanted cover is already at the CenterStage point sl@0: sl@0: VGfloat moveEachCover = iSpeed; sl@0: if (iCoverLocation[iWantedCover] > 0.0) sl@0: { sl@0: moveEachCover *= -1; sl@0: } sl@0: sl@0: for (TInt i = 0; i < KMaxCoversExample3; ++i) sl@0: { sl@0: iCoverLocation[i] += moveEachCover; sl@0: } sl@0: sl@0: TInt coverClippingCount = 10; sl@0: TInt middleCoverPos = 0; sl@0: VGfloat threshold = 0.50f; sl@0: sl@0: while(Abs(iCoverLocation[middleCoverPos]) > threshold) sl@0: { sl@0: ++middleCoverPos; sl@0: } sl@0: sl@0: sl@0: //left sl@0: TInt cutOff = middleCoverPos - coverClippingCount; sl@0: if (cutOff <0 ) sl@0: { sl@0: cutOff = 0; sl@0: } sl@0: for (TInt i = cutOff; i < middleCoverPos; ++i) sl@0: { sl@0: DrawCover(i); sl@0: } sl@0: sl@0: //right sl@0: cutOff = coverClippingCount + middleCoverPos; sl@0: if (cutOff >= KMaxCoversExample3) sl@0: { sl@0: cutOff = KMaxCoversExample3-1; sl@0: } sl@0: sl@0: for (TInt j = cutOff; j >= middleCoverPos; --j) sl@0: { sl@0: DrawCover(j); sl@0: } sl@0: sl@0: static TInt dir = 1; sl@0: if (iWantedCover == (KMaxCoversExample3 - 1)) sl@0: { sl@0: dir = -1; sl@0: } sl@0: else if (iWantedCover == 0) sl@0: { sl@0: dir = 1; sl@0: } sl@0: sl@0: iWantedCover += dir; sl@0: iHasPendingDraw = ETrue; sl@0: } sl@0: sl@0: void COpenVGEngine::DrawCover(TInt coverIndex) sl@0: { sl@0: VGImage image = iImages[coverIndex % iImages.Count()]; sl@0: // Starting at the outside, render each visible (+/- KMaxDisplayCoversExample3/2) Cover sl@0: // Calculate its path sl@0: vgLoadIdentity(); sl@0: #ifdef PORTRAIT_MODE sl@0: vgTranslate(iSurfaceSize.iHeight, 0); sl@0: vgRotate(90); sl@0: #endif sl@0: VGfloat coverPosition = iCoverLocation[coverIndex]; sl@0: VGfloat tempMatrix[3][3]; sl@0: sl@0: //flip coords sl@0: VGfloat flipmatrix[] = sl@0: { sl@0: 1.0f, 0.0f, 0.0f, sl@0: 0.0f, -1.0f, 0.0f, sl@0: 0.0f, 0.0f, 1.0f sl@0: }; sl@0: vgMultMatrix(flipmatrix); sl@0: VGint imageWidth = vgGetParameteri(image, VG_IMAGE_WIDTH); sl@0: VGint imageHeight = vgGetParameteri(image, VG_IMAGE_HEIGHT); sl@0: sl@0: //VGint yTrans = -200; sl@0: sl@0: //factors which must be multiplied with side of image which will be projected towards back sl@0: //valid if projecting right image side to back sl@0: //opposite is (1 - factor) for projecting left image side. sl@0: sl@0: VGfloat bottomProjectXFactor= (0.75f); sl@0: VGfloat bottomProjectYFactor = (0.20f); sl@0: sl@0: VGfloat topProjectXFactor = (0.75f); sl@0: VGfloat topProjectYFactor = (0.90f); sl@0: sl@0: VGfloat imageSpacingFactor = 0.16; sl@0: sl@0: VGfloat translationOffset = 0.0; sl@0: sl@0: sl@0: //float yscale = 1.7; sl@0: //float xscale = 4.4; sl@0: //imageHeight = Min(iSurfaceSize.iWidth/xscale, iSurfaceSize.iHeight/yscale); sl@0: //imageWidth = imageHeight; sl@0: //TInt KImageSize = imageHeight/1.125; sl@0: //VGint yTrans = iSurfaceSize.iHeight/-1.2; sl@0: sl@0: TInt KImageSize = (imageHeight * 8) / 9; //KImageSize - secondary covers should be 8/9 of the size of the middle cover sl@0: //VGint yTrans = -200; sl@0: VGint yTrans = - (iWindow.Size().iHeight * 5) / 6; sl@0: sl@0: sl@0: VGfloat middleTranslationOffset = KImageSize / 2; sl@0: VGfloat coverProjectionLimit = 10; sl@0: sl@0: if (coverPosition >= 1) sl@0: { sl@0: //if considering an image on the right side, this is offset from middle to place image on screen sl@0: translationOffset = middleTranslationOffset- KImageSize/2 + KImageSize*imageSpacingFactor * (coverPosition -1); sl@0: sl@0: //left side of image goes back. sl@0: vguComputeWarpQuadToQuadProxy(0.0f, 0.0f, sl@0: imageWidth, 0.0f, sl@0: 0.0f, imageHeight, sl@0: imageWidth, imageHeight, sl@0: KImageSize * (1 - bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)),KImageSize * bottomProjectYFactor,//left vertex sl@0: KImageSize, 0.0f, sl@0: KImageSize * (1 - topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)), KImageSize * topProjectYFactor,//left vertex sl@0: KImageSize, KImageSize, sl@0: &tempMatrix[0][0]); sl@0: } sl@0: else if (coverPosition < -1) sl@0: { sl@0: //must move an extra image width from center , as coordinates from bottom left corner of image. sl@0: translationOffset = - (middleTranslationOffset + (KImageSize * imageSpacingFactor) * ( -coverPosition - 1) + KImageSize/2) ; sl@0: sl@0: vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, sl@0: imageWidth, 0.0f, sl@0: 0.0f, imageHeight, sl@0: imageWidth, imageHeight, sl@0: sl@0: 0.0f, 0.0f, sl@0: (bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit))* KImageSize, bottomProjectYFactor * KImageSize, //Right Vertex sl@0: 0.0f, (KImageSize), sl@0: (topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)) * KImageSize, topProjectYFactor * KImageSize, //Right Vertex sl@0: sl@0: &tempMatrix[0][0]); sl@0: } sl@0: else if((coverPosition > -1) && (coverPosition <= 0))// -0.07)) sl@0: { sl@0: translationOffset = -middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ; sl@0: sl@0: vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, sl@0: imageWidth, 0.0f, sl@0: 0.0f, imageHeight, sl@0: imageWidth, imageHeight, sl@0: 0.0f, 0.0f, sl@0: KImageSize * (1 - (1-bottomProjectXFactor) * Abs(coverPosition)), KImageSize * bottomProjectYFactor * Abs(coverPosition), sl@0: 0.0f, KImageSize, sl@0: (KImageSize * (1 - ( 1 - topProjectXFactor) * Abs(coverPosition))) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)), sl@0: &tempMatrix[0][0]); sl@0: } sl@0: else if ((coverPosition >=0) && (coverPosition <= 1)) sl@0: { sl@0: translationOffset = middleTranslationOffset * Abs(coverPosition) - KImageSize / 2; sl@0: vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, sl@0: imageWidth, 0.0f, sl@0: 0.0f, imageHeight, sl@0: imageWidth, imageHeight, sl@0: KImageSize * (1-bottomProjectXFactor)* (coverPosition), KImageSize * (bottomProjectYFactor) * (coverPosition), sl@0: KImageSize, 0, sl@0: KImageSize * ( 1 - topProjectXFactor) * (coverPosition) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)), sl@0: KImageSize, KImageSize, sl@0: &tempMatrix[0][0]); sl@0: } sl@0: iSpeedOffset = 140*(iSpeed)*(iSpeed); sl@0: if (iCoverLocation[iWantedCover] < 0) sl@0: { sl@0: iSpeedOffset *= -1; sl@0: } sl@0: vgTranslate(iWindow.Size().iWidth/2 + translationOffset + iSpeedOffset, yTrans); sl@0: sl@0: vgMultMatrix(&tempMatrix[0][0]); sl@0: if (Abs(coverPosition) <= 1) sl@0: { sl@0: VGfloat scale = GetMiddleCoverScalingFactor(coverPosition); sl@0: vgScale(scale,scale); sl@0: vgTranslate(-(scale-1)/2 * KImageSize,-(scale-1)/2 * KImageSize); sl@0: } sl@0: vgDrawImage(image); sl@0: CEGLRendering::VGCheckError(); sl@0: if (iShowMirror) sl@0: { sl@0: vgScale(1,-1); sl@0: vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); sl@0: vgTranslate(0,-4*KImageSize+226); sl@0: //vgTranslate(0,iSurfaceSize.iHeight/-.839); sl@0: sl@0: vgSetPaint(iShadowPaint, VG_FILL_PATH); sl@0: vgDrawImage(image); sl@0: CEGLRendering::VGCheckError(); sl@0: sl@0: vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL); sl@0: } sl@0: } sl@0: sl@0: TKeyResponse COpenVGEngine::HandleKeyEventL(const TKeyEvent& aKeyEvent) sl@0: { sl@0: TKeyResponse response = EKeyWasConsumed; sl@0: switch (aKeyEvent.iCode) sl@0: { sl@0: case EKeyRightArrow: sl@0: NextCover(); sl@0: break; sl@0: case EKeyLeftArrow: sl@0: PreviousCover(); sl@0: break; sl@0: case EKeyBackspace: sl@0: ToggleCoverReflection(); sl@0: break; sl@0: default: sl@0: response = EKeyWasNotConsumed; sl@0: break; sl@0: }; sl@0: return response; sl@0: } sl@0: sl@0: void COpenVGEngine::NextCover() sl@0: { sl@0: if (iWantedCover < (KMaxCoversExample3 - 1)) sl@0: { sl@0: ++iWantedCover; sl@0: iHasPendingDraw = ETrue; sl@0: } sl@0: } sl@0: sl@0: void COpenVGEngine::PreviousCover() sl@0: { sl@0: if (iWantedCover > 0) sl@0: { sl@0: --iWantedCover; sl@0: iHasPendingDraw = ETrue; sl@0: } sl@0: } sl@0: sl@0: void COpenVGEngine::ToggleCoverReflection() sl@0: { sl@0: iShowMirror = !iShowMirror; sl@0: } sl@0: sl@0: VGfloat COpenVGEngine::GetMiddleCoverScalingFactor(VGfloat aCoverPosition) sl@0: { sl@0: if(Abs(aCoverPosition) > 1) sl@0: { sl@0: return 0.0f; sl@0: } sl@0: return (-0.125 * Abs(aCoverPosition) + 1.125); sl@0: } sl@0: sl@0: void COpenVGEngine::Refresh() sl@0: { sl@0: iHasPendingDraw = ETrue; sl@0: }