uiacceltk/hitchcock/coretoolkit/src/HuiCurvePath.cpp
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Implementation for CHuiCurvePath. Curve paths are composed of 
       
    15 *                path segments and can be used as mapping functions, and in 
       
    16 *                line visuals.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 #include "uiacceltk/HuiCurvePath.h"
       
    23 #include "HuiRenderPlugin.h"
       
    24 #include "uiacceltk/HuiRealPoint.h"
       
    25 #include "uiacceltk/HuiUtil.h"
       
    26 #include "uiacceltk/HuiStatic.h"
       
    27 #include "uiacceltk/huifixmath.h"
       
    28 #include "huicurvepathprivdata.h"
       
    29 #include <e32math.h>
       
    30 
       
    31 
       
    32 
       
    33 EXPORT_C CHuiCurvePath* CHuiCurvePath::NewL()
       
    34     {
       
    35     CHuiCurvePath* self = CHuiCurvePath::NewLC();
       
    36     CleanupStack::Pop(self);
       
    37     return self;
       
    38     }
       
    39     
       
    40     
       
    41 EXPORT_C CHuiCurvePath* CHuiCurvePath::NewLC()
       
    42     {
       
    43     // Create a curve path suitable for the current renderer.
       
    44     CHuiCurvePath* self = CHuiStatic::Renderer().CreateCurvePathL();
       
    45     self->iExtension = new (ELeave) THuiCurvePathExtension;
       
    46     self->iExtension->iLooped = ETrue;
       
    47     self->iExtension->iLegacyAPIUsed = EFalse;
       
    48     self->iExtension->iVisual = NULL;
       
    49     CleanupStack::PushL(self);
       
    50     return self;
       
    51     }
       
    52 
       
    53 
       
    54 EXPORT_C CHuiCurvePath::CHuiCurvePath()
       
    55         : iExtension(NULL), iChanged(ETrue)
       
    56     {
       
    57     }
       
    58     
       
    59     
       
    60 EXPORT_C CHuiCurvePath::~CHuiCurvePath()
       
    61     {
       
    62     iSegments.Close();
       
    63     delete iExtension;
       
    64     }
       
    65   
       
    66     
       
    67 EXPORT_C void CHuiCurvePath::Reset()
       
    68     {
       
    69     iSegments.Reset();
       
    70     iTotalLength = 0;
       
    71     iOffset.Set(TPoint(0, 0));
       
    72     iPosOrigin = 0;
       
    73     iChanged = ETrue;
       
    74     }
       
    75     
       
    76       
       
    77 EXPORT_C void CHuiCurvePath::EnableLoop(TBool aEnable)
       
    78     {
       
    79     iExtension->iLooped = aEnable;
       
    80     iChanged = ETrue;
       
    81     }
       
    82 
       
    83 
       
    84 EXPORT_C TBool CHuiCurvePath::Loop() const
       
    85     {
       
    86     return iExtension->iLooped;
       
    87     }
       
    88     
       
    89     
       
    90 EXPORT_C TBool CHuiCurvePath::NeedUpdate() const
       
    91     {
       
    92     if ( iOffset.Changed() )
       
    93         {
       
    94         return ETrue;
       
    95         }
       
    96     
       
    97     return iNeedUpdate;
       
    98     }
       
    99     
       
   100 EXPORT_C void CHuiCurvePath::SetNeedsUpdate()
       
   101     {
       
   102     iNeedUpdate = ETrue;
       
   103     }
       
   104     
       
   105     
       
   106 EXPORT_C void CHuiCurvePath::SetOrigin(TReal32 aPosOrigin) __SOFTFP
       
   107     {
       
   108     iPosOrigin = aPosOrigin;
       
   109     iNeedUpdate = ETrue;    
       
   110     iChanged = ETrue;
       
   111     }
       
   112 
       
   113 
       
   114 /**
       
   115  * @deprecated 
       
   116  */
       
   117 EXPORT_C void 
       
   118 CHuiCurvePath::AppendLineL(const TPoint& aStart, const TPoint& aEnd, 
       
   119                            TReal32 aLength) __SOFTFP
       
   120     {
       
   121     AppendLineL(THuiRealPoint(aStart), THuiRealPoint(aEnd), aLength);
       
   122     iExtension->iLegacyAPIUsed = ETrue;
       
   123     }
       
   124     
       
   125 
       
   126 EXPORT_C void 
       
   127 CHuiCurvePath::AppendLineL(const THuiRealPoint& aStart, const THuiRealPoint& aEnd, 
       
   128                            TReal32 aLength) __SOFTFP
       
   129     {
       
   130     TSegment segment;
       
   131     segment.iType = ESegmentTypeLine;
       
   132     segment.iOrigin = aStart;
       
   133     segment.iDelta = aEnd - aStart;
       
   134     segment.iStartAngle = segment.iAngleDelta = 0;
       
   135     if(aLength < 0)
       
   136         {
       
   137         TReal length2 = segment.iDelta.iX * segment.iDelta.iX + 
       
   138                         segment.iDelta.iY * segment.iDelta.iY;
       
   139         TReal target;
       
   140         Math::Sqrt(target, length2);
       
   141         segment.iLength = TReal32(target);
       
   142         }
       
   143     else
       
   144         {
       
   145         segment.iLength = aLength;
       
   146         }
       
   147     TReal32 length = CalculateLength();        
       
   148     segment.iTotalPos = length;
       
   149 
       
   150     User::LeaveIfError(iSegments.Append(segment)); 
       
   151     
       
   152     iTotalLength = length + segment.iLength;
       
   153     iNeedUpdate = ETrue;
       
   154     iChanged = ETrue;
       
   155     }
       
   156     
       
   157 
       
   158 /**
       
   159  * @deprecated 
       
   160  */
       
   161 EXPORT_C void 
       
   162 CHuiCurvePath::AppendArcL(const TPoint& aOrigin, const TSize& aSize,
       
   163                           TReal32 aStartAngle, TReal32 aEndAngle,
       
   164                           TReal32 aLength) __SOFTFP
       
   165     {
       
   166     AppendArcL(THuiRealPoint(aOrigin), THuiRealSize(aSize), aStartAngle, aEndAngle, aLength);    
       
   167     iExtension->iLegacyAPIUsed = ETrue;
       
   168     }
       
   169 
       
   170 
       
   171 
       
   172 EXPORT_C void 
       
   173 CHuiCurvePath::AppendArcL(const THuiRealPoint& aOrigin, const THuiRealSize& aSize,
       
   174                           TReal32 aStartAngle, TReal32 aEndAngle,
       
   175                           TReal32 aLength) __SOFTFP
       
   176     {
       
   177     TSegment segment;
       
   178     segment.iType = ESegmentTypeArc;
       
   179     segment.iOrigin = aOrigin;
       
   180     segment.iDelta = THuiRealPoint(aSize.iWidth, aSize.iHeight);
       
   181     segment.iStartAngle = aStartAngle;
       
   182     segment.iAngleDelta = aEndAngle - aStartAngle;
       
   183     if(aLength < 0)
       
   184         {
       
   185         // Calculate ellipse arc length.
       
   186         // Approximation: 2 * pi * sqrt((a^2+b^2)/2) 
       
   187         TReal temp = 0;
       
   188         TReal a = (aSize.iWidth*aSize.iWidth + 
       
   189                    aSize.iHeight*aSize.iHeight) / 2.0;
       
   190         Math::Sqrt(temp, a);
       
   191         TReal32 angleLength = segment.iAngleDelta;
       
   192         if(angleLength < 0)
       
   193             {
       
   194             angleLength = -angleLength;
       
   195             }
       
   196         segment.iLength = 2.f * KPi * temp * angleLength / 360.f;
       
   197         }
       
   198     else
       
   199         {
       
   200         segment.iLength = aLength;
       
   201         }
       
   202 
       
   203     TReal32 length = CalculateLength();        
       
   204     segment.iTotalPos = length;
       
   205         
       
   206     User::LeaveIfError(iSegments.Append(segment));
       
   207     
       
   208     iTotalLength = length + segment.iLength;
       
   209     iNeedUpdate = ETrue;
       
   210     iChanged = ETrue;
       
   211     }
       
   212 
       
   213 
       
   214 EXPORT_C TReal32 CHuiCurvePath::CalculateLength() const
       
   215     {
       
   216     TReal32 length = 0;
       
   217     
       
   218     for(TInt i = 0; i < iSegments.Count(); ++i)
       
   219         {
       
   220         length += iSegments[i].iLength;
       
   221         }
       
   222     return length;        
       
   223     }
       
   224     
       
   225     
       
   226 EXPORT_C TReal32 CHuiCurvePath::Length() const __SOFTFP
       
   227     {
       
   228     return iTotalLength;
       
   229     }
       
   230      
       
   231 
       
   232 EXPORT_C void CHuiCurvePath::Evaluate(TReal32 aPos, THuiRealPoint& aPoint) const __SOFTFP
       
   233     {
       
   234     if(!iSegments.Count())
       
   235         {
       
   236         // No segments to evalute.
       
   237         aPoint = THuiRealPoint(0.f, 0.f);
       
   238         return;
       
   239         }
       
   240     
       
   241     aPos += iPosOrigin;
       
   242     
       
   243     TReal32 length = Length();
       
   244     if(iExtension->iLooped)
       
   245         {
       
   246         // Wrap to range so that negative positions are mapped to the end.
       
   247         HuiUtil::WrapValue(aPos, 0.f, length);
       
   248         }
       
   249     else
       
   250         {
       
   251         aPos = Max(0.f, aPos);
       
   252         aPos = Min(aPos, length);
       
   253         }
       
   254     
       
   255     if(aPos < 0)
       
   256         {
       
   257         // Not a valid position on the path. Beginning of the first segment.
       
   258         EvaluateSegment(0.f, iSegments[0], aPoint);
       
   259         return;
       
   260         }                        
       
   261         
       
   262     for(TInt i = 0; i < iSegments.Count(); ++i)
       
   263         {
       
   264         const TSegment& segment = iSegments[i];
       
   265         
       
   266         if(aPos < segment.iLength)
       
   267             {
       
   268             EvaluateSegment(aPos, segment, aPoint);
       
   269             return;
       
   270             }
       
   271             
       
   272         aPos -= segment.iLength;
       
   273         }
       
   274         
       
   275     // The position is past the end of the last segment.
       
   276     const TSegment& lastSegment = iSegments[iSegments.Count() - 1];
       
   277     EvaluateSegment(lastSegment.iLength, lastSegment, aPoint);
       
   278     }
       
   279 
       
   280 
       
   281 EXPORT_C TInt CHuiCurvePath::SegmentCount() const
       
   282     {
       
   283     return iSegments.Count();
       
   284     }
       
   285                          
       
   286 
       
   287 EXPORT_C CHuiCurvePath::TSegment CHuiCurvePath::Segment(TInt aIndex) const
       
   288     {
       
   289     return iSegments[aIndex];
       
   290     }
       
   291 
       
   292 
       
   293 EXPORT_C void CHuiCurvePath::EvaluateSegment(TReal32 aPos, const TSegment& aSegment,
       
   294                                     THuiRealPoint& aPoint,
       
   295                                     THuiRealPoint* aNormal) const
       
   296     {
       
   297     // aPos is in range [0,width].
       
   298     if(aSegment.iLength > 0)
       
   299         {
       
   300         // Normalize position.
       
   301         aPos /= aSegment.iLength;
       
   302         }
       
   303     
       
   304     if(aSegment.iType == ESegmentTypeLine)
       
   305         {
       
   306         aPoint.iX = aSegment.iOrigin.iX + aPos * aSegment.iDelta.iX;
       
   307         aPoint.iY = aSegment.iOrigin.iY + aPos * aSegment.iDelta.iY;
       
   308         
       
   309         if(aNormal)
       
   310             {
       
   311             aNormal->iX = -aSegment.iDelta.iY;
       
   312             aNormal->iY = aSegment.iDelta.iX;
       
   313             HuiUtil::QuickNormalize(*aNormal);
       
   314             }
       
   315         }
       
   316     else if(aSegment.iType == ESegmentTypeArc)
       
   317         {
       
   318         TReal a = 0.0;
       
   319         TReal b = 0.0;
       
   320         const TReal angle = ((aSegment.iStartAngle + aPos * aSegment.iAngleDelta) / 180.f ) * KPi;
       
   321         
       
   322         Math::Cos( a, angle );
       
   323         Math::Sin( b, angle );
       
   324 
       
   325         aPoint.iX = aSegment.iOrigin.iX + aSegment.iDelta.iX * a;
       
   326         aPoint.iY = aSegment.iOrigin.iY + aSegment.iDelta.iY * b;
       
   327         
       
   328         if(aNormal)
       
   329             {
       
   330             aNormal->iX = a * aSegment.iDelta.iX;
       
   331             aNormal->iY = b * aSegment.iDelta.iY;
       
   332             HuiUtil::QuickNormalize(*aNormal);
       
   333             
       
   334             // Reverse normal, if arc going the other way.
       
   335             if(aSegment.iAngleDelta > 0)
       
   336                 {
       
   337                 aNormal->iX = -aNormal->iX;
       
   338                 aNormal->iY = -aNormal->iY;
       
   339                 }
       
   340             }
       
   341         }
       
   342     else
       
   343         {
       
   344         // for PC lint
       
   345         }
       
   346 
       
   347     // Apply an offset.        
       
   348     aPoint += iOffset.RealNow();        
       
   349     }
       
   350 
       
   351 
       
   352 EXPORT_C TReal32 CHuiCurvePath::MapValue(TReal32 aValue, TInt aComponent) const __SOFTFP
       
   353     {
       
   354     THuiRealPoint point;
       
   355     Evaluate(aValue, point);
       
   356     if(aComponent == 0)
       
   357         {
       
   358         return point.iX;
       
   359         }
       
   360     else
       
   361         {
       
   362         return point.iY;
       
   363         }
       
   364     }
       
   365     
       
   366     
       
   367 EXPORT_C TBool CHuiCurvePath::MappingFunctionChanged() const
       
   368     {
       
   369     return iChanged;
       
   370     }
       
   371     
       
   372     
       
   373 EXPORT_C void CHuiCurvePath::MappingFunctionClearChanged()
       
   374     {
       
   375     iChanged = EFalse;
       
   376     }
       
   377 
       
   378     
       
   379 EXPORT_C void CHuiCurvePath::Update(TReal32 /*aStartPos*/, 
       
   380                            TReal32 /*aEndPos*/, 
       
   381                            TReal32 /*aAlphaFactor*/,
       
   382                            MHuiMappingFunction* /*aAlphaFunction*/,
       
   383                            MHuiMappingFunction* /*aWidthFunction*/) __SOFTFP
       
   384     {
       
   385     iNeedUpdate = EFalse;
       
   386     iOffset.ClearChanged();
       
   387     }
       
   388     
       
   389 
       
   390 EXPORT_C void CHuiCurvePath::Draw(const TPoint& /*aOrigin*/, CHuiGc* /*aGc*/) const
       
   391     {
       
   392     }
       
   393 
       
   394 EXPORT_C void CHuiCurvePath::SetVisual(const CHuiVisual* aVisual) const
       
   395     {
       
   396     if (!iExtension->iLegacyAPIUsed)
       
   397         {
       
   398         iExtension->iVisual = const_cast<CHuiVisual*>(aVisual);   
       
   399         }
       
   400     }
       
   401 
       
   402 EXPORT_C const CHuiVisual* CHuiCurvePath::GetVisual() const
       
   403     {
       
   404     return iExtension->iVisual;
       
   405     }
       
   406 
       
   407 
       
   408 EXPORT_C TBool CHuiCurvePath::IsLegacyApiUsed() const
       
   409 	{
       
   410 	return(iExtension->iLegacyAPIUsed);
       
   411 	}
       
   412 
       
   413 EXPORT_C void CHuiCurvePath::CurvePathExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams)
       
   414     {
       
   415     // If no extension with given UID was found, indicate it by returning null
       
   416     *aExtensionParams = NULL;
       
   417     }
       
   418