uiacceltk/hitchcock/coretoolkit/src/HuiCurvePath.cpp
changeset 0 15bf7259bb7c
--- /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 <e32math.h>
+
+
+
+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<CHuiVisual*>(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;
+    }
+