uiacceltk/hitchcock/coretoolkit/src/HuiStatic.cpp
changeset 0 15bf7259bb7c
child 7 433cbbb6a04b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiStatic.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,1279 @@
+/*
+* 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:   Implements CHuiStatic, static data access and utility 
+*                functions such as timing.
+*
+*/
+
+
+
+#include "uiacceltk/HuiStatic.h"  // Class definition
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiEnv.h"
+#include "HuiRenderPlugin.h"
+#include "huistatictlsdata.h"
+#include "uiacceltk/HuiProbe.h"
+#include <e32math.h>
+#include <eikenv.h>
+#include <flogger.h>
+#include <AknsUtils.h>
+#include <AknUtils.h>
+#include <AknBidiTextUtils.h>
+#include <bidivisual.h>
+#include "alfappfwproxyops.h"
+
+
+
+// Global writeable data, used in HW instead of TLS which relatively slow
+#ifndef __WINSCW__
+TTlsData globalWriteableData;
+#endif
+
+void CleanupWg(TAny* aWg)
+    {   
+    RWindowGroup* wg = static_cast<RWindowGroup*>(aWg);
+    delete wg;
+    }
+
+/** Dummy implementation for HuiProbe, to be used when external probe is not set */
+NONSHARABLE_CLASS(TFakeProbe) : public MHuiProbe
+    {
+public:
+    virtual void ReportObjectLifeCycleEvent(const MHuiSessionObject&, TLifecycleEvent) {}
+    virtual void ReportProgramFlowEvent(TProgramFlowPoint, TProgramFlowEvent) {}
+    virtual void ReportProgramFlowEvent(const MHuiSessionObject&, TProgramFlowPoint, TProgramFlowEvent) {}
+    void ReportFrameRate(TInt) const {}
+    void AssociateWithCurrentSession(MHuiSessionObject&) {}
+    };
+
+
+NONSHARABLE_CLASS(CAppFwProxy): public CBase
+    {
+public:
+    class CAlfLayoutListener: public CActive
+        {
+        public:
+        CAlfLayoutListener(CAppFwProxy& aNotif):CActive(CActive::EPriorityStandard), iNotif(aNotif)
+            {
+            CActiveScheduler::Add(this);
+            iStatus = KErrNotFound;    
+            }
+
+        ~CAlfLayoutListener()
+            {
+            Cancel();    
+            }
+            
+        void RunL()
+            {           
+            iNotif.iLayoutMirrored = (iStatus.Int() > 0);         
+            SetActive();
+            TAlfCommandParams params={EAlfIsMirrorred,0,0,0};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TBuf8<1> awkwardApiDummy;
+            iNotif.iNotif.StartNotifierAndGetResponse(iStatus,TUid::Uid(KAlfAppFwProxyUid), pkg, awkwardApiDummy);            }
+    
+        void DoCancel()
+            {
+            // just wait for notifier completion    
+            User::WaitForRequest(iStatus);    
+            }    
+
+        private:
+            CAppFwProxy& iNotif;
+            };    
+
+    CAppFwProxy():iLayoutMirrored(KErrNotFound)
+        {}
+        
+    ~CAppFwProxy()
+        {
+        if (iConnected)
+            {
+            iNotif.Close();
+            delete iLayoutUpdateAo;
+			}
+		}
+    
+    TBool Connect()
+        {
+        if (!iConnected)
+            {
+            // perhaps should check also whether eikon server / notifier server exists..
+            iConnected = (iNotif.Connect() == KErrNone);
+            }
+        return iConnected;
+        }
+    
+    TBool LayoutMirrored()
+        {                
+        if ( Connect() && iLayoutMirrored == KErrNotFound)
+            {
+            TRequestStatus status;
+            TAlfCommandParams params={EAlfIsMirrorred,0,0,0};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TBuf8<1> awkwardApiDummy;
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, awkwardApiDummy);
+            User::WaitForRequest(status);
+            // order updates
+            iLayoutUpdateAo = new CAlfLayoutListener(*this);
+            if (iLayoutUpdateAo)
+                {
+                TRAP_IGNORE(iLayoutUpdateAo->RunL());
+                }
+            
+            iLayoutMirrored = (status.Int() > 0);
+            }
+     
+        return iLayoutMirrored==KErrNotFound?EFalse:iLayoutMirrored;    
+        }
+
+    TInt SoftKeyOrientation()
+        {
+        TInt ret = 0;
+        if ( Connect() )
+            {
+            TRequestStatus status;
+            TAlfCommandParams params={EAlfCbaLocation,0,0,0};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TBuf8<1> awkwardApiDummy;
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, awkwardApiDummy);
+            User::WaitForRequest(status);
+            ret = status.Int();
+            }
+        
+        return ret;    
+        }
+
+    TRect LayoutMetricsRect(TInt aType)
+        {
+        TRect ret=TRect(0,0,0,0);
+        if ( Connect() )
+            {
+            TRequestStatus status;
+            TAlfCommandParams params={EAlfLayoutMetricsRect,aType,0,0};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TPckg<TRect> retpkg(ret);
+                        
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, retpkg);
+            User::WaitForRequest(status);
+            }
+        
+        return ret;    
+        }
+  
+    TInt GetCachedColor(TRgb& aRgb, const TAknsItemID& aID,
+            const TInt aIndex )
+        {
+        if ( Connect() )
+            {
+            TRequestStatus status;
+            TAlfCommandParams params={EAlfGetCachedColor,aID.iMajor,aID.iMinor,aIndex};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TPckg<TRgb> retpkg(aRgb);
+                    
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, retpkg);
+            User::WaitForRequest(status);
+            return status.Int();
+            }
+    
+        return KErrCouldNotConnect;    
+        }
+    
+    void GetSkinBitmapL(CFbsBitmap* aBitmap, CFbsBitmap* aMask, const TAknsItemID& aID, const TDesC& aFileName, TInt aBitmapId, 
+                        TInt aMaskId, const TSize& aSize, TScaleMode aScaleMode)
+        {
+        if ( Connect() )
+            {
+            TRequestStatus status;
+            TAlfCommandParams2 params={EAlfGetSkinBitmap,aID.iMajor,aID.iMinor,aBitmapId,aMaskId,aFileName, aSize, aScaleMode};
+            TPckgC<TAlfCommandParams2> pkg(params);
+            TInt2 handles = {0,0};
+            TPckg<TInt2> retpkg(handles);
+                    
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, retpkg);
+            User::WaitForRequest(status);
+            User::LeaveIfError(status.Int());
+            if (!handles.iInt1)
+                {
+                User::Leave(KErrNotFound); 
+                }   
+            User::LeaveIfError(aBitmap->Duplicate(handles.iInt1));
+            if ( aMask && handles.iInt2 )
+                {
+                User::LeaveIfError(aMask->Duplicate(handles.iInt2));                    
+                }
+            }
+        }
+
+    void GetSkinBackgroundBitmapL(CFbsBitmap* aBitmap, const TAknsItemID& aID )
+        {
+        if ( Connect() )
+            {
+            TRequestStatus status;
+            TAlfCommandParams params={EAlfGetSkinBackgroundBitmap,aID.iMajor,aID.iMinor,0};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TInt handle = 0;
+            TPckg<TInt> retpkg(handle);
+                    
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, retpkg);
+            User::WaitForRequest(status);
+            User::LeaveIfError(status.Int());
+            User::LeaveIfError(aBitmap->Duplicate(handle));
+            }
+        }
+
+    void GetCachedSkinItemDataArrayL(const TAknsItemID& aID, TInt aType, TAlfCachedSkinItemArray& aArray)  
+        {
+        if ( Connect() )
+            {
+            TRequestStatus status;
+            TAlfCommandParams params={EGetCachedSkinItemData,aID.iMajor,aID.iMinor,aType};
+            TPckgC<TAlfCommandParams> pkg(params);
+            TPckg<TAlfCachedSkinItemArray> retpkg(aArray);
+                    
+            iNotif.StartNotifierAndGetResponse(status,TUid::Uid(KAlfAppFwProxyUid), pkg, retpkg);
+            User::WaitForRequest(status);
+            User::LeaveIfError(status.Int());
+            }
+        }
+        
+    void GetListOfWindowGroupsL(TRequestStatus& aStatus, TPtr8& aPtr)
+        {
+        if ( Connect() )
+            {
+            TAlfCommandParams params={EGetListOfWindowGroups,0,0,0};
+            TPckgC<TAlfCommandParams> pkg(params);
+            iNotif.StartNotifierAndGetResponse(aStatus,TUid::Uid(KAlfAppFwProxyUid), pkg, aPtr);
+            }        
+        }    
+    public: 
+        TBool iLayoutMirrored;
+        RNotifier iNotif;
+        TBool iConnected;
+        CAlfLayoutListener* iLayoutUpdateAo;
+    };
+
+CHuiStatic* CHuiStatic::NewLC(CHuiEnv* aPrimaryEnv)
+    {
+    CHuiStatic* self = new (ELeave) CHuiStatic();
+    CleanupStack::PushL(self);
+    self->ConstructL(aPrimaryEnv);
+    return self;
+    }
+
+
+CHuiStatic* CHuiStatic::NewL(CHuiEnv* aPrimaryEnv)
+    {
+    CHuiStatic* self = NewLC(aPrimaryEnv);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+
+CHuiStatic::CHuiStatic()
+    {
+    }
+
+
+void CHuiStatic::ConstructL(CHuiEnv* aPrimaryEnv)
+    {
+    iData = new (ELeave) TTlsData();
+    
+    iData->iPrimaryEnv = aPrimaryEnv;
+    iData->iIdCounter = -1;
+    iData->iTimeFactor = 1.0;
+    iData->iIsFirstUpdateTime = ETrue;
+    iData->iFirstUpdateTime.UniversalTime();
+    iData->iUniversalTime.UniversalTime();
+    iData->iRealUniversalTime.UniversalTime();
+    iData->iLastFpsTime.UniversalTime();
+    iData->DoInitL(); // make sure that we have infra even CCoeEnv was not there
+
+    // Re-construct the virtual table for iFakeProbe
+    iData->iFakeProbe = new (ELeave) TFakeProbe;
+    
+    iData->iAppFwProxy = new (ELeave) CAppFwProxy;
+    
+    //Register for environment change ( here system time change ) event notification
+    iChangeNotifier = CEnvironmentChangeNotifier::NewL(0, TCallBack(CHuiStatic::SettingChangedCallBack, this));
+    iChangeNotifier->Start();
+#ifndef __WINSCW__
+    globalWriteableData = *iData;
+#else
+    Dll::SetTls(iData);
+#endif
+
+#ifndef WIN32
+#ifdef HUI_DEBUG_WITH_PRINTF
+    EnableLogging();
+#endif
+#endif
+    }
+
+
+CHuiStatic::~CHuiStatic()
+    {
+    if(iData)
+        {
+        if(iData->iFakeProbe)
+            {
+            delete iData->iFakeProbe;
+            iData->iFakeProbe = NULL;
+            }
+        iData->iLogFile.Close();
+        delete iData->iAppFwProxy;
+        iData->Disconnect();
+        }
+    iChangeNotifier->Cancel();
+    delete iChangeNotifier;
+#ifdef __WINSCW__
+    Dll::FreeTls();
+#endif
+    delete iData;
+    }
+
+
+EXPORT_C TTlsData* CHuiStatic::Data()
+    {
+#ifndef __WINSCW__
+    return &globalWriteableData;
+#else
+    return static_cast<TTlsData*>(Dll::Tls());
+#endif
+    }
+
+
+void CHuiStatic::UpdateTime(TTlsData* aData)
+    {
+    ASSERT( aData );
+    // Updates the toolkit's time counters. This includes the toolkit's
+    // realtime clock, the internal absolute clock (which is affected by the
+    // time factor), the amount of elapsed time since last UpdateTime()
+    // invocation, and the amount of elapsed time since the first UpdateTime()
+    // invocation (which was done in the beginning of the first refresh).
+
+    if(aData->iIsFirstUpdateTime)
+        {
+        aData->iIsFirstUpdateTime = EFalse;
+        aData->iFirstUpdateTime.UniversalTime();
+        aData->iUniversalTime = aData->iFirstUpdateTime;
+        aData->iRealUniversalTime = aData->iUniversalTime;
+        return;
+        }
+
+    TTime now;
+    now.UniversalTime();
+
+    // Advance the toolkit's internal clock, applying the time factor.
+    if(!aData->iTimePaused)
+        {
+        aData->iInternalElapsed = now.MicroSecondsFrom(aData->iRealUniversalTime).Int64();
+        aData->iInternalElapsed = (TInt64)((TReal32)aData->iInternalElapsed * aData->iTimeFactor);
+        aData->iUniversalTime += TTimeIntervalMicroSeconds(aData->iInternalElapsed);
+        }
+    else
+        {
+        aData->iInternalElapsed = aData->iInternalElapsedBeforePausing;
+        aData->iInternalElapsedBeforePausing = 0;        
+        }
+
+    aData->iRealUniversalTime = now;      
+    }
+
+
+TUint32 CHuiStatic::MilliSecondsSinceUpdateTime()
+    {
+    TTlsData* data = Data();
+    
+    TTime now;
+    now.UniversalTime();
+    
+    return now.MicroSecondsFrom(data->iRealUniversalTime).Int64() / 1000;
+    }
+
+
+EXPORT_C CHuiEnv& CHuiStatic::Env()
+    {
+    if(!Data())
+        {
+        THuiPanic::Panic(THuiPanic::EStaticDataNotCreated);
+        }
+    return *Data()->iPrimaryEnv;
+    }
+
+
+EXPORT_C CHuiRenderPlugin& CHuiStatic::Renderer()
+    {
+    if(!Data() || !Data()->iRenderer)
+        {
+           HUI_DEBUG(_L("CHuiStatic::Renderer() - Static data or renderer not specified."));
+        THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer);
+        }
+    return *Data()->iRenderer;
+    }
+
+
+void CHuiStatic::SetRenderer(CHuiRenderPlugin& aRenderer)
+    {
+    if(!Data())
+        {
+        THuiPanic::Panic(THuiPanic::EStaticDataNotCreated);
+        }
+    Data()->iRenderer = &aRenderer;
+    }
+
+
+// @TODO SHOULD THIS BE MODIFIED SOMEHOW, OR IS THIS EXPORT OK???
+EXPORT_C CHuiBitgdiRenderPlugin& CHuiStatic::BitgdiRenderer()
+    {
+    CHuiRenderPlugin* renderer = &Renderer();
+    if(renderer->Id() != EHuiRenderPluginBitgdi)
+        {
+        HUI_DEBUG(_L("CHuiStatic::BitgdiRenderer() - Renderer cannot be used as Bitgdi renderer."));
+        THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer);
+        }
+    return *reinterpret_cast< CHuiBitgdiRenderPlugin* >(renderer);
+    }
+
+
+EXPORT_C CHuiVg10RenderPlugin& CHuiStatic::Vg10Renderer()
+    {
+    CHuiRenderPlugin* renderer = &Renderer();
+    if(renderer->Id() != EHuiRenderPluginVg10)
+        {
+        HUI_DEBUG(_L("CHuiStatic::Vg10Renderer() - Renderer cannot be used as Vg10 renderer."));
+        THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer);
+        }
+    return *reinterpret_cast< CHuiVg10RenderPlugin* >(renderer);
+    }
+
+
+EXPORT_C CHuiGles10RenderPlugin& CHuiStatic::Gles10Renderer()
+    {
+    CHuiRenderPlugin* renderer = &Renderer();
+    if(renderer->Id() != EHuiRenderPluginGles10 &&
+       renderer->Id() != EHuiRenderPluginGles11) // compatible
+        {
+        HUI_DEBUG(_L("CHuiStatic::Gles10Renderer() - Renderer cannot be used as Gles10 renderer."));
+        THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer);
+        }
+    return *reinterpret_cast< CHuiGles10RenderPlugin* >(renderer);
+    }
+
+
+EXPORT_C CHuiGles11RenderPlugin& CHuiStatic::Gles11Renderer()
+    {
+    CHuiRenderPlugin* renderer = &Renderer();
+    if(renderer->Id() != EHuiRenderPluginGles11)
+        {
+        HUI_DEBUG(_L("CHuiStatic::Gles11Renderer() - Renderer cannot be used as Gles11 renderer."));
+        THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer);
+        }
+    return *reinterpret_cast< CHuiGles11RenderPlugin* >(renderer);
+    }
+
+
+EXPORT_C CHuiGles20RenderPlugin& CHuiStatic::Gles20Renderer()
+    {
+    CHuiRenderPlugin* renderer = &Renderer();
+    if(renderer->Id() != EHuiRenderPluginGles20)
+        {
+        HUI_DEBUG(_L("CHuiStatic::Gles20Renderer() - Renderer cannot be used as Gles20 renderer."));
+        THuiPanic::Panic(THuiPanic::EStaticInvalidRenderer);
+        }
+    return *reinterpret_cast< CHuiGles20RenderPlugin* >(renderer);
+    }
+
+
+EXPORT_C MHuiRenderSurface* CHuiStatic::CurrentRenderSurface()
+    {
+    if(!Data())
+        {
+        HUI_DEBUG(_L("CHuiStatic::CurrentRenderSurface() - Static data or current render surface not specified. Panicking."));
+        THuiPanic::Panic(THuiPanic::EStaticCurrentRenderSurfaceNotSpecified);
+        }
+    return Data()->iCurrentRenderSurface;
+    }
+
+
+EXPORT_C void CHuiStatic::SetCurrentRenderSurface(MHuiRenderSurface* aSurface)
+    {
+    Data()->iCurrentRenderSurface = aSurface;
+    }
+
+
+EXPORT_C void CHuiStatic::EnableLogging(TBool aEnable)
+    {
+    TTlsData* data = Data();
+
+    if(aEnable && !data->iLogEnabled)
+        {
+        data->iLogEnabled = ETrue;
+
+		// debug code only 
+        TFileName filename;
+        filename.Append('e');
+        filename.Append(':');
+        filename.Append('\\');
+        filename.Append(_L("HuiMessages.log"));
+                
+        if(data->iLogFile.Replace(*data->iFs, filename, EFileWrite) != KErrNone)
+            {
+            RDebug::Print(_L("CHuiStatic::EnableLogging() - Could not open log file e:HuiMessages.log for writing. Trying c: .."));
+            _LIT(KFileName2, "c:\\HuiMessages.log");
+            if(data->iLogFile.Replace(*data->iFs, KFileName2, EFileWrite) != KErrNone)
+                {
+                RDebug::Print(_L("CHuiStatic::EnableLogging() - Could not open log file c:HuiMessages.log for writing. Logging disabled."));
+                data->iLogEnabled = EFalse;
+                }
+            else
+                {
+                RDebug::Print(_L("CHuiStatic::EnableLogging() - Enabled Logging to c \"HuiMessages.log\"."));
+                Printf(_L("CHuiStatic::EnableLogging() - Enabled Logging to \"HuiMessages.log\"."));
+                }
+            }
+        else
+            {
+            RDebug::Print(_L("CHuiStatic::EnableLogging() - Enabled Logging to mmc \"HuiMessages.log\"."));
+            Printf(_L("CHuiStatic::EnableLogging() - Enabled Logging to mmc \"HuiMessages.log\"."));
+            }
+        }
+    else if(!aEnable && data->iLogEnabled)
+        {
+        data->iLogFile.Close();
+        data->iLogEnabled = EFalse;
+        }
+    else
+        {
+        // for PC lint
+        }
+    }
+
+
+EXPORT_C TBool CHuiStatic::Logging()
+    {
+    return Data()->iLogEnabled;
+    }
+
+
+EXPORT_C void CHuiStatic::ContinueRefresh()
+    {
+    TTlsData* data = Data();
+    if(data && data->iPrimaryEnv)
+        {
+        data->iPrimaryEnv->ContinueRefresh();
+        }
+    }
+
+
+void CHuiStatic::UpdateTime()
+    {
+    // Updates the toolkit's time counters. This includes the toolkit's
+    // realtime clock, the internal absolute clock (which is affected by the
+    // time factor), the amount of elapsed time since last UpdateTime()
+    // invocation, and the amount of elapsed time since the first UpdateTime()
+    // invocation (which was done in the beginning of the first refresh).
+
+    TTlsData* data = Data();
+    
+    UpdateTime(data);
+    }
+
+
+EXPORT_C const TTime& CHuiStatic::Time()
+    {
+    return Data()->iUniversalTime;
+    }
+
+
+EXPORT_C void CHuiStatic::SetTimeFactor(TReal32 aTimeFactor) __SOFTFP
+    {
+    TTlsData* data = Data();
+
+    if(data)
+        {
+        if(aTimeFactor < 0)
+            {
+            aTimeFactor = 0;
+            }
+            
+        if(data->iTimeFactor == 0 && aTimeFactor != 0)
+            {
+            // Continuing from a paused state
+            UpdateTime(data);
+            }
+            
+        data->iTimeFactor = aTimeFactor;
+        }
+    }
+
+
+EXPORT_C TReal32 CHuiStatic::TimeFactor() __SOFTFP
+    {
+    TTlsData* data = Data();
+
+    if(data)
+        {
+        return data->iTimeFactor;
+        }
+    return 1.0;
+    }
+
+
+EXPORT_C void CHuiStatic::PauseTime()
+    {
+    TTlsData* data = Data();
+
+    if(data)
+        {
+        // Update internal elapsed
+        UpdateTime(data);       
+        // Cache internal elapsed in internal time passed before pausing
+        data->iInternalElapsedBeforePausing = data->iInternalElapsed;
+        // Pause timing
+        data->iTimePaused = ETrue;
+        }
+    }
+
+
+EXPORT_C void CHuiStatic::ContinueTime()
+    {
+    TTlsData* data = Data();
+
+    if(data && data->iTimePaused)
+        {
+        UpdateTime(data);
+        data->iTimePaused = EFalse;
+        }
+    }
+
+
+EXPORT_C TBool CHuiStatic::TimePaused()
+    {
+    TTlsData* data = Data();
+
+    if(data)
+        {
+        return data->iTimePaused;
+        }
+    return EFalse;
+    }
+
+
+EXPORT_C TReal32 CHuiStatic::ElapsedSeconds() __SOFTFP
+    {
+    TTlsData* data = Data();
+
+    if(data)
+        {
+#ifdef EKA2
+        return data->iInternalElapsed / 1.0e6;
+#else
+        return data->iInternalElapsed.GetTReal() / 1.0e6;
+#endif
+        }
+    return 0;
+    }
+
+
+EXPORT_C TReal32 CHuiStatic::SecondsSinceStart() __SOFTFP
+    {
+    TTlsData* data = Data();
+    if(!data)
+        {
+        // Time has not begun yet.
+        return 0;
+        }
+
+    // Calculate difference between internal absolute clock and the first update time.
+    TInt64 delta = data->iUniversalTime.MicroSecondsFrom(data->iFirstUpdateTime).Int64();
+#ifdef EKA2
+    return delta / 1.0e6;
+#else
+    return delta.GetTReal() / 1.0e6;
+#endif
+    }
+
+
+EXPORT_C TUint32 CHuiStatic::MilliSecondsSinceStart()
+    {
+    // This will wrap around in approx. 50 days.
+    TTlsData* data = Data();
+    if(data)
+        {
+        // Calculate difference between internal absolute clock and the first update time.
+        TInt64 delta = data->iUniversalTime.MicroSecondsFrom(data->iFirstUpdateTime).Int64();
+        return delta / 1000;
+        }
+    return 0;
+
+    }
+
+
+TInt CHuiStatic::GenerateId()
+    {
+    TTlsData* data = Data();
+
+    // The ID counter counts backwards.
+    TInt id = data->iIdCounter;
+
+    if(data->iIdCounter == KMinTInt)
+        {
+        // Wrap around to stay negative.
+        data->iIdCounter = -1;
+        }
+    else
+        {
+        --data->iIdCounter;
+        }
+
+    return id;
+    }
+
+
+void CHuiStatic::ReportNewFrame()
+    {
+    TTlsData* data = Data();
+    data->iFrameCounter++;
+    data->iCurrentFrameCounter++;
+    }
+
+
+EXPORT_C TUint CHuiStatic::FrameCount()
+    {
+    TTlsData* data = Data();
+    return data->iFrameCounter;
+    }
+
+
+EXPORT_C TReal32 CHuiStatic::AverageFrameRate() __SOFTFP
+    {
+    return 0;
+    }
+
+
+EXPORT_C TReal32 CHuiStatic::FrameRate() __SOFTFP
+    {
+
+    TTlsData* data = Data();
+
+    TTime now;
+    now.UniversalTime();
+
+    // If very little time has passed, don't calculate a new value yet.
+    TTimeIntervalMicroSeconds msFromLast = 0;
+    msFromLast = now.MicroSecondsFrom(data->iLastFpsTime);
+    if(msFromLast < TTimeIntervalMicroSeconds(TInt64(1e6)))
+        {
+        // Do not recalculate yet.
+#ifdef SYMBIAN_BUILD_GCE
+        return 0; // to ignore the value if time is not elapsed
+#else
+        return data->iLastFps;
+#endif
+        }
+
+    if(data->iCurrentFrameCounter == 0)
+        {
+        data->iLastFpsTime = now;
+        return 0;
+        }
+
+    TInt64 delta = now.MicroSecondsFrom(data->iLastFpsTime).Int64();
+
+    TReal32 fps = 0;
+#ifdef EKA2
+    TReal32 elapsed = delta / 1.0e6;
+#else
+    TReal32 elapsed = delta.GetTReal() / 1.0e6;
+#endif
+
+    if(elapsed > 0)
+        {
+        fps = (TReal32)data->iCurrentFrameCounter / elapsed;
+        }
+
+    data->iLastFps = fps;
+    data->iCurrentFrameCounter = 0;
+    data->iLastFpsTime = now;
+
+    return fps;
+    }
+
+
+EXPORT_C void CHuiStatic::Printf(TRefByValue<const TDesC8> aFormat, ...)
+    {
+    TTlsData* data = Data();
+    // Bail out early if logging is disabled.
+    if(!data || !data->iLogEnabled)
+        {
+#ifdef _DEBUG
+        // redirect to RDebug output if we are debugging
+        TUint total = 0;
+        TUint free = HuiUtil::FreeMemory(&total);
+        TBuf8<256> buf;
+        VA_LIST list;
+        VA_START(list, aFormat);
+        buf.FormatList(aFormat, list);
+        VA_END(list);
+        RDebug::Print(_L("(%i/%i KB) %s"), free/1024, total/1024, &buf);
+#endif
+        // Already gone?
+        return;
+        }
+    TTime now;
+    now.UniversalTime();
+    TInt32 elapsed = (TInt32)(now.MicroSecondsFrom(data->iFirstUpdateTime).Int64() / 1000);
+
+    TBuf8<100> memData;
+    TUint total = 0;
+    TUint free = HuiUtil::FreeMemory(&total);
+    memData.Format(_L8("% 2d,%03d (%i/%i KB) "), elapsed / 1000,
+                                             elapsed % 1000,
+                                             free/1024, total/1024);
+
+    TBuf8<512> buf;
+    VA_LIST list;
+    VA_START(list, aFormat);
+    buf.FormatList(aFormat, list);
+    VA_END(list);
+    buf.Insert(0, memData);
+    buf.Append(_L8("\n"));
+
+    data->iLogFile.Write(buf);
+    data->iLogFile.Flush();
+    }
+
+
+EXPORT_C void CHuiStatic::Printf(TRefByValue<const TDesC16> aFormat, ...)
+    {
+    TTlsData* data = Data();
+    // Bail out early if logging is disabled.
+    if(!data || !data->iLogEnabled)
+        {
+#ifdef _DEBUG
+        // redirect to RDebug output if we are debugging
+        TBuf16<512> buf;
+        TUint total; TUint free = HuiUtil::FreeMemory(&total);
+        VA_LIST list;
+        VA_START(list, aFormat);
+        buf.FormatList(aFormat, list);
+        VA_END(list);
+        RDebug::Print(_L("(%i/%i KB) %S"), free/1024, total/1024, &buf);
+#endif
+        // Already gone?
+        return;
+        }
+    TTime now;
+    now.UniversalTime();
+    TInt32 elapsed = (TInt32)(now.MicroSecondsFrom(data->iFirstUpdateTime).Int64() / 1000);
+
+    TBuf16<100> memData;
+    TUint total = 0;
+    TUint free = HuiUtil::FreeMemory(&total);
+    memData.Format(_L16("% 2d,%03d (%i/%i KB) "), elapsed / 1000,
+                                              elapsed % 1000,
+                                              free/1024, total/1024);
+
+    TBuf16<512> buf;
+    VA_LIST list;
+    VA_START(list, aFormat);
+    buf.FormatList(aFormat, list);
+    VA_END(list);
+    buf.Insert(0, memData);
+    buf.Append(_L16("\n"));
+
+    TBuf8<512> buf8;
+    buf8.SetLength(buf.Length());
+    for(TInt i = 0; i < buf.Length(); ++i)
+        {
+        buf8[i] = TUint8(buf[i]);
+        }
+
+    data->iLogFile.Write(buf8);
+    data->iLogFile.Flush();
+    }
+
+
+EXPORT_C void CHuiStatic::Tic(TInt aClock)
+    {
+    if(aClock < 0 || aClock >= KMaxClocks)
+        {
+        THuiPanic::Panic(THuiPanic::EStaticInvalidClock);
+        }
+
+    TTlsData* data = Data();
+    data->iClocks[aClock].UniversalTime();
+    }
+
+
+EXPORT_C TReal32 CHuiStatic::Toc(TInt aClock) __SOFTFP
+    {
+    if(aClock < 0 || aClock >= KMaxClocks)
+        {
+        THuiPanic::Panic(THuiPanic::EStaticInvalidClock);
+        }
+
+    TTlsData* data = Data();
+
+    TTime now;
+    now.UniversalTime();
+
+    TInt64 delta = now.MicroSecondsFrom(data->iClocks[aClock]).Int64();
+#ifdef EKA2
+    return delta / 1.0e6;
+#else
+    return delta.GetTReal() / 1.0e6;
+#endif
+    }
+
+
+EXPORT_C RFs& CHuiStatic::FsSession()
+    {
+    TTlsData* data = Data();
+    __ASSERT_ALWAYS(data, User::Panic(_L("HUI"),0));
+    return *data->iFs;
+    }
+
+EXPORT_C RWsSession& CHuiStatic::WsSession()
+    {
+    TTlsData* data = Data();
+    __ASSERT_ALWAYS(data, User::Panic(_L("HUI"),0));
+    return *data->iWsSession;
+    }
+
+EXPORT_C CWsScreenDevice* CHuiStatic::ScreenDevice( TInt aScreenNumber )
+    {
+    TTlsData* data = Data();
+    __ASSERT_ALWAYS(data, User::Panic(_L("HUI"),0));
+    return data->WsScreenDevice(aScreenNumber);
+    }
+
+EXPORT_C RWindowGroup* CHuiStatic::RootWin( TInt aScreenNumber )
+    {
+    TTlsData* data = Data();
+    __ASSERT_ALWAYS(data, User::Panic(_L("HUI"),0));
+    return data->RootWin(aScreenNumber);
+    }
+
+EXPORT_C void CHuiStatic::SetLayoutTransitionTime( TInt aTime )
+    {
+    TTlsData* data = Data();
+    if(data)
+        {
+        data->iLayoutTransitionTime = aTime;
+        }
+    }
+
+
+EXPORT_C TInt CHuiStatic::LayoutTransitionTime()
+    {
+    TTlsData* data = Data();
+    if(data)
+        {
+        return data->iLayoutTransitionTime;
+        }
+    return 0;
+    }
+
+EXPORT_C void CHuiStatic::SetProbe(MHuiProbe* aProbe)
+    {
+    TTlsData* data = Data();
+    if(data)
+        {
+        data->iProbe = aProbe;
+        }
+    }
+
+MHuiProbe& CHuiStatic::Probe()
+    {
+    TTlsData* data = Data();
+    
+    if ( !data )
+        {
+        THuiPanic::Panic(THuiPanic::EStaticDataNotCreated);
+        }
+    
+    if(data->iProbe)
+        {
+        return *(data->iProbe);
+        }
+    return *(data->iFakeProbe);
+    }
+
+EXPORT_C MAknsSkinInstance* CHuiStatic::SkinInstance()
+    {
+    if (CCoeEnv::Static())
+        {
+        return AknsUtils::SkinInstance();
+        }
+    return 0;
+    }
+
+TBool CHuiStatic::LayoutMirrored()
+    {
+    if (CCoeEnv::Static())
+        {
+        return AknLayoutUtils::LayoutMirrored();
+        }
+    else
+        {
+        TTlsData* data = Data();
+        return data->iAppFwProxy->LayoutMirrored(); 
+        }
+    }
+
+TInt CHuiStatic::CbaLocation()
+    {
+    if (CCoeEnv::Static())
+        {
+        return AknLayoutUtils::CbaLocation();
+        }
+    else
+        {
+        TTlsData* data = Data();
+        return data->iAppFwProxy->SoftKeyOrientation(); 
+        }
+    }
+
+void CHuiStatic::LayoutMetricsRect(TInt aType, TRect& aRect)
+    {
+    if (CCoeEnv::Static())
+        {
+        (void)AknLayoutUtils::LayoutMetricsRect((AknLayoutUtils::TAknLayoutMetrics)aType, aRect);
+        }
+    else
+        {
+        TTlsData* data = Data();
+        aRect = data->iAppFwProxy->LayoutMetricsRect(aType); 
+        }
+    }
+
+TInt CHuiStatic::GetCachedColor(TRgb& aRgb, const TAknsItemID& aID,
+          const TInt aIndex )
+    {
+    MAknsSkinInstance* skin = SkinInstance();
+    if (skin)
+        {
+        return AknsUtils::GetCachedColor(skin, aRgb, aID, aIndex );
+        }
+    else
+        {
+        TTlsData* data = Data();
+        return data->iAppFwProxy->GetCachedColor(aRgb, aID, aIndex );        
+        }
+    }
+
+TBool CHuiStatic::ConvertToVisualAndClipL(
+    TDes& aLogicalText,
+    const CFont& aFont,
+    TInt aMaxWidthInPixels,
+    TInt aMaxClippedWidthInPixels )
+    {
+    if (CCoeEnv::Static())
+       {
+       return AknBidiTextUtils::ConvertToVisualAndClipL(
+            aLogicalText,
+            aFont,
+            aMaxWidthInPixels,
+            aMaxClippedWidthInPixels );
+       }
+    else
+        {
+        if ( !aLogicalText.Length() )
+            {
+            aLogicalText = KNullDesC; // null text 
+            return EFalse;
+            }
+
+        HBufC* visualBuffer = HBufC::NewLC(
+                aLogicalText.Length() + KAknBidiExtraSpacePerLine );
+        
+        TPtr ptr = visualBuffer->Des();
+        
+        TInt chars = aLogicalText.Length();
+
+        TBool clipped = EFalse;
+
+        TChar clipChar = 0xffff;
+
+        // TextCount() converts text to visual form and then checks it
+        if ( aFont.TextCount( aLogicalText, aMaxWidthInPixels ) < chars )
+            {
+            clipped = ETrue;
+
+            TInt clipCharWidth = 0;
+            // Not enough space even for clip char alone - return empty descriptor.
+            if ( aMaxClippedWidthInPixels < clipCharWidth )
+                {
+                aLogicalText = KNullDesC; // null text 
+                CleanupStack::PopAndDestroy(); // visual buf
+                return ETrue;
+                }
+
+            // Check how many characters fit in given space with truncation char.
+            // We need to give this information to TBidiLogicalToVisual.
+            chars = aFont.TextCount( 
+                    aLogicalText, aMaxClippedWidthInPixels - clipCharWidth );
+
+            // This is "avkon rule": should not insert ellipsis right after a space.
+            if ( chars > 1 && 
+                    aLogicalText[chars - 1] == ' ' &&
+                    aLogicalText[chars - 2] != ' ' )
+                {
+                chars--;
+                }
+            }
+        
+        TBidirectionalState::TRunInfo* array =
+                new TBidirectionalState::TRunInfo[chars];
+        
+        TBidiLogicalToVisual converter(
+                aLogicalText,
+                array,
+                chars ) ;
+ 
+        TInt count = converter.Reorder();
+
+        if (count > chars)
+            {
+            delete array;
+            array = 0;
+            array = new TBidirectionalState::TRunInfo[chars];
+            }
+     
+        if (array)
+            {
+            TBidiLogicalToVisual converter = TBidiLogicalToVisual( aLogicalText, array, chars );
+            converter.Reorder();
+            TPtr ptr = visualBuffer->Des();
+            converter.GetVisualLine( ptr, 0, chars, clipChar );
+            }
+     
+        aLogicalText = *visualBuffer;
+   
+        CleanupStack::PopAndDestroy();
+        return clipped;
+        }
+    }
+
+HBufC* CHuiStatic::ConvertToVisualAndWrapToArrayL( 
+    const TDesC& aLogicalText,
+    TInt aLineWidth,
+    const CFont& aFont,
+    CArrayFix<TPtrC>& aWrappedArray )
+    {
+    if (CCoeEnv::Static())
+        {
+        return AknBidiTextUtils::ConvertToVisualAndWrapToArrayL( 
+            aLogicalText,
+            aLineWidth,
+            aFont,
+            aWrappedArray);
+        }
+    else
+        {
+        // will not be supported ever
+        HBufC* ret = aLogicalText.AllocLC();
+        aWrappedArray.AppendL(ret->Des());
+        CleanupStack::Pop();
+        return ret;
+        }
+    }
+
+CFbsBitmap* CHuiStatic::GetBgBitmapLC(const TAknsItemID& aID)
+    {
+    CFbsBitmap * bitmap = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL(bitmap);
+ 
+    TTlsData* data = Data();
+    data->iAppFwProxy->GetSkinBackgroundBitmapL(bitmap, aID);        
+    
+    return bitmap;
+    }
+
+void CHuiStatic::GetMaskedBitmapL(const TAknsItemID& aID, CFbsBitmap*& aBitmap, CFbsBitmap*& aBitmapMask,
+                                 const TDesC& aFileName, TInt aBitmapId, TInt aMaskId,  const TSize& aSize, TScaleMode aScaleMode)
+    {
+    CFbsBitmap * bitmap = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL(bitmap);
+
+    CFbsBitmap * mask = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL(mask);
+
+    TTlsData* data = Data();
+    data->iAppFwProxy->GetSkinBitmapL(bitmap, mask, aID, aFileName, aBitmapId, aMaskId, aSize, aScaleMode );        
+    
+    // Transfer the ownership
+    if (mask->Handle())
+        {
+        aBitmapMask = mask;
+        CleanupStack::Pop(); //mask
+        }
+    else 
+        {
+        CleanupStack::PopAndDestroy(); //mask
+        }        
+    aBitmap = bitmap;
+    CleanupStack::Pop(); //bitmap
+    }
+        
+CAknsItemData* CHuiStatic::GetCachedSkinItemDataL(const TAknsItemID& aID, TInt aDataType)   
+    {
+    CAknsImageTableItemData* skindata = 0;    
+    if (aDataType == EAknsITImageTable) // only image table for framebrush supported
+        {
+        TTlsData* data = Data();
+        TAlfCachedSkinItemArray array;
+        data->iAppFwProxy->GetCachedSkinItemDataArrayL(aID, aDataType, array);         
+        if (array.iCount)
+            {
+            skindata = CAknsImageTableItemData::NewL();
+            CleanupStack::PushL(skindata);
+            skindata->SetImagesL(array.iCount, array.iImages);
+            CleanupStack::Pop();
+            }        
+        }
+    return skindata;
+    }
+
+TInt CHuiStatic::SettingChangedCallBack(TAny* aInstance)
+    {
+    return ((CHuiStatic *)aInstance)->DoChange();
+    }
+
+TInt CHuiStatic::DoChange()
+    {
+    TInt change = iChangeNotifier->Change();
+    TTlsData* data = Data();
+    if(!data)
+        {
+        // Time has not begun yet.
+         return 0;
+         }
+      if (change & EChangesLocale)
+          {
+          data->iIsFirstUpdateTime = ETrue;
+          UpdateTime();
+          }
+     
+      if (change & EChangesSystemTime)
+          {
+          data->iIsFirstUpdateTime = ETrue;
+          UpdateTime();
+          }
+      
+      return 1;
+    }