diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiCurvePath.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiCurvePath.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,418 @@ +/* +* Copyright (c) 2006-2007 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: Implementation for CHuiCurvePath. Curve paths are composed of +* path segments and can be used as mapping functions, and in +* line visuals. +* +*/ + + + +#include "uiacceltk/HuiCurvePath.h" +#include "HuiRenderPlugin.h" +#include "uiacceltk/HuiRealPoint.h" +#include "uiacceltk/HuiUtil.h" +#include "uiacceltk/HuiStatic.h" +#include "uiacceltk/huifixmath.h" +#include "huicurvepathprivdata.h" +#include + + + +EXPORT_C CHuiCurvePath* CHuiCurvePath::NewL() + { + CHuiCurvePath* self = CHuiCurvePath::NewLC(); + CleanupStack::Pop(self); + return self; + } + + +EXPORT_C CHuiCurvePath* CHuiCurvePath::NewLC() + { + // Create a curve path suitable for the current renderer. + CHuiCurvePath* self = CHuiStatic::Renderer().CreateCurvePathL(); + self->iExtension = new (ELeave) THuiCurvePathExtension; + self->iExtension->iLooped = ETrue; + self->iExtension->iLegacyAPIUsed = EFalse; + self->iExtension->iVisual = NULL; + CleanupStack::PushL(self); + return self; + } + + +EXPORT_C CHuiCurvePath::CHuiCurvePath() + : iExtension(NULL), iChanged(ETrue) + { + } + + +EXPORT_C CHuiCurvePath::~CHuiCurvePath() + { + iSegments.Close(); + delete iExtension; + } + + +EXPORT_C void CHuiCurvePath::Reset() + { + iSegments.Reset(); + iTotalLength = 0; + iOffset.Set(TPoint(0, 0)); + iPosOrigin = 0; + iChanged = ETrue; + } + + +EXPORT_C void CHuiCurvePath::EnableLoop(TBool aEnable) + { + iExtension->iLooped = aEnable; + iChanged = ETrue; + } + + +EXPORT_C TBool CHuiCurvePath::Loop() const + { + return iExtension->iLooped; + } + + +EXPORT_C TBool CHuiCurvePath::NeedUpdate() const + { + if ( iOffset.Changed() ) + { + return ETrue; + } + + return iNeedUpdate; + } + +EXPORT_C void CHuiCurvePath::SetNeedsUpdate() + { + iNeedUpdate = ETrue; + } + + +EXPORT_C void CHuiCurvePath::SetOrigin(TReal32 aPosOrigin) __SOFTFP + { + iPosOrigin = aPosOrigin; + iNeedUpdate = ETrue; + iChanged = ETrue; + } + + +/** + * @deprecated + */ +EXPORT_C void +CHuiCurvePath::AppendLineL(const TPoint& aStart, const TPoint& aEnd, + TReal32 aLength) __SOFTFP + { + AppendLineL(THuiRealPoint(aStart), THuiRealPoint(aEnd), aLength); + iExtension->iLegacyAPIUsed = ETrue; + } + + +EXPORT_C void +CHuiCurvePath::AppendLineL(const THuiRealPoint& aStart, const THuiRealPoint& aEnd, + TReal32 aLength) __SOFTFP + { + TSegment segment; + segment.iType = ESegmentTypeLine; + segment.iOrigin = aStart; + segment.iDelta = aEnd - aStart; + segment.iStartAngle = segment.iAngleDelta = 0; + if(aLength < 0) + { + TReal length2 = segment.iDelta.iX * segment.iDelta.iX + + segment.iDelta.iY * segment.iDelta.iY; + TReal target; + Math::Sqrt(target, length2); + segment.iLength = TReal32(target); + } + else + { + segment.iLength = aLength; + } + TReal32 length = CalculateLength(); + segment.iTotalPos = length; + + User::LeaveIfError(iSegments.Append(segment)); + + iTotalLength = length + segment.iLength; + iNeedUpdate = ETrue; + iChanged = ETrue; + } + + +/** + * @deprecated + */ +EXPORT_C void +CHuiCurvePath::AppendArcL(const TPoint& aOrigin, const TSize& aSize, + TReal32 aStartAngle, TReal32 aEndAngle, + TReal32 aLength) __SOFTFP + { + AppendArcL(THuiRealPoint(aOrigin), THuiRealSize(aSize), aStartAngle, aEndAngle, aLength); + iExtension->iLegacyAPIUsed = ETrue; + } + + + +EXPORT_C void +CHuiCurvePath::AppendArcL(const THuiRealPoint& aOrigin, const THuiRealSize& aSize, + TReal32 aStartAngle, TReal32 aEndAngle, + TReal32 aLength) __SOFTFP + { + TSegment segment; + segment.iType = ESegmentTypeArc; + segment.iOrigin = aOrigin; + segment.iDelta = THuiRealPoint(aSize.iWidth, aSize.iHeight); + segment.iStartAngle = aStartAngle; + segment.iAngleDelta = aEndAngle - aStartAngle; + if(aLength < 0) + { + // Calculate ellipse arc length. + // Approximation: 2 * pi * sqrt((a^2+b^2)/2) + TReal temp = 0; + TReal a = (aSize.iWidth*aSize.iWidth + + aSize.iHeight*aSize.iHeight) / 2.0; + Math::Sqrt(temp, a); + TReal32 angleLength = segment.iAngleDelta; + if(angleLength < 0) + { + angleLength = -angleLength; + } + segment.iLength = 2.f * KPi * temp * angleLength / 360.f; + } + else + { + segment.iLength = aLength; + } + + TReal32 length = CalculateLength(); + segment.iTotalPos = length; + + User::LeaveIfError(iSegments.Append(segment)); + + iTotalLength = length + segment.iLength; + iNeedUpdate = ETrue; + iChanged = ETrue; + } + + +EXPORT_C TReal32 CHuiCurvePath::CalculateLength() const + { + TReal32 length = 0; + + for(TInt i = 0; i < iSegments.Count(); ++i) + { + length += iSegments[i].iLength; + } + return length; + } + + +EXPORT_C TReal32 CHuiCurvePath::Length() const __SOFTFP + { + return iTotalLength; + } + + +EXPORT_C void CHuiCurvePath::Evaluate(TReal32 aPos, THuiRealPoint& aPoint) const __SOFTFP + { + if(!iSegments.Count()) + { + // No segments to evalute. + aPoint = THuiRealPoint(0.f, 0.f); + return; + } + + aPos += iPosOrigin; + + TReal32 length = Length(); + if(iExtension->iLooped) + { + // Wrap to range so that negative positions are mapped to the end. + HuiUtil::WrapValue(aPos, 0.f, length); + } + else + { + aPos = Max(0.f, aPos); + aPos = Min(aPos, length); + } + + if(aPos < 0) + { + // Not a valid position on the path. Beginning of the first segment. + EvaluateSegment(0.f, iSegments[0], aPoint); + return; + } + + for(TInt i = 0; i < iSegments.Count(); ++i) + { + const TSegment& segment = iSegments[i]; + + if(aPos < segment.iLength) + { + EvaluateSegment(aPos, segment, aPoint); + return; + } + + aPos -= segment.iLength; + } + + // The position is past the end of the last segment. + const TSegment& lastSegment = iSegments[iSegments.Count() - 1]; + EvaluateSegment(lastSegment.iLength, lastSegment, aPoint); + } + + +EXPORT_C TInt CHuiCurvePath::SegmentCount() const + { + return iSegments.Count(); + } + + +EXPORT_C CHuiCurvePath::TSegment CHuiCurvePath::Segment(TInt aIndex) const + { + return iSegments[aIndex]; + } + + +EXPORT_C void CHuiCurvePath::EvaluateSegment(TReal32 aPos, const TSegment& aSegment, + THuiRealPoint& aPoint, + THuiRealPoint* aNormal) const + { + // aPos is in range [0,width]. + if(aSegment.iLength > 0) + { + // Normalize position. + aPos /= aSegment.iLength; + } + + if(aSegment.iType == ESegmentTypeLine) + { + aPoint.iX = aSegment.iOrigin.iX + aPos * aSegment.iDelta.iX; + aPoint.iY = aSegment.iOrigin.iY + aPos * aSegment.iDelta.iY; + + if(aNormal) + { + aNormal->iX = -aSegment.iDelta.iY; + aNormal->iY = aSegment.iDelta.iX; + HuiUtil::QuickNormalize(*aNormal); + } + } + else if(aSegment.iType == ESegmentTypeArc) + { + TReal a = 0.0; + TReal b = 0.0; + const TReal angle = ((aSegment.iStartAngle + aPos * aSegment.iAngleDelta) / 180.f ) * KPi; + + Math::Cos( a, angle ); + Math::Sin( b, angle ); + + aPoint.iX = aSegment.iOrigin.iX + aSegment.iDelta.iX * a; + aPoint.iY = aSegment.iOrigin.iY + aSegment.iDelta.iY * b; + + if(aNormal) + { + aNormal->iX = a * aSegment.iDelta.iX; + aNormal->iY = b * aSegment.iDelta.iY; + HuiUtil::QuickNormalize(*aNormal); + + // Reverse normal, if arc going the other way. + if(aSegment.iAngleDelta > 0) + { + aNormal->iX = -aNormal->iX; + aNormal->iY = -aNormal->iY; + } + } + } + else + { + // for PC lint + } + + // Apply an offset. + aPoint += iOffset.RealNow(); + } + + +EXPORT_C TReal32 CHuiCurvePath::MapValue(TReal32 aValue, TInt aComponent) const __SOFTFP + { + THuiRealPoint point; + Evaluate(aValue, point); + if(aComponent == 0) + { + return point.iX; + } + else + { + return point.iY; + } + } + + +EXPORT_C TBool CHuiCurvePath::MappingFunctionChanged() const + { + return iChanged; + } + + +EXPORT_C void CHuiCurvePath::MappingFunctionClearChanged() + { + iChanged = EFalse; + } + + +EXPORT_C void CHuiCurvePath::Update(TReal32 /*aStartPos*/, + TReal32 /*aEndPos*/, + TReal32 /*aAlphaFactor*/, + MHuiMappingFunction* /*aAlphaFunction*/, + MHuiMappingFunction* /*aWidthFunction*/) __SOFTFP + { + iNeedUpdate = EFalse; + iOffset.ClearChanged(); + } + + +EXPORT_C void CHuiCurvePath::Draw(const TPoint& /*aOrigin*/, CHuiGc* /*aGc*/) const + { + } + +EXPORT_C void CHuiCurvePath::SetVisual(const CHuiVisual* aVisual) const + { + if (!iExtension->iLegacyAPIUsed) + { + iExtension->iVisual = const_cast(aVisual); + } + } + +EXPORT_C const CHuiVisual* CHuiCurvePath::GetVisual() const + { + return iExtension->iVisual; + } + + +EXPORT_C TBool CHuiCurvePath::IsLegacyApiUsed() const + { + return(iExtension->iLegacyAPIUsed); + } + +EXPORT_C void CHuiCurvePath::CurvePathExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams) + { + // If no extension with given UID was found, indicate it by returning null + *aExtensionParams = NULL; + } +