/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
// INCLUDE FILES
#include "HgVgMediaWallRenderer.h"
#include "HgVgHelper.h"
#include "HgConstants.h"
#include "HgVgConstants.h"
#include <VG/vgu.h>
#include <ganes/HgVgItem.h>
#include <AknUtils.h>
#include <layoutmetadata.cdl.h>
#include <AknLayout2ScalableDef.h>
#include <AknsDrawUtils.h>
#include <e32math.h>
using namespace HgVgConstants;
const VGfloat KColorByteToFloat(255.0f);
// Ending position of the left album stack
const VGfloat KLeftStackEndX(-1.04);//-235.0f);
// Ending position of the right album stack
const VGfloat KRightStackStartX(1.04);//235.0f);
// Space between albums in stacks
const VGfloat KSpaceBetween(1.04);//235);
const TInt KGroundHeightFactor(2);
const TInt KNumGroundGradientValues(4);
const VGfloat KGroundGradient[] = {
0.0f, 0.0f, 0.0f, 1.0f
};
const TInt KGroundVerticesHint(4);
const TInt KGroundSegmentsHint(4);
const VGfloat KGroundScale(1.0f);
const VGfloat KGroundBias(0.0f);
const VGfloat KFov(PI/2);
const VGfloat KFlipAngle(PI);
const VGfloat KQuadVerts[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f
};
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CHgVgCoverflowRenderer::NewL()
// -----------------------------------------------------------------------------
//
CHgVgMediaWallRenderer* CHgVgMediaWallRenderer::NewL(TInt aMaxQuads, const TRect& aRect,
const TRect& aFrontRect, TReal aZOffset )
{
CHgVgMediaWallRenderer* self = new (ELeave) CHgVgMediaWallRenderer( aRect,
aFrontRect, aZOffset);
CleanupStack::PushL( self );
self->ConstructL(aMaxQuads);
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CHgVgMediaWallRenderer::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::ConstructL (TInt aMaxQuads)
{
for (TInt i = 0; i < aMaxQuads; i++)
{
TQuad* q = new (ELeave)TQuad;
q->iItemIndex = -1;
iQuads.Append(q);
}
CreateGround();
}
// -----------------------------------------------------------------------------
// CHgVgMediaWallRenderer::CHgVgMediaWallRenderer()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CHgVgMediaWallRenderer::CHgVgMediaWallRenderer(
const TRect& aWindowRect,
const TRect& aFrontRect,
TReal aZOffset) :
iRect(aWindowRect),
iReflectionsEnabled(ETrue),
iSelectedItemIndex(KSelectedItemIndex),
iLeftStackEndX(KLeftStackEndX),
iRightStackStartX(KRightStackStartX),
iSpaceBetween(KSpaceBetween),
iFov(KFov),
iFlipAngle(KFlipAngle)
{
AdjustSettingsBasedOnRects(aFrontRect, aZOffset);
}
// -----------------------------------------------------------------------------
// CHgVgScrollBar::~CHgVgScrollBar()
// Destructor.
// -----------------------------------------------------------------------------
//
CHgVgMediaWallRenderer::~CHgVgMediaWallRenderer ( )
{
if (iDefaultImage != VG_INVALID_HANDLE)
vgDestroyImage(iDefaultImage);
if (iChildBlurImage != VG_INVALID_HANDLE)
vgDestroyImage(iChildBlurImage);
if (iBlurImage != VG_INVALID_HANDLE)
vgDestroyImage(iBlurImage);
vgDestroyPaint(iGroundPaint);
vgDestroyPath(iGroundPath);
iQuads.ResetAndDestroy();
iSortedQuads.Reset();
}
// -----------------------------------------------------------------------------
// CHgMediaWallRenderer::SetDefaultImage()
// Setter for default image used to draw quads.
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::SetDefaultIconL(const CGulIcon& aIcon)
{
iDefaultImage = HgVgHelper::CreateVgImageFromIconL(aIcon);
}
// -----------------------------------------------------------------------------
// CHgMediaWallRenderer::SetCameraPosition()
// Setter for camera position modifier.
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::SetCameraPosition(TReal aX, TReal aY, TReal aZ)
{
iCameraX = aX;
iCameraY = aY;
iCameraZ = aZ;
}
// -----------------------------------------------------------------------------
// CHgMediaWallRenderer::SetCameraRotation()
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::SetCameraRotation(TReal aAngle)
{
iCameraRotation = aAngle;
}
// -----------------------------------------------------------------------------
// CHgVgScrollBar::SortQuads
// Sorts quads from iQuads to iSortedQuads.
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::SortQuads(TInt aNumQuads)
{
iSortedQuads.Reset();
for(TInt i = 0; i < aNumQuads; ++i)
{
iSortedQuads.Append(iQuads[i]);
}
for (TInt i = 1; i < aNumQuads; i++)
{
for (int j = 0; j < aNumQuads; j++)
{
if( iSortedQuads[i]->iZ > iSortedQuads[j]->iZ )
{
TQuad* q1 = iSortedQuads[i];
TQuad* q2 = iSortedQuads[j];
iSortedQuads[i] = q2;
iSortedQuads[j] = q1;
}
}
}
}
// -----------------------------------------------------------------------------
// CHgVgScrollBar::GetItemIndex
// gets index of the item under pointer position.
// -----------------------------------------------------------------------------
//
TInt CHgVgMediaWallRenderer::GetItemIndex(const TPoint& aPointerPosition) const
{
for (TInt i = 0; i < iSortedQuads.Count(); i++)
{
VGfloat* verts = iSortedQuads[iSortedQuads.Count()-i-1]->iPoints;
TRect rect;
HgVgHelper::CalculateBoundingRect(rect, verts, 4, iRect);
if (rect.Contains(aPointerPosition))
{
TInt index = iSortedQuads.Count()-i-1;
return iSortedQuads[index]->iItemIndex;
}
}
return KErrNotFound;
}
// -----------------------------------------------------------------------------
// CHgVgScrollBar::TransformQuads
// Draws quads using OpenVG.
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::TransformQuads(TInt aNumVisibleQuads,
TBool aMirrored, VGfloat aFov, CHgVgMediaWall::THgVgOpeningAnimationType aOpeningAnimationType)
{
VGfloat scW = (VGfloat) iRect.Width();
VGfloat scH = (VGfloat) iRect.Height();
VGfloat imW = (VGfloat)iImageSize.iWidth;
VGfloat imH = (VGfloat)iImageSize.iHeight;
// construct mirror matrix
HgVgHelper::TMatrix mirrorMatrix;
mirrorMatrix.Scale(1, -1, 1);
// construct camera rotation matrix
HgVgHelper::TMatrix cameraRotMatrix;
if (iFlipXY)
{
cameraRotMatrix.RotationX(iCameraRotation);
}
else
{
cameraRotMatrix.RotationY(iCameraRotation);
}
// mat[0] = transform
// mat[1] = mirrored transform
HgVgHelper::TMatrix mat[2];
VGfloat cameraX = iCameraBaseX + iCameraX;
VGfloat cameraY = iCameraBaseY + iCameraY;
VGfloat cameraZ = iCameraBaseZ + iCameraZ;
if (iFlipXY)
{
VGfloat foobar = cameraX;
cameraX = cameraY;
cameraY = foobar;
}
// scaling matrix is used to set correct size for the
// quad by image size
VGfloat hImW = (VGfloat)KWorldQuadWidth * 0.5f;
VGfloat hImH = (VGfloat)imH * (KWorldQuadWidth / imW) * 0.5f;
VGfloat oldHImH = hImH;
// flips image upside down
HgVgHelper::TMatrix scaleMatrix;
scaleMatrix.Scale(hImW, -hImH, 1); // negative scale because our all images are updaside down.
TBool deform =
(aOpeningAnimationType == CHgVgMediaWall::EHgVgOpeningAnimationFlipToFront) ||
(aOpeningAnimationType == CHgVgMediaWall::EHgVgOpeningAnimationZoomToFront);
for (TInt j = 0; j < aNumVisibleQuads; j++)
{
TQuad* q = iQuads[j];
if (q->iFlipped && deform)
{
// animate scaling to flipped rect size
VGfloat newH = (VGfloat)iFlippedHeight * (KWorldQuadWidth / iFlippedWidth) * 0.5f;
hImH = HgVgHelper::Lerp(hImH, newH, iBlurAlpha);
mat[0].Identity();
mat[0].Scale(hImW, -hImH, 1);
}
else
{
// restore old normal half image height
hImH = oldHImH;
mat[0] = scaleMatrix;
}
// rotMatrix rotates by quads angle
HgVgHelper::TMatrix rotMatrix;
rotMatrix.RotationY(-q->iAngle);
// trMatrix translates by quads position
HgVgHelper::TMatrix trMatrix;
trMatrix.Translation(q->iX, q->iY + hImH, q->iZ);
// then rotate
if (q->iAngle != 0)
{
mat[0].Multiply(rotMatrix);
}
// then translate to position
mat[0].Multiply(trMatrix);
// construct mirroring matrix
if (aMirrored)
{
mat[1] = mat[0];
mat[1].Multiply(mirrorMatrix);
}
// construct camera translation matrix
HgVgHelper::TMatrix cameraMatrix;
cameraMatrix.Translation(-cameraX, -cameraY - hImH, -cameraZ);
// apply camera movement
mat[0].Multiply(cameraMatrix);
// apply camera rotation hack
mat[0].Multiply(cameraRotMatrix);
// apply to mirror matrix also
if (aMirrored)
{
mat[1].Multiply(cameraMatrix);
mat[1].Multiply(cameraRotMatrix);
}
// transform all points by resulting transformation matrix
// and project to screen coordinates.
TInt count = aMirrored ? 2 : 1;
for (TInt k = 0; k < count; k++)
{
VGfloat* tverts = NULL;
VGfloat* tm = NULL;
if (k == 0)
{
tverts = q->iPoints;
tm = q->iTM;
}
else
{
tverts = q->iMirroredPoints;
tm = q->iMirroredTM;
}
for (TInt i = 0; i < 4; i++)
{
HgVgHelper::TVertex v;
v.iX = KQuadVerts[i*3+0];
v.iY = KQuadVerts[i*3+1];
v.iZ = KQuadVerts[i*3+2];
v.TransformPoint(mat[k]);
v.ProjectPoint(scW, scH, aFov);
tverts[i*2+0] = v.iScreenX;
tverts[i*2+1] = v.iScreenY;
}
VGImage image = q->iNoImage ? iDefaultImage : q->iImage;
VGfloat pxWidth = vgGetParameteri(image, VG_IMAGE_WIDTH);
VGfloat pxHeight = vgGetParameteri(image, VG_IMAGE_HEIGHT);
// use screen coordinates to build warp matrix
// for rendering the image
vguComputeWarpQuadToQuad(tverts[0], tverts[1], tverts[2], tverts[3],
tverts[4], tverts[5], tverts[6], tverts[7], 0, 0, pxWidth, 0,
pxWidth, pxHeight, 0, pxHeight, tm);
}
}
}
// -----------------------------------------------------------------------------
// CHgVgScrollBar::DrawQuads
// Draws quads using OpenVG.
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::DrawQuads(TBool aDrawMirrored)
{
VGfloat values[] = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 };
vgSeti(VG_COLOR_TRANSFORM, VG_TRUE);
for (TInt j = 0; j < iSortedQuads.Count(); j++)
{
TQuad* q = iSortedQuads[j];
if (q->iAlpha < 0.01f)
continue;
values[3] = q->iAlpha;
vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, values);
if (q->iZ < 0)
continue;
DrawQuad(q, aDrawMirrored);
}
vgSeti(VG_COLOR_TRANSFORM, VG_FALSE);
}
// -----------------------------------------------------------------------------
// CHgVgMediaWallRenderer::DrawQuad
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::DrawQuad(CHgVgMediaWallRenderer::TQuad* q, TBool aDrawMirrored)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgLoadIdentity();
//vgTranslate(iOffset.iX, iOffset.iY);
VGImage image = q->iImage;
if (q->iNoImage)
{
image = iDefaultImage;
}
if (aDrawMirrored)
{
vgMultMatrix(q->iMirroredTM);
}
else
{
vgMultMatrix(q->iTM);
if ((iBlurImage != VG_INVALID_HANDLE) && (iChildBlurImage != VG_INVALID_HANDLE) && q->iFlipped)
{
vgGaussianBlur(iChildBlurImage, image, iBlurDeviationX*iBlurAlpha,
iBlurDeviationY*iBlurAlpha, VG_TILE_PAD);
image = iChildBlurImage;
}
}
vgDrawImage(image);
}
// -----------------------------------------------------------------------------
// CHgVgScrollBar::Draw()
// -----------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::Draw(RPointerArray<CHgVgItem>& aItems,
TInt aSelectedIndex, TReal aNextIndex,
TReal aViewPosition,
TReal aAnimationAlpha,
CHgVgMediaWall::THgVgAnimationState aState,
CHgVgMediaWall::THgVgOpeningAnimationType aSelectionAnimationType,
CHgVgMediaWall::THgVgMediaWallStyle /*aStyle*/,
TReal aStartIndex)
{
TInt itemsOnScreen = 0;
itemsOnScreen = SetupQuads(aItems,
aSelectedIndex, aNextIndex,
aViewPosition,
aAnimationAlpha,
aState, aSelectionAnimationType, aStartIndex);
TransformAndDraw(itemsOnScreen, aSelectionAnimationType);
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::DrawGrid()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::DrawGrid(
TInt aRowCount,
RPointerArray<CHgVgItem>& aItems,
TReal aViewX, TReal aViewY,
TInt aCurItem, TInt aPrevItem,
TReal aAnimationAlpha,
CHgVgMediaWall::THgVgAnimationState aAnimationState,
TInt aPickedItem,
CHgVgMediaWall::THgVgOpeningAnimationType aAnimationType)
{
TInt itemsOnScreen = 0;
for (TInt i = 0; i < aRowCount; i++)
{
SetupQuadsToRow(i, aRowCount, itemsOnScreen,
aItems, aViewX, aViewY, aCurItem, aPrevItem,
aAnimationAlpha, aAnimationState, aPickedItem,
aAnimationType);
}
TransformAndDraw(itemsOnScreen, aAnimationType);
}
TReal CHgVgMediaWallRenderer::GetWorldSpaceRowHeight() const
{
// TODO: replace these macig numbers
return (120.0 / 90.0 * 0.25 + 0.02);
}
// ---------------------------------------------------------------------------
// CHgVgCoverflowRenderer::CreateGround()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::CreateGround()
{
// Create path and paint for drawing ground plane
iGroundPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, KGroundScale, KGroundBias,
KGroundVerticesHint, KGroundSegmentsHint, (unsigned int)VG_PATH_CAPABILITY_ALL);
vguRect(iGroundPath, 0, 0, 1, 1);
VGfloat gradientStops[] = {
0, 0.0f, 0.0f, 0.0f, 1.0f,
0.01f, 0.0f, 0.0f, 0.0f, 0.95f,
1.0f, 0.0f, 0.0f, 0.0f, 0.0f
};
VGfloat groundColor[4];
GetGroundColorFromSkin(groundColor);
gradientStops[1] = groundColor[0];
gradientStops[2] = groundColor[1];
gradientStops[3] = groundColor[2];
gradientStops[6] = groundColor[0];
gradientStops[7] = groundColor[1];
gradientStops[8] = groundColor[2];
gradientStops[11] = groundColor[0];
gradientStops[12] = groundColor[1];
gradientStops[13] = groundColor[2];
iGroundPaint = vgCreatePaint();
vgSetParameteri(iGroundPaint, VG_PAINT_TYPE,
VG_PAINT_TYPE_LINEAR_GRADIENT);
vgSetParameterfv(iGroundPaint, VG_PAINT_LINEAR_GRADIENT,
KNumGroundGradientValues, KGroundGradient);
vgSetParameteri(iGroundPaint, VG_PAINT_COLOR_RAMP_SPREAD_MODE,
VG_COLOR_RAMP_SPREAD_PAD);
vgSetParameterfv(iGroundPaint, VG_PAINT_COLOR_RAMP_STOPS,
5*3, gradientStops);
}
// ---------------------------------------------------------------------------
// CHgVgCoverflowRenderer::DrawGround()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::DrawGround(TInt aWidth, TInt aHeight)
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
vgLoadIdentity();
//vgTranslate(iOffset.iX, iOffset.iY);
vgScale(aWidth, aHeight);
vgSetPaint(iGroundPaint, VG_FILL_PATH);
vgDrawPath(iGroundPath, VG_FILL_PATH);
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::SetupQuadsToRow()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::SetupQuadsToRow(
TInt aRow,
TInt aRowCount,
TInt &aItemsOnScreen,
RPointerArray<CHgVgItem>& aItems,
TReal aViewX, TReal aViewY,
TInt aCurItem, TInt aPrevItem,
TReal aAnimationAlpha,
CHgVgMediaWall::THgVgAnimationState aState,
TInt aPickedItem,
CHgVgMediaWall::THgVgOpeningAnimationType aAnimationType)
{
if (aItems.Count() <= 0)
return;
TReal src = aViewX;
TReal frac;
Math::Frac(frac, src);
VGfloat fDiff = frac;
TBool isSelectionToFocusedItem =
(
(aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateOpening) ||
(aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateClosing) ||
(aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateItemOpened)
) &&
(aAnimationType != CHgVgMediaWall::EHgVgOpeningAnimationNone);
TReal selectionAnimationAlpha = aAnimationAlpha;
if (aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateItemOpened)
selectionAnimationAlpha = 1.0f;
VGfloat leftIndex = (VGfloat)(iSelectedItemIndex - 1);
VGfloat leftX = iLeftStackEndX;
VGfloat step = iSpaceBetween;
if (AknLayoutUtils::LayoutMirrored())
{
leftX = iRightStackStartX;
step = -step;
}
TInt i = 0;
TInt currentRow = ((TInt)aViewX - (iSelectedItemIndex)) * aRowCount;
VGfloat zFar = iZNear;
VGfloat zNear = zFar - 0.8;
TInt itemsOnRow = 0;
TInt selX = aCurItem / 3;
TInt selY = aCurItem % 3;
TReal div = (TReal)(iQuads.Count()/aRowCount/2-1);
while (itemsOnRow < (iQuads.Count()/aRowCount))
{
TInt itemIndex = currentRow + i * 3 + aRow;
if (itemIndex < 0)
{
i++;
continue;
}
// all items drawn and at the end of the list, lets bail out.
if (itemIndex >= aItems.Count())
{
break;
}
TQuad* q = iQuads[aItemsOnScreen + itemsOnRow];
q->iZ = zFar;
q->iAngle = 0;
q->iFlipped = EFalse;
VGfloat fi = (VGfloat)i - fDiff;
q->iX = leftX - step * (leftIndex - fi);
q->iAlpha = 1;
q->iItemIndex = itemIndex;
if (aItems[itemIndex]->VgImage() == VG_INVALID_HANDLE)
{
q->iNoImage = ETrue;
}
else
{
q->iNoImage = EFalse;
q->iImage = aItems[itemIndex]->VgImage();
}
VGfloat imW = (VGfloat) iImageSize.iWidth;
VGfloat imH = (VGfloat) iImageSize.iHeight;
// width is constant but same aspect ratio must be preserved
VGfloat worldImageHeight = imH * (KWorldQuadWidth / imW);
q->iY = (2 - aRow) * (worldImageHeight + KSpaceBetweenGridItems);
if (aCurItem != KErrNotFound && itemIndex == aCurItem)
{
TReal alphaX = 1.0 - Min(Abs(aViewX - (TReal)selX), 1);
TReal alphaY = 1.0 - Min(Abs(aViewY - (TReal)selY), 1);
q->iZ = HgVgHelper::Lerp(zFar, zNear, Min(alphaX, alphaY));
}
else if (aPrevItem != KErrNotFound && itemIndex == aPrevItem)
{
TReal alphaX = 1.0 - Min(Abs(aViewX - (TReal)selX), 1);
TReal alphaY = 1.0 - Min(Abs(aViewY - (TReal)selY), 1);
q->iZ = HgVgHelper::Lerp(zFar, zNear, 1.0f - Min(alphaX, alphaY));
}
q->iAlpha = HgVgHelper::Lerp(1, 0, Max(0.0, (Abs(q->iX)-1.0) / div));
if (isSelectionToFocusedItem && (itemIndex == aPickedItem))
{
q->iAlpha = 1;
q->iFlipped = ETrue;
iBlurAlpha = selectionAnimationAlpha;
ApplyOpeningAnimation(q, selectionAnimationAlpha, zFar,
CHgVgMediaWall::EHgVgMediaWallStyleGrid,
aAnimationType);
}
if (iFlipXY)
{
VGfloat temp = q->iX;
q->iX = q->iY;
q->iY = -temp;
}
i++;
itemsOnRow++;
}
aItemsOnScreen += itemsOnRow;
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::SetupQuads()
// ---------------------------------------------------------------------------
//
TInt CHgVgMediaWallRenderer::SetupQuads(RPointerArray<CHgVgItem>& aItems,
TInt aSelectedIndex, TReal aNextIndex,
VGfloat aViewPosition,
VGfloat aAnimationAlpha,
CHgVgMediaWall::THgVgAnimationState aState,
CHgVgMediaWall::THgVgOpeningAnimationType aOpeningAnimationType,
TReal aStartIndex)
{
if (aItems.Count() <= 0)
return 0;
VGfloat selectionAnimationAlpha = aAnimationAlpha;
TBool isSelectionToFocusedItem =
((aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateOpening) ||
(aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateClosing) ||
(aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateItemOpened)) &&
(aOpeningAnimationType != CHgVgMediaWall::EHgVgOpeningAnimationNone);
if (aState == CHgVgMediaWall::EHgVgMediaWallAnimationStateItemOpened)
selectionAnimationAlpha = 1.0f;
TReal src = aViewPosition;
TReal frac;
Math::Frac(frac, src);
VGfloat fDiff = frac;
VGfloat leftIndex = (VGfloat)(iSelectedItemIndex - 1);
VGfloat leftX = iLeftStackEndX;
VGfloat step = iSpaceBetween;
// support mirrored layouts (right-to-left reading)
if (AknLayoutUtils::LayoutMirrored())
{
leftX = -iLeftStackEndX;
step = -step;
}
TInt i = 0;
TInt itemsOnScreen = 0;
TInt currentRow = (TInt)aViewPosition - KSelectedItemIndex;
while (itemsOnScreen < iQuads.Count())
{
TInt itemIndex = currentRow + i;
// not really an item
if (itemIndex < 0)
{
i++;
continue;
}
// got past all items
if (itemIndex >= aItems.Count())
{
break;
}
// setup quads to represent coverflow
TQuad* q = iQuads[itemsOnScreen];
q->iY = 0;
q->iZ = iZFar;
q->iAngle = 0;
q->iFlipped = EFalse;
VGfloat fi = (VGfloat)i - fDiff;
q->iX = leftX - step * (leftIndex - fi);
if (aStartIndex != aNextIndex)
{
// if start and next index are not same, we can just interpolate
// items at these indices.
if (itemIndex == (TInt)aStartIndex ||
itemIndex == (TInt)aNextIndex)
{
q->iZ = HgVgHelper::Lerp((VGfloat)iZNear, (VGfloat)iZFar, Abs(q->iX / leftX));
q->iZ = Min(q->iZ, (VGfloat)iZFar);
}
}
else
{
// in this case we are just dragging and startindex and left index are
// same so we need to interpolate z for all items coming/leaving center
// of the screen.
q->iZ = HgVgHelper::Lerp((VGfloat)iZNear, (VGfloat)iZFar, Abs(q->iX / leftX));
q->iZ = Min(q->iZ, (VGfloat)iZFar);
}
// calculate alpha so that items further are more transparent.
q->iAlpha = HgVgHelper::Lerp(1, 0, Max(0.0, (Abs(q->iX)-2.0) / (TReal)(iQuads.Count()/2-2)));
q->iItemIndex = itemIndex;
// setup image to quad from item
if (aItems[itemIndex]->VgImage() == VG_INVALID_HANDLE)
{
q->iNoImage = ETrue;
}
else
{
q->iNoImage = EFalse;
q->iImage = aItems[itemIndex]->VgImage();
}
// apply opening animation to item if needed
if (isSelectionToFocusedItem && (itemIndex == aSelectedIndex))
{
q->iAlpha = 1;
q->iFlipped = ETrue;
iBlurAlpha = selectionAnimationAlpha;
ApplyOpeningAnimation(q, selectionAnimationAlpha, q->iZ,
CHgVgMediaWall::EHgVgMediaWallStyleCoverflowFullScreen,
aOpeningAnimationType);
}
i++;
itemsOnScreen++;
}
return itemsOnScreen;
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::ApplyFlipAnimation()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::ApplyOpeningAnimation(CHgVgMediaWallRenderer::TQuad* aQuad,
TReal aAnimationAlpha, TReal aZNear, CHgVgMediaWall::THgVgMediaWallStyle /*aMediaWallStyle*/,
CHgVgMediaWall::THgVgOpeningAnimationType aAnimationStyle)
{
VGfloat wz = 0.0f;
VGfloat wy = (iCameraBaseY + iCameraY);
VGfloat wx = (iCameraBaseX + iCameraX);
VGfloat angle = 0;
if (aAnimationStyle == CHgVgMediaWall::EHgVgOpeningAnimationFlipToFront)
{
wz = iFlippedZ;
angle = iFlipAngle;
wx += iFlippedX;
wy += iFlippedY;
}
else if (aAnimationStyle == CHgVgMediaWall::EHgVgOpeningAnimationZoomToFront)
{
wz = iFlippedZ;
wx += iFlippedX;
wy += iFlippedY;
}
if (iBlurImage != VG_INVALID_HANDLE)
{
VGImage image = aQuad->iNoImage ? iDefaultImage : aQuad->iImage;
UpdateBlurChildImage(image);
}
aQuad->iZ = HgVgHelper::Lerp(aZNear, wz, aAnimationAlpha);
aQuad->iX = HgVgHelper::Lerp(aQuad->iX, wx, aAnimationAlpha);
aQuad->iY = HgVgHelper::Lerp(aQuad->iY, wy, aAnimationAlpha);
aQuad->iAngle = -aAnimationAlpha * angle;
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::GetGroundColorFromSkin()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::GetGroundColorFromSkin(VGfloat* aColor)
{
TRgb color(KRgbBlack);
// get text color from skin
if ( AknsUtils::AvkonSkinEnabled() )
{
// this does not modify color unless it gets a correct one
// no real need to check errors
AknsUtils::GetCachedColor(
AknsUtils::SkinInstance(),
color,
KAknsIIDQsnTextColors,
EAknsCIQsnTextColorsCG6 );
}
if (color.Blue() < 128)
color = KRgbWhite;
else
color = KRgbBlack;
aColor[0] = (VGfloat)color.Red() / KColorByteToFloat;
aColor[1] = (VGfloat)color.Green() / KColorByteToFloat;
aColor[2] = (VGfloat)color.Blue() / KColorByteToFloat;
aColor[3] = 1.0f;
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::HandleSkinChange()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::HandleSkinChange()
{
vgDestroyPaint(iGroundPaint);
vgDestroyPath(iGroundPath);
CreateGround();
}
// ---------------------------------------------------------------------------
// CHgVgMediaWallRenderer::AdjustSettingsBaseOnFrontRect()
// ---------------------------------------------------------------------------
//
void CHgVgMediaWallRenderer::AdjustSettingsBasedOnRects(const TRect& aFrontRect,
TReal aZOffset)
{
// size of the images should be the same as given for aFrontRect
iImageSize = aFrontRect.Size();
// calculate screen center point
TPoint center(iRect.Width()/2, iRect.Height()/2);
// near z coordinate is calculated so that the size of the quad at front matches
// aFrontRect
iZNear = GetZInWorldSpaceBasedOnWidth(aFrontRect.Width());
iZFar = iZNear + aZOffset;
// width is always constant
VGfloat ImW = KWorldQuadWidth;
// height is altered by image aspect ratio
VGfloat ImH = (VGfloat)(iImageSize.iHeight) * (KWorldQuadWidth / (VGfloat)iImageSize.iWidth);
// camera coordinates are altered so that the front quad
// is at correct place
VGfloat deltaX = aFrontRect.Center().iX - center.iX;
VGfloat deltaY = aFrontRect.Center().iY - center.iY;
iCameraBaseX = ImW * (deltaX / (VGfloat)iImageSize.iWidth);
iCameraBaseY = ImH * (deltaY / (VGfloat)iImageSize.iHeight);
iCameraBaseZ = 0;
}
void CHgVgMediaWallRenderer::TransformAndDraw(TInt itemsOnScreen,
CHgVgMediaWall::THgVgOpeningAnimationType aOpeningAnimationType)
{
/*
vgSeti( VG_SCISSORING, VG_TRUE );
VGfloat rects[4];
rects[0]= 0;
rects[1]= 0;
rects[2]= iRect.Width();
rects[3]= iRect.Height();
vgSetfv( VG_SCISSOR_RECTS, 4, rects );
*/
vgSeti( VG_SCISSORING, VG_FALSE );
if (itemsOnScreen > 0)
{
// draw reflections
TransformQuads(itemsOnScreen,
iReflectionsEnabled, iFov, aOpeningAnimationType);
SortQuads(itemsOnScreen);
if (iReflectionsEnabled)
DrawQuads(ETrue);
DrawGround(iRect.Width(), iRect.Height() / KGroundHeightFactor);
DrawQuads(EFalse);
}
else
{
// if no items exists, just draw ground plane.
DrawGround(iRect.Width(), iRect.Height() / KGroundHeightFactor);
}
//vgSeti( VG_SCISSORING, VG_FALSE );
}
void CHgVgMediaWallRenderer::SetReflections(TBool aEnabled)
{
iReflectionsEnabled = aEnabled;
}
TBool CHgVgMediaWallRenderer::ReflectionsEnabled() const
{
return iReflectionsEnabled;
}
TSize CHgVgMediaWallRenderer::ImageSize() const
{
return iImageSize;
}
void CHgVgMediaWallRenderer::SetFlippedRect(const TRect& aFlippedRect)
{
iFlippedWidth = aFlippedRect.Width();
iFlippedHeight = aFlippedRect.Height();
iFlippedZ = GetZInWorldSpaceBasedOnWidth(aFlippedRect.Width());
TPoint center = iRect.Center();
VGfloat ImW = KWorldQuadWidth;
VGfloat ImH = (VGfloat)(iImageSize.iHeight) * (KWorldQuadWidth / (VGfloat)iImageSize.iWidth);
VGfloat deltaX = aFlippedRect.Center().iX - center.iX;
VGfloat deltaY = aFlippedRect.Center().iY - center.iY;
iFlippedY = -ImH * (deltaY / (VGfloat)aFlippedRect.Height());
iFlippedX = ImW * (deltaX / (VGfloat)aFlippedRect.Width());
}
VGfloat CHgVgMediaWallRenderer::GetZInWorldSpaceBasedOnWidth(VGfloat aWidth)
{
// calculate screen center point
TPoint center(iRect.Width()/2, iRect.Height()/2);
// Z-coordinate is set so that the front quad has
// the correct size
TReal hw = iRect.Width() * 0.5f;
TReal alpha = iFov / 2.0f;
TReal tanAlpha;
Math::Tan(tanAlpha, alpha);
TReal d = hw / tanAlpha;
return (d * (-KWorldQuadWidth/2)) / ((TReal)(center.iX - aWidth/2) - hw);
}
void CHgVgMediaWallRenderer::SetFlipAngle(TReal aAngle)
{
iFlipAngle = aAngle;
}
void CHgVgMediaWallRenderer::EnableBlurOnFlip(TBool aEnabled, TReal aBlurX, TReal aBlurY)
{
if (iBlurImage != VG_INVALID_HANDLE)
{
vgDestroyImage(iBlurImage);
iBlurImage = VG_INVALID_HANDLE;
}
if (aEnabled)
{
iBlurDeviationX = aBlurX;
iBlurDeviationY = aBlurY;
iBlurImage = vgCreateImage(VG_sRGBA_8888_PRE, iImageSize.iWidth, iImageSize.iHeight,
VG_IMAGE_QUALITY_NONANTIALIASED);
}
}
void CHgVgMediaWallRenderer::UpdateBlurChildImage(VGImage aImage)
{
VGint width = vgGetParameteri(aImage, VG_IMAGE_WIDTH);
VGint height = vgGetParameteri(aImage, VG_IMAGE_HEIGHT);
if (iBlurImageWidth != width || iBlurImageHeight != height)
{
vgDestroyImage(iChildBlurImage);
iChildBlurImage = vgChildImage(iBlurImage, 0, 0, width, height);
iBlurImageWidth = width;
iBlurImageHeight = height;
}
}
void CHgVgMediaWallRenderer::SetOffset(const TPoint& aOffset)
{
iOffset = aOffset;
}
void CHgVgMediaWallRenderer::EnableFlipXY(TBool aEnabled)
{
iFlipXY = aEnabled;
}
// End of File