uiacceltk/hitchcock/coretoolkit/src/HuiVisual.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiVisual.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,2155 @@
+/*
+* 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 CHuiVisual class. Visuals are graphical entities 
+*                visible on a display.
+*
+*/
+
+
+
+#include "uiacceltk/HuiVisual.h"  // Class definition
+#include "uiacceltk/HuiLayout.h"
+#include "uiacceltk/HuiControl.h"
+#include "uiacceltk/HuiControlGroup.h"
+#include "uiacceltk/HuiEnv.h"
+#include "uiacceltk/HuiDisplay.h"
+#include "uiacceltk/HuiRoster.h"
+#include "uiacceltk/HuiTransformation.h"
+#include "uiacceltk/HuiDrawing.h"
+#include "HuiRenderPlugin.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiStatic.h"
+#include "uiacceltk/HuiProbe.h"
+#include "uiacceltk/huidropshadow.h"
+#include "HuiRosterImpl.h"
+#include "HuiFxEffect.h"
+#include "HuiFxEffectParser.h"
+#include "alflogger.h"
+#include "HuiCmdBufferBrush.h"
+#include "huicanvasrenderbuffer.h"
+
+struct CHuiVisual::THuiVisualPrivateData
+    {
+public: // Functions
+    // Constructor: initialize the data
+    THuiVisualPrivateData() : iTacticons(), iDropShadow(NULL)
+        {
+        iEffect = NULL;
+        iEffectParser = NULL;
+        }
+        
+    // Destructor: destruct the data
+    ~THuiVisualPrivateData()
+        {
+        iTacticons.Close();
+        delete iDropShadow;
+        delete iEffectParser;
+        delete iEffect;
+        }
+    
+    // structs
+    struct TTacticon
+        {
+        TInt iFeedbackType;
+        TInt iEventType;
+        };
+    
+    // Data
+    RArray<TTacticon> iTacticons;
+    CHuiDropShadow* iDropShadow;
+    TRect iPreviousDrawnTvOut; 
+    CHuiFxEffect* iEffect;
+    CHuiFxEffectParser* iEffectParser;
+    MHuiEffectable *iEffectable;
+    CHuiCanvasRenderBuffer* iStoredRenderBuffer;
+    TBool iStoredRenderBufferModificationsEnabled;
+    TBool iFreezed;
+    };
+class CHuiEffectable : public CBase, public MHuiEffectable
+    {
+public: // from MHuiEffectable
+    CHuiEffectable(CHuiVisual *aVisual) : iVisual(aVisual) { }
+    void EffectSetEffect(CHuiFxEffect* aEffect);
+    TReal32 EffectOpacityTarget() const;
+    void EffectSetOpacity(TReal32 aOpacity);
+    void EffectDrawSelf( CHuiGc &aGc, const TRect & aDisplayRect) const;
+    THuiRealRect EffectDisplayRect() const __SOFTFP;
+    void SetLoadingEffect(TBool aLoading);    
+    void EffectSetSource( TBool aIsInput1 );
+    TBool EffectGetSource() const;
+
+private:
+    CHuiVisual *iVisual;
+    TBool iIsInput1;
+    };
+void CHuiEffectable::EffectSetEffect(CHuiFxEffect* aEffect)
+    {
+    iVisual->SetEffect(aEffect);
+    }
+void CHuiEffectable::EffectSetSource( TBool aIsInput1 )
+    {
+    iIsInput1 = aIsInput1;
+    }
+TBool CHuiEffectable::EffectGetSource() const
+    {
+    return iIsInput1;
+    }
+
+TReal32 CHuiEffectable::EffectOpacityTarget() const
+    {
+    return iVisual->iOpacity.Target();
+    }
+
+void CHuiEffectable::EffectSetOpacity(TReal32 aOpacity)
+    {
+    iVisual->iOpacity.Set( aOpacity );
+    }
+
+void CHuiEffectable::EffectDrawSelf( CHuiGc &aGc, const TRect & aDisplayRect) const
+    {
+    iVisual->DrawSelf(aGc, aDisplayRect);
+    }
+
+THuiRealRect CHuiEffectable::EffectDisplayRect() const __SOFTFP
+    {
+    return iVisual->DisplayRect();
+    }
+
+void CHuiEffectable::SetLoadingEffect(TBool aLoading)
+    {
+    iVisual->SetLoadingEffect(aLoading);
+    }
+
+
+/// Descriptor that is returned when the tag is queried and no tag has been
+/// been defined for a visual.
+_LIT8(KHuiVisualUndefinedTag, "");
+
+EXPORT_C MHuiVisualOwner::~MHuiVisualOwner()
+    {
+    }
+
+EXPORT_C CHuiCanvasRenderBuffer *CHuiVisual::StoredRenderBuffer() const
+    {
+    return iVisualData->iStoredRenderBuffer;
+    }
+EXPORT_C void CHuiVisual::SetStoredRenderBuffer(CHuiCanvasRenderBuffer *aRenderBuffer)
+    {
+    if (iVisualData->iStoredRenderBufferModificationsEnabled)
+        {
+        if (iVisualData->iStoredRenderBuffer)
+            {
+            iVisualData->iStoredRenderBuffer->UnInitialize();
+            }
+        delete iVisualData->iStoredRenderBuffer;
+        iVisualData->iStoredRenderBuffer = aRenderBuffer;
+        }
+    }
+EXPORT_C void CHuiVisual::SetStoredRenderBufferModificationsEnabled(TBool aEnabled)
+    {
+    iVisualData->iStoredRenderBufferModificationsEnabled = aEnabled;
+    }
+
+EXPORT_C void CHuiVisual::SetFreezeState(TBool aEnabled)
+    {
+    iVisualData->iFreezed = aEnabled;
+    }
+TBool CHuiVisual::Freezed() const
+{
+    return iVisualData->iFreezed;
+}
+
+EXPORT_C CHuiVisual* CHuiVisual::AddNewL(CHuiControl& aOwnerControl,
+                                         CHuiLayout* aParentLayout)
+    {
+    CHuiVisual* visual = STATIC_CAST(CHuiVisual*,
+        aOwnerControl.AppendVisualL(EHuiVisualTypeVisual, aParentLayout));
+    return visual;
+    }
+
+
+EXPORT_C CHuiVisual::CHuiVisual(MHuiVisualOwner& aOwner)
+        : iOpacity(1.f),
+          iOwner(&aOwner), 
+          // Set the maximum size to unlimited.
+          iMaxSize(TSize(KMaxTInt, KMaxTInt)),
+          iPadding(0), 
+          iDisplayRectFrameNumber(KMaxTUint),
+          iDisplayRectTargetFrameNumber(KMaxTUint)
+    {
+    HUI_PROBE_ASSOCIATE_WITH_CURRENT_SESSION
+    HUI_PROBE_REPORT_CONSTRUCTED
+    iOpacity.SetStyle(EHuiTimedValueStyleLinear);
+    }
+
+
+EXPORT_C void CHuiVisual::ConstructL()
+    {
+    iVisualData = new (ELeave) THuiVisualPrivateData;
+    iVisualData->iEffectable = new CHuiEffectable(this);
+    iVisualData->iStoredRenderBuffer = NULL;
+    }
+
+
+EXPORT_C CHuiVisual::~CHuiVisual()
+    {
+    // Cancel scheduled commands for this visual.
+    Env().CancelCommands(this);
+
+	// Update previous dirty rect to relevant displays so that the visual can be erased
+    if(Display())
+        {        
+        CHuiRoster& roster = Display()->Roster();
+		// Check if this roster is shared between several displays and add previous dirty to all 
+		// of them
+    	for(TInt i = 0; i < Env().Displays().Count(); ++i)
+        	{ 
+        	CHuiDisplay* display = &Env().Display(i);
+        	if (&(display->Roster()) == &roster)
+        		{
+				const TRect& previousDirtyRect = display->IsDisplayTypeTvOut() ? iVisualData->iPreviousDrawnTvOut : iPreviousDrawn;
+				TRect empty;
+        		display->CombineAndAddDirtyRegion(previousDirtyRect, empty);
+        		}
+        	}	
+        }
+
+    // If this is a root-level visual, it must be hidden on the display.
+    if(iDisplay)
+        {
+        iDisplay->Roster().HideVisual(this);
+        }
+
+    // If the visual is still attached to a layout, it is time to remove it.
+    if(iLayout)
+        {
+        iLayout->Remove(this);
+        }
+        
+    // If the visual is attached to some visual as external content visual,
+    // remove the link from the parent visual
+    if (Flags() & EHuiVisualFlagDrawOnlyAsExternalContent)
+    	{
+    	TRAP_IGNORE(CHuiStatic::Env().Display(0).RosterImpl().RemoveExternalContentVisualFromParentL(this));
+    	}
+
+    delete iBrushes;
+    delete iTag;
+    delete iTransform;
+    delete iVisualData->iEffectable;
+    if (iVisualData->iStoredRenderBuffer)
+        {
+        iVisualData->iStoredRenderBuffer->UnInitialize();
+        }
+    delete iVisualData->iStoredRenderBuffer;
+    delete iVisualData;
+    
+    iOwner = NULL;
+    iDisplay = NULL;
+    iLayout = NULL;
+
+    HUI_PROBE_REPORT_DESTRUCTED
+    }
+
+
+EXPORT_C void CHuiVisual::RemoveAndDestroyAllD()
+    {
+    ASSERT(iOwner != NULL);
+    iOwner->VisualDestroyed(*this);
+    delete this;
+    }
+
+
+EXPORT_C CHuiLayout* CHuiVisual::Layout() const
+    {
+    return iLayout;
+    }
+
+
+void CHuiVisual::SetLayout(CHuiLayout* aLayout)
+    {
+    iLayout = aLayout;
+    }
+
+
+EXPORT_C CHuiEnv& CHuiVisual::Env() const
+    {
+    return Owner().Env();
+    }
+
+
+EXPORT_C CHuiSkin& CHuiVisual::Skin() const
+    {
+    return Owner().Env().Skin();
+    }
+
+
+EXPORT_C CHuiDisplay* CHuiVisual::Display() const
+    {
+    const CHuiVisual* iter = this;
+
+    while(iter)
+        {
+        if(iter->iDisplay)
+            {
+            return iter->iDisplay;
+            }
+        iter = iter->Layout();
+        }
+
+    // Not shown on any display.
+    return NULL;
+    }
+
+
+void CHuiVisual::SetDisplay(CHuiDisplay* aDisplay)
+    {
+    iDisplay = aDisplay;
+    }
+
+
+EXPORT_C void CHuiVisual::SetFlag(THuiVisualFlags aFlag)
+    {
+    SetFlags(aFlag);
+    }
+
+
+EXPORT_C void CHuiVisual::SetFlags(TInt aAnyFlags)
+    {
+    const TInt oldFlags = iFlags;
+    iFlags |= aAnyFlags;
+
+    if(!CHuiStatic::Renderer().Allows(EHuiRenderPluginAllow3DProjection))
+        {
+        // The rendering plugin does not support 3D projection.
+        ClearFlag(EHuiVisualFlag3DProjection);
+        }
+        
+    HandleFlagsChanged( oldFlags );
+    }
+
+
+EXPORT_C void CHuiVisual::ClearFlag(THuiVisualFlags aFlag)
+    {
+    ClearFlags( aFlag );
+    }
+
+
+EXPORT_C void CHuiVisual::ClearFlags(TInt aAnyFlags)
+    {
+    const TInt oldFlags = iFlags;
+    iFlags &= ~aAnyFlags;
+    
+    HandleFlagsChanged( oldFlags );
+    }
+
+
+EXPORT_C MHuiVisualOwner& CHuiVisual::Owner() const
+    {
+    ASSERT(iOwner != NULL);
+    return *iOwner;
+    }
+    
+    
+EXPORT_C void CHuiVisual::SetOwner(MHuiVisualOwner& aOwner)
+    {
+    iOwner = &aOwner;
+    }
+    
+    
+EXPORT_C TInt CHuiVisual::Count() const
+    {
+    return 0;
+    }
+
+
+EXPORT_C CHuiVisual& CHuiVisual::Visual(TInt /*aIndex*/) const
+    {
+    USER_INVARIANT();
+    return *(CHuiVisual*)this; // never reached
+    }
+
+
+EXPORT_C void CHuiVisual::SetOrigin(THuiVisualHOrigin aHoriz, THuiVisualVOrigin aVert)
+    {
+    ClearFlags(EHuiVisualFlagHOriginCenter | EHuiVisualFlagHOriginRight);
+    switch(aHoriz)
+        {
+        case EHuiVisualHOriginCenter:
+            SetFlag(EHuiVisualFlagHOriginCenter);
+            break;
+
+        case EHuiVisualHOriginRight:
+            SetFlag(EHuiVisualFlagHOriginRight);
+            break;
+
+        default:
+            break;
+        }
+
+    ClearFlags(EHuiVisualFlagVOriginCenter | EHuiVisualFlagVOriginBottom);
+    switch(aVert)
+        {
+        case EHuiVisualVOriginCenter:
+            SetFlag(EHuiVisualFlagVOriginCenter);
+            break;
+
+        case EHuiVisualVOriginBottom:
+            SetFlag(EHuiVisualFlagVOriginBottom);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+
+EXPORT_C THuiVisualHOrigin CHuiVisual::HorizontalOrigin() const
+    {
+    if(iFlags & EHuiVisualFlagHOriginCenter)
+        {
+        return EHuiVisualHOriginCenter;
+        }
+    if(iFlags & EHuiVisualFlagHOriginRight)
+        {
+        return EHuiVisualHOriginRight;
+        }
+    return EHuiVisualHOriginLeft;
+    }
+
+
+EXPORT_C THuiVisualVOrigin CHuiVisual::VerticalOrigin() const
+    {
+    if(iFlags & EHuiVisualFlagVOriginCenter)
+        {
+        return EHuiVisualVOriginCenter;
+        }
+    if(iFlags & EHuiVisualFlagVOriginBottom)
+        {
+        return EHuiVisualVOriginBottom;
+        }
+    return EHuiVisualVOriginTop;
+    }
+
+
+EXPORT_C void CHuiVisual::AlignByOrigin(THuiRealPoint& aPointInPixels, TBool aUndo) const
+    {
+    TInt factor = (aUndo? -1 : 1);
+    THuiRealPoint itemSize(0.f, 0.f); 
+    
+    TInt horizOrig = HorizontalOrigin();
+    TInt vertOrig = VerticalOrigin();
+
+    // The position of the origin depends whether the coordinates are mirrored.    
+    if(LocalBaseUnit().iX.iMagnitude < 0)
+        {
+        if(horizOrig == EHuiVisualHOriginLeft)
+            {
+            horizOrig = EHuiVisualHOriginRight;
+            }
+        else if(horizOrig == EHuiVisualHOriginRight)
+            {
+            horizOrig = EHuiVisualHOriginLeft;
+            }
+        else
+            {
+            // For PC-lint
+            }
+        }
+    if(LocalBaseUnit().iY.iMagnitude < 0)
+        {
+        if(vertOrig == EHuiVisualVOriginTop)
+            {
+            vertOrig = EHuiVisualVOriginBottom;
+            }
+        else if(vertOrig == EHuiVisualVOriginBottom)
+            {
+            vertOrig = EHuiVisualVOriginTop;
+            }
+        else
+            {
+            // For PC-lint
+            }
+        }
+    
+    if(horizOrig != EHuiVisualHOriginLeft ||
+        vertOrig != EHuiVisualVOriginTop)
+        {
+        // Need the size of the visual for aligning to non-top/left corner.
+        itemSize = LocalPointInPixels(Size().RealNow());
+        }
+    
+    switch(horizOrig)
+        {
+        case EHuiVisualHOriginCenter:
+            aPointInPixels.iX -= factor * itemSize.iX / 2.f;
+            break;
+
+        case EHuiVisualHOriginRight:
+            aPointInPixels.iX -= factor * itemSize.iX;
+            break;
+
+        default:
+            break;
+        }
+
+    switch(vertOrig)
+        {
+        case EHuiVisualVOriginCenter:
+            aPointInPixels.iY -= factor * itemSize.iY / 2.f;
+            break;
+
+        case EHuiVisualVOriginBottom:
+            aPointInPixels.iY -= factor * itemSize.iY;
+            break;
+
+        default:
+            break;
+        }
+    }
+
+
+EXPORT_C const THuiTimedPoint& CHuiVisual::Pos() const
+    {
+    return iPos;
+    }
+
+
+EXPORT_C const THuiTimedPoint& CHuiVisual::Size() const
+    {
+    return iSize;
+    }
+
+
+EXPORT_C void CHuiVisual::SetPos(const THuiRealPoint& aPos, TInt aTransitionTime)
+    {
+    iPos.iX.Set(aPos.iX, aTransitionTime);
+    iPos.iY.Set(aPos.iY, aTransitionTime);
+    }
+
+
+EXPORT_C void CHuiVisual::SetSize(const THuiRealSize& aSize, TInt aTransitionTime)
+    {
+    iSize.iX.Set(aSize.iWidth < 0 ? aSize.iWidth *-1 : aSize.iWidth, aTransitionTime);
+    iSize.iY.Set(aSize.iHeight < 0 ? aSize.iHeight *-1 : aSize.iHeight, aTransitionTime);
+    }
+
+
+EXPORT_C void CHuiVisual::SetRect(const THuiRealRect& aRect, TInt aTransitionTime)
+    {
+    SetPos(aRect.iTl, aTransitionTime);
+    SetSize(aRect.Size(), aTransitionTime);
+    }
+
+
+// deprecated
+EXPORT_C void CHuiVisual::Move(const TPoint& aOffset, TInt aTransitionTime)
+    {
+	Move(PixelPointInLocal(THuiRealPoint(aOffset), EHuiReferenceStateNow), aTransitionTime);  
+	}
+
+
+EXPORT_C void CHuiVisual::Move(const THuiRealPoint& aOffset, TInt aTransitionTime)
+    {
+    iPos.iX.Set(iPos.iX.Target() + aOffset.iX, aTransitionTime);
+    iPos.iY.Set(iPos.iY.Target() + aOffset.iY, aTransitionTime);
+    }
+
+
+EXPORT_C void CHuiVisual::Mimic(const CHuiVisual& aVisual, TInt aTransitionTime)
+    {
+    SetPos(aVisual.iPos.RealTarget(), aTransitionTime);
+    SetSize(aVisual.iSize.RealTarget().AsSize(), aTransitionTime);
+    }
+
+
+// deprecated
+EXPORT_C void CHuiVisual::SetCenteredPosAndSize(const TPoint& aCenterPoint,
+                                                const TSize& aSize,
+                                                TInt aTransitionTime)
+    {
+    THuiRealPoint visualSize = PixelPointInLocal(THuiRealPoint(aSize.iWidth, aSize.iHeight),
+    	EHuiReferenceStateNow);
+    SetCenteredPosAndSize(PixelPointInLocal(THuiRealPoint(aCenterPoint), EHuiReferenceStateNow), 
+    	visualSize.AsSize(), aTransitionTime);
+    }
+
+
+EXPORT_C void CHuiVisual::SetCenteredPosAndSize(const THuiRealPoint& aCenterPoint,
+                                                const THuiRealSize& aSize,
+                                                TInt aTransitionTime)
+    {
+    SetPos(THuiRealPoint(aCenterPoint.iX - aSize.iWidth/2,
+    	aCenterPoint.iY - aSize.iHeight/2), aTransitionTime);
+    SetSize(aSize, aTransitionTime);
+    }
+
+
+EXPORT_C void CHuiVisual::UpdateChildrenLayout(TInt /*aTransitionTime*/)
+    {
+    }
+
+
+void CHuiVisual::ReportLayoutUpdate()
+    {
+    // Notify owner, if requested.
+    if(iFlags & EHuiVisualFlagLayoutUpdateNotification)
+        {
+        Owner().VisualLayoutUpdated(*this);
+        }
+    }
+
+// deprecated
+EXPORT_C void CHuiVisual::SetMinSize(const TSize& aMinSize)
+    {
+    THuiRealPoint minPoint = PixelPointInLocal(THuiRealPoint(aMinSize.iWidth, aMinSize.iHeight),
+    	EHuiReferenceStateNow);
+    SetMinSize(minPoint.AsSize());
+    }
+
+EXPORT_C void CHuiVisual::SetMinSize(const THuiRealSize& aMinSize)
+    {
+    iMinSize = aMinSize;
+    }
+    
+// deprecated
+EXPORT_C TSize CHuiVisual::MinSize() const
+    {
+    THuiRealSize minSize = MinSizeInBaseUnits();
+    THuiRealPoint minPoint = LocalPointInPixels(THuiRealPoint(minSize.iWidth, minSize.iHeight),
+    	EHuiReferenceStateNow);
+    // @todo: Should we round this value?
+    return (TSize(minPoint.AsSize()));
+    }
+
+EXPORT_C THuiRealSize CHuiVisual::MinSizeInBaseUnits() const __SOFTFP 
+    {
+    return iMinSize;
+    }
+
+
+// deprecated
+EXPORT_C void CHuiVisual::SetMaxSize(const TSize& aMaxSize)
+    {
+    THuiRealPoint maxPoint = PixelPointInLocal(THuiRealPoint(aMaxSize.iWidth, aMaxSize.iHeight),
+    	EHuiReferenceStateNow);
+    SetMaxSize(maxPoint.AsSize());
+    }
+
+EXPORT_C void CHuiVisual::SetMaxSize(const THuiRealSize& aMaxSize)
+    {
+    iMaxSize = aMaxSize;
+    }
+
+
+// deprecated
+EXPORT_C TSize CHuiVisual::MaxSize() const
+    {
+    THuiRealSize maxSize = MaxSizeInBaseUnits();
+    THuiRealPoint maxPoint = LocalPointInPixels(THuiRealPoint(maxSize.iWidth, maxSize.iHeight),
+    	EHuiReferenceStateNow);
+    // @todo: Should we round this value?
+    return (TSize(maxPoint.AsSize()));
+    }
+
+EXPORT_C THuiRealSize CHuiVisual::MaxSizeInBaseUnits() const __SOFTFP
+    {
+    return iMaxSize;
+    }
+
+
+EXPORT_C void CHuiVisual::SetClipping(TBool aClipping)
+    {
+    if(aClipping)
+        {
+        SetFlag(EHuiVisualFlagClipping);
+        }
+    else
+        {
+        ClearFlag(EHuiVisualFlagClipping);
+        }
+    }
+
+
+EXPORT_C TBool CHuiVisual::Clipping() const
+    {
+    return (iFlags & EHuiVisualFlagClipping) != 0;
+    }
+
+
+EXPORT_C THuiRealRect CHuiVisual::DisplayRect() const __SOFTFP
+    {
+    // Recalculate and cache as necessary. 
+    TBool recalculationNeeded = ETrue;
+    
+    TUint frameno = 0; // CHuiStatic::FrameCount() is called before used
+    const TBool calledDuringDraw = Env().CurrentDisplay() ? ETrue : EFalse;
+    
+    if ( calledDuringDraw ) // before the draw, the cache is not updated
+        {
+        frameno = CHuiStatic::FrameCount();
+        if ( frameno == iDisplayRectFrameNumber )
+            {
+            recalculationNeeded = EFalse;
+            }
+        }
+    
+    if( recalculationNeeded )
+	    {
+	    THuiRealRect rect(LocalToDisplay(Pos().RealNow()),
+	                      LocalPointInPixels(Size().RealNow()).AsSize());
+
+        if (rect.iTl.iX > rect.iBr.iX)
+            {
+            TReal tempX = rect.iTl.iX;
+            rect.iTl.iX = rect.iBr.iX;
+            rect.iBr.iX = tempX;
+            }
+  
+        if (rect.iTl.iY > rect.iBr.iY)
+            {
+            TReal tempY = rect.iTl.iY;
+            rect.iTl.iY = rect.iBr.iY;
+            rect.iBr.iY = tempY;
+            }
+	                      
+	    iDisplayRect = rect;
+	    
+	    if ( calledDuringDraw ) // update frame number only during draw
+            {
+	        iDisplayRectFrameNumber = frameno;
+            }
+	    }
+    return iDisplayRect;
+    }
+
+THuiRealRect CHuiVisual::CachedDisplayRect() const
+    {
+    return iDisplayRect;    
+    }
+
+
+EXPORT_C THuiRealRect CHuiVisual::DisplayRectTarget() const __SOFTFP
+    {
+    // Calculate effect display area if the visual has an attached effect
+    // For OpenVG nothing is needed as the area is the final position,
+    // not something that happens during transition.
+    // Recalculate and cache as necessary. 
+    TBool recalculationNeeded = ETrue;
+    
+    TUint frameno = 0; // CHuiStatic::FrameCount() is called before used
+    const TBool calledDuringDraw = Env().CurrentDisplay() ? ETrue : EFalse;
+    
+    if ( calledDuringDraw ) // before the draw, the cache is not updated
+        {
+        frameno = CHuiStatic::FrameCount();
+        if ( frameno == iDisplayRectTargetFrameNumber )
+            {
+            recalculationNeeded = EFalse;
+            }
+        }
+
+    if( recalculationNeeded )
+	    {
+		THuiRealRect rect(LocalToDisplay(Pos().RealTarget(), EHuiReferenceStateTarget),
+		                  LocalPointInPixels(Size().RealTarget(), EHuiReferenceStateTarget).AsSize());
+
+        if (rect.iTl.iX > rect.iBr.iX)
+            {
+            TReal32 tempX = rect.iTl.iX;
+            rect.iTl.iX = rect.iBr.iX;
+            rect.iBr.iX = tempX;
+            }
+  
+        if (rect.iTl.iY > rect.iBr.iY)
+            {
+            TReal32 tempY = rect.iTl.iY;
+            rect.iTl.iY = rect.iBr.iY;
+            rect.iBr.iY = tempY;
+            }
+        
+        iDisplayRectTarget = rect;
+        
+        if ( calledDuringDraw ) // update frame number only during draw
+            {
+	        iDisplayRectTargetFrameNumber = frameno;
+            }
+	    }
+	return iDisplayRectTarget;
+    }
+
+
+EXPORT_C TReal32 CHuiVisual::EffectiveOpacity() const __SOFTFP
+    {
+    TReal32 opacity = iOpacity.Now();
+
+    // Controls in control groups (i.e., normally all controls)
+    // get a common opacity from the group.
+    if(Owner().ControlGroup())
+        {
+        opacity *= Owner().ControlGroup()->iOpacity.Now();
+        }
+
+    CHuiVisual* iter = Layout();
+
+    // Factor in all the opacities of the parent visuals.
+    while(iter)
+        {
+        opacity *= iter->iOpacity.Now();
+        if(opacity <= 0)
+            {
+            // Fully transparent;
+            return 0;
+            }
+        iter = iter->Layout();
+        }
+
+    return opacity;
+    }
+
+
+EXPORT_C TBool CHuiVisual::PrepareDrawL()
+    {
+    // The visual base class doesn't prepare anything.	
+    return ETrue;
+    }
+
+
+EXPORT_C void CHuiVisual::Draw(CHuiGc& aGc) const
+    {
+    if (Flags() & EHuiVisualFlagDrawOnlyAsExternalContent)
+    	{
+   	    // This is used only as external content visual. Return now if we are not currently drawing
+   	    // external content.
+    	if (!Display() || !Display()->RosterImpl().IsDrawingExternalContent())
+    		{
+			return;
+    		}
+    	}
+
+    TReal32 opacity = EffectiveOpacity();
+    if(opacity <= 0)
+        {
+        // The visual is invisible because it's fully transparent.
+        return;
+        }
+
+    // This is the currently effective area on the display used
+    // by the visual.
+    THuiRealRect displayRect = DisplayRect();
+
+    EnterLocalProjection(aGc, ETrue, 0.f, &displayRect);
+
+    // Apply local transformation.
+    Transform(aGc, ETrue, &displayRect);
+
+    // Draw background brushes (under the content).
+    DrawBrushes(aGc, EHuiBrushLayerBackground);
+
+    // Clip contents to visual rectangle.
+    if(Clipping())
+        {
+        // Visual content clipping is affected by transformation.
+        aGc.PushClip();
+        aGc.Clip(displayRect);
+        aGc.Enable(CHuiGc::EFeatureClipping);
+        }
+    if( iVisualData->iEffect )
+        {
+        // Can we draw effect
+        TBool canUseEffectDrawing = Effect() && !LoadingEffect();
+        
+        // Flag to know what we did
+        TBool didDrawEffect = EFalse;
+        
+        if (canUseEffectDrawing)
+            {
+            // Note that EHuiVisualFlagOpaqueHint improves performance a lot in cached effect drawing 
+            TBool transparent = !(Flags() & EHuiVisualFlagOpaqueHint);
+            TBool refreshCache = Changed();                
+            didDrawEffect = iVisualData->iEffect->CachedDraw(aGc, displayRect, refreshCache, !transparent);
+            }
+
+        if (!didDrawEffect) 
+            {
+            // Draw the visual instead if the effect failed
+            DrawSelf(aGc, displayRect);
+            }
+        else
+            {
+            // Effect was drawn, OpenGLES/OpenVG may be in different state than what Gc thinks so we restore it.
+            aGc.RestoreState();
+            }
+        }
+    else if ( !LoadingEffect() )
+        {
+        // Draw the visual itself.
+        // But don't draw if we are just building the effect - 
+        // We may get a view of the visual with its default values though it may
+        // want to start from size 0 or whatever
+        DrawSelf(aGc, displayRect);
+        }
+    else
+        {
+        // just to keep codescanners and other stupid tools happy
+        }
+
+    if(Clipping())
+        {
+        aGc.PopClip();
+        }
+
+    // Draw foreground brushes (over the content).
+    DrawBrushes(aGc, EHuiBrushLayerForeground);
+
+    // Undo local transformation.
+    Transform(aGc, EFalse);
+    EnterLocalProjection(aGc, EFalse);
+
+    }
+
+
+EXPORT_C void CHuiVisual::DrawBrushes(CHuiGc& aGc, THuiBrushLayer aLayer) const
+    {
+    if(iBrushes)
+        {
+        iBrushes->ActivateBrushGuide(this);
+        iBrushes->Draw(aLayer, aGc, *this);
+        iBrushes->ActivateBrushGuide(NULL);        
+        }
+    }
+
+
+EXPORT_C void CHuiVisual::DrawSelf(CHuiGc& /*aGc*/,
+                                   const TRect& /*aDisplayRect*/) const
+    {
+    // The visual base class doesn't draw a3nything.
+    }
+    
+    
+EXPORT_C void CHuiVisual::BoxMetricToPixelRect(const THuiBoxMetric& aBox, 
+        THuiRealRect& aRectInPixels) const
+    {
+    aRectInPixels.iTl = MetricToPixels(THuiXYMetric(aBox.iLeft, aBox.iTop));
+    aRectInPixels.iBr = MetricToPixels(THuiXYMetric(aBox.iRight, aBox.iBottom));
+    }
+    
+    
+/*EXPORT_C void CHuiVisual::BoxMetricToLocalRect(const THuiBoxMetric& aBox,
+        THuiRealRect& aLocalRect) const
+    {
+    THuiRealRect pixelRect;
+    BoxMetricToPixelRect(aBox, pixelRect);
+    aLocalRect.iTl = PixelPointInLocal(pixelRect.iTl);
+    aLocalRect.iBr = PixelPointInLocal(pixelRect.iBr);
+    }*/
+
+
+EXPORT_C THuiRealPoint CHuiVisual::LocalPointInPixels(const THuiRealPoint& aLocalPoint) const __SOFTFP
+    {
+    return LocalPointInPixels(aLocalPoint, EHuiReferenceStateNow);
+    }
+    
+    
+EXPORT_C THuiRealPoint CHuiVisual::PixelPointInLocal(const THuiRealPoint& aPixelPoint) const __SOFTFP
+    {
+    return PixelPointInLocal(aPixelPoint, EHuiReferenceStateNow);
+    }
+    
+    
+THuiRealPoint CHuiVisual::PixelPointInUnits(const THuiRealPoint& aPixelPoint, 
+    const THuiXYMetric& aUnit, THuiReferenceState aReferenceState ) const __SOFTFP
+    {
+    THuiRealPoint result(0.f, 0.f);
+    THuiXYMetric metric = aUnit;
+    PixelsToMetric(aPixelPoint, metric, aReferenceState); // sets X and Y lengths
+
+    if(aUnit.iX.iMagnitude != 0)
+        {
+        result.iX = metric.iX.iMagnitude / aUnit.iX.iMagnitude;
+        }
+    else
+        {
+        result.iX = 0;
+        }
+
+    if(aUnit.iY.iMagnitude != 0)
+        {
+        result.iY = metric.iY.iMagnitude / aUnit.iY.iMagnitude;
+        }
+    else
+        {
+        result.iY = 0;
+        }
+
+    return result;
+    }
+
+EXPORT_C THuiRealPoint CHuiVisual::MetricReferenceInPixels(const THuiXYMetric& aMetric) const __SOFTFP
+    {
+    return MetricReferenceInPixels(aMetric, EHuiReferenceStateNow);
+    }
+
+
+EXPORT_C THuiRealPoint CHuiVisual::MetricReferenceInPixels(const THuiXYMetric& aMetric, 
+                                                           THuiReferenceState aReferenceState) const __SOFTFP
+    {
+    THuiRealPoint refSizePx(0.f, 0.f);
+    
+    // if weights are used in this context, treat them as normalized units
+    TInt xUnit = (aMetric.iX.iUnit == EHuiUnitWeight) ? EHuiUnitNormalized : aMetric.iX.iUnit;
+    TInt yUnit = (aMetric.iY.iUnit == EHuiUnitWeight) ? EHuiUnitNormalized : aMetric.iY.iUnit;
+        
+    // For normalized units, the reference is the parent size in pixels.
+    if(xUnit == EHuiUnitNormalized || yUnit == EHuiUnitNormalized ||
+       xUnit == EHuiUnitParentWidth || yUnit == EHuiUnitParentWidth ||
+       xUnit == EHuiUnitParentHeight || yUnit == EHuiUnitParentHeight)        
+       {
+        THuiRealPoint sizePx(0.f, 0.f);
+        
+        // Determine parent size in pixels.
+        if(iLayout)
+            {
+            // Recursive fun. We don't want to do this more than once.
+            // (LocalPointInPixels => MetricsToPixels => MetricReferenceInPixels)
+            sizePx = iLayout->LocalPointInPixels(
+                            aReferenceState == EHuiReferenceStateTarget? iLayout->Size().RealTarget() :
+                            iLayout->Size().RealNow(), aReferenceState);
+  	        }
+        else if(Display())
+            {
+            // @todo Jaakko please code review this change!
+//            sizePx = Display()->Size().AsPoint();
+            sizePx = Display()->VisibleArea().Size().AsPoint();
+            }
+        else
+            {
+            // For PC-lint
+            }
+            
+        if(xUnit == EHuiUnitNormalized || xUnit == EHuiUnitParentWidth)
+            {
+            refSizePx.iX = sizePx.iX;
+            }
+        else if(xUnit == EHuiUnitParentHeight)
+            {
+            refSizePx.iX = sizePx.iY;
+            }
+        else
+            {
+            // For PC-lint
+            }
+
+        if(yUnit == EHuiUnitNormalized || yUnit == EHuiUnitParentHeight)
+            {
+            refSizePx.iY = sizePx.iY;
+            }
+        else if(yUnit == EHuiUnitParentWidth)
+            {
+            refSizePx.iY = sizePx.iX;
+            }
+        else
+            {
+            // For PC-lint
+            }
+        }
+
+    // Display-relative units are always relative to the display where the visual is on.
+    if(xUnit == EHuiUnitRelativeToDisplay && Display())
+        {
+        refSizePx.iX = Display()->VisibleArea().Width();
+        }
+    if(yUnit == EHuiUnitRelativeToDisplay && Display())
+        {
+        refSizePx.iY = Display()->VisibleArea().Height();
+        }        
+
+    // For relative to my size units, the reference is the size of this visual in pixels.
+    if(xUnit == EHuiUnitRelativeToMySize || yUnit == EHuiUnitRelativeToMySize ||
+        xUnit == EHuiUnitMyWidth || yUnit == EHuiUnitMyWidth ||
+        xUnit == EHuiUnitMyHeight || yUnit == EHuiUnitMyHeight ||
+        xUnit == EHuiUnitMyDimensionAverage || yUnit == EHuiUnitMyDimensionAverage)
+        {
+        THuiRealPoint sizePx(0.f, 0.f);
+        if(iLayout)
+            {
+            // Recursive fun. We don't want to do this more than once.
+            // (MetricsToPixels => MetricReferenceInPixels)
+            sizePx = iLayout->MetricToPixels(LocalBaseUnit().Abs() * 
+                ((aReferenceState == EHuiReferenceStateTarget) ? iSize.RealTarget() : iSize.RealNow()));
+            }
+        else if(Display())
+            {
+            sizePx = Display()->VisibleArea().Size().AsPoint();
+            }
+        else
+            {
+            // For PC-lint
+            }
+        
+        if(xUnit == EHuiUnitRelativeToMySize || xUnit == EHuiUnitMyWidth)
+            {
+            refSizePx.iX = sizePx.iX;
+            }
+        else if(xUnit == EHuiUnitMyHeight)
+            {
+            refSizePx.iX = sizePx.iY;
+            }
+        else
+            {
+            // For PC-lint
+            }
+        
+        if(yUnit == EHuiUnitRelativeToMySize || yUnit == EHuiUnitMyHeight)
+            {
+            refSizePx.iY = sizePx.iY;
+            }
+        else if(yUnit == EHuiUnitMyWidth)
+            {
+            refSizePx.iY = sizePx.iX;
+            }
+        else
+            {
+            // For PC-lint
+            }
+
+        if( xUnit == EHuiUnitMyDimensionAverage ||
+      	    yUnit == EHuiUnitMyDimensionAverage )
+            {
+            TReal32 average = (sizePx.iX + sizePx.iY) / 2;
+            if(xUnit == EHuiUnitMyDimensionAverage)
+      	        {
+                refSizePx.iX = average;
+                }
+            if(yUnit == EHuiUnitMyDimensionAverage)
+                {           
+                refSizePx.iY = average;
+                }
+            }
+        }
+                
+    if(xUnit == EHuiUnitS60 && Display())
+        {
+        refSizePx.iX = Display()->UnitValue();
+        }
+    if(yUnit == EHuiUnitS60 && Display())
+        {
+        refSizePx.iY = Display()->UnitValue();
+        }
+
+    return refSizePx;        
+    }
+    
+void CHuiVisual::ConvertMetricLengthToPixels(
+    TReal32& aResult, 
+    const THuiMetric& aMetric, 
+    TReal32 aReference)
+    {
+    switch(aMetric.iUnit)
+        {
+        case EHuiUnitPixel:
+            aResult = aMetric.iMagnitude;
+            break;
+        default:
+            aResult = aMetric.iMagnitude * aReference;
+            break;
+        }
+    }
+    
+    
+void CHuiVisual::ConvertPixelsToMetricLength(
+    THuiMetric& aResult, 
+    TReal32 aPixels, 
+    TReal32 aReference)
+    {
+    switch(aResult.iUnit)
+        {
+        case EHuiUnitPixel:
+            aResult.iMagnitude = aPixels;
+            break;
+            
+        default:
+            if(aReference != 0)
+                {
+                aResult.iMagnitude = aPixels / aReference;
+                }
+            else
+                {
+                aResult.iMagnitude = 0;
+                }
+            break;
+        }
+    }
+
+EXPORT_C THuiRealPoint CHuiVisual::MetricToPixels(const THuiXYMetric& aMetric) const __SOFTFP
+    {
+    return MetricToPixels(aMetric,EHuiReferenceStateNow);        
+    }   
+    
+    
+EXPORT_C THuiRealPoint CHuiVisual::MetricToPixels(const THuiXYMetric& aMetric,
+                                                  THuiReferenceState aReferenceState) const __SOFTFP
+    {
+    THuiRealPoint refSizePx = MetricReferenceInPixels(aMetric, aReferenceState);
+    THuiRealPoint resultPx(0.f, 0.f);
+
+    ConvertMetricLengthToPixels(resultPx.iX, aMetric.iX, refSizePx.iX);
+    ConvertMetricLengthToPixels(resultPx.iY, aMetric.iY, refSizePx.iY);
+        
+    return resultPx;        
+    }   
+
+EXPORT_C void CHuiVisual::PixelsToMetric(const THuiRealPoint& aPixels, THuiXYMetric& aMetric) const
+    {
+    PixelsToMetric(aPixels, aMetric, EHuiReferenceStateNow);
+    }
+
+
+EXPORT_C void CHuiVisual::PixelsToMetric(const THuiRealPoint& aPixels, THuiXYMetric& aMetric,
+                                         THuiReferenceState aReferenceState) const
+    {
+    THuiRealPoint refSizePx = MetricReferenceInPixels(aMetric, aReferenceState);
+
+    ConvertPixelsToMetricLength(aMetric.iX, aPixels.iX, refSizePx.iX);
+    ConvertPixelsToMetricLength(aMetric.iY, aPixels.iY, refSizePx.iY);
+    }
+    
+    
+EXPORT_C THuiXYMetric CHuiVisual::LocalBaseUnit() const
+    {
+    if(iLayout)
+        {
+        return iLayout->BaseUnit();
+        }
+    else
+        {
+        return THuiXYMetric(THuiMetric(1.f), THuiMetric(1.f));
+        }
+    }
+    
+    
+void CHuiVisual::ApplyMirroring(THuiRealPoint& aPixels, THuiReferenceState aReferenceState) const
+    {
+    THuiRealPoint refSizePx = MetricReferenceInPixels(
+        THuiXYMetric( THuiMetric(1.f, EHuiUnitNormalized), THuiMetric(1.f, EHuiUnitNormalized)), aReferenceState );
+    
+    if(LocalBaseUnit().iX.iMagnitude < 0)
+        {
+        aPixels.iX = refSizePx.iX - aPixels.iX;
+        }
+    if(LocalBaseUnit().iY.iMagnitude < 0)
+        {
+        aPixels.iY = refSizePx.iY - aPixels.iY;
+        }    
+    }
+    
+
+EXPORT_C TPoint CHuiVisual::LocalToDisplay(const TPoint& aPoint) const
+    {
+    return LocalToDisplay(THuiRealPoint(aPoint));
+    }
+
+
+EXPORT_C THuiRealPoint CHuiVisual::LocalToDisplay(const THuiRealPoint& aPoint) const __SOFTFP
+    {
+    return LocalToDisplay(aPoint, EHuiReferenceStateNow);    
+    }
+
+THuiRealPoint CHuiVisual::LocalToDisplay(const THuiRealPoint& aPoint, 
+    THuiReferenceState aReferenceState) const
+    {
+    THuiRealPoint pos = aPoint;
+    THuiRealPoint resultPx(0.f, 0.f);
+    
+    const CHuiVisual* iter = this;
+    while(iter)
+        {
+        // Add the scroll offset to the position in the local coordinate system.
+        if(iter->iLayout && iter->iLayout->Scrolling())
+            {
+            pos -= (aReferenceState == EHuiReferenceStateNow ? iter->iLayout->ScrollOffset().RealNow() : iter->iLayout->ScrollOffset().RealTarget());
+            }
+        
+        THuiRealPoint coordsPx = iter->LocalPointInPixels(pos);
+        iter->ApplyMirroring(coordsPx, aReferenceState);
+        iter->AlignByOrigin(coordsPx);
+        resultPx += coordsPx;
+        
+        // Move up in the tree.
+        iter = iter->iLayout;
+        if(iter)
+            {
+            pos = (aReferenceState == EHuiReferenceStateNow ? iter->Pos().RealNow() : iter->Pos().RealTarget());
+            }
+        }
+    
+    return resultPx;
+    }
+
+
+EXPORT_C TPoint CHuiVisual::DisplayToLocal(const TPoint& aPoint) const
+    {
+    return DisplayToLocal(THuiRealPoint(aPoint));
+    }
+
+
+EXPORT_C THuiRealPoint CHuiVisual::DisplayToLocal(const THuiRealPoint& aPointInPixels) const __SOFTFP
+    {
+    return DisplayToLocal(aPointInPixels, EHuiReferenceStateNow);
+    }
+
+THuiRealPoint CHuiVisual::DisplayToLocal(const THuiRealPoint& aPointInPixels, 
+    THuiReferenceState aReferenceState) const
+    {
+    THuiRealPoint posPx = aPointInPixels;
+
+    // Undo the effect of the parents.
+    CHuiLayout* ancestor = iLayout;
+    while(ancestor)
+        {
+        THuiRealPoint ancestorPos = (aReferenceState == EHuiReferenceStateNow ? ancestor->Pos().RealNow() : ancestor->Pos().RealTarget());
+        if(ancestor->Scrolling())
+            {
+            ancestorPos -= (aReferenceState == EHuiReferenceStateNow ? ancestor->ScrollOffset().RealNow() : ancestor->ScrollOffset().RealTarget());
+            }
+        THuiRealPoint coordsPx = ancestor->LocalPointInPixels(ancestorPos);
+        ancestor->ApplyMirroring(coordsPx, aReferenceState);
+        ancestor->AlignByOrigin(coordsPx);
+        posPx -= coordsPx;        
+        
+        // Move up in the tree.
+        ancestor = ancestor->iLayout;
+        }
+        
+    // Now we have the point as pixels in the local coordinate system.
+    AlignByOrigin(posPx, ETrue); // undo alignment
+    ApplyMirroring(posPx, aReferenceState); // undo mirroring
+    return PixelPointInLocal(posPx);
+    }
+
+
+EXPORT_C void CHuiVisual::SetChanged()
+    {
+    if ( Display() )
+        {
+        Owner().Env().ContinueRefresh();
+        }
+    iFlags |= EHuiVisualChanged;
+    }
+
+
+EXPORT_C TBool CHuiVisual::Changed() const
+    {
+    if(iFlags & EHuiVisualChanged)
+        {
+        return ETrue;
+        }
+
+    if(iBrushes && iBrushes->Changed())
+        {
+        return ETrue;
+        }
+
+    if(iTransform && iTransform->Changed())
+        {
+        return ETrue;
+        }
+
+    if (iVisualData->iEffect && iVisualData->iEffect->Changed())
+        {
+        return ETrue;
+        }
+    
+    if(Owner().ControlGroup() && Owner().ControlGroup()->iOpacity.Changed())
+        {
+        return ETrue;
+        }
+        
+    if ( iVisualData->iDropShadow && iVisualData->iDropShadow->Changed() )
+        {
+        return ETrue;
+        }
+
+    return iPos.Changed() || iSize.Changed() || iOpacity.Changed();
+    }
+
+
+EXPORT_C void CHuiVisual::ClearChanged()
+    {
+    if (iFlags & EHuiVisualChanged)
+        {
+        HUI_DEBUGF1(_L("CHuiVisual::ClearChanged() - Clearing change flags of visual %x."), this);
+        }
+    iFlags &= ~EHuiVisualChanged;
+
+    if(iBrushes)
+        {
+        iBrushes->ClearChanged();
+        }
+
+    if(iTransform)
+        {
+        iTransform->ClearChanged();
+        }
+        
+    if ( iVisualData->iDropShadow )
+        {
+        iVisualData->iDropShadow->ClearChanged();
+        }
+
+    iPos.ClearChanged();
+    iSize.ClearChanged();
+    iOpacity.ClearChanged();
+    }
+
+
+EXPORT_C void CHuiVisual::ReportChanged()
+    {
+    // Notify the display that the visual's area should be redrawn.
+    CHuiDisplay* display = NULL;
+        
+    // Select active display, fallback to own display.
+    // For scaled tv-out cloning the active display takes care of scaling direty areas too. 
+    if (iOwner && iOwner->Env().CurrentDisplay())
+        {
+        display = iOwner->Env().CurrentDisplay();    
+        }
+    else
+        {
+        display = Display();    
+        }
+
+    if(display)
+        {
+        // If nothing has changed, then we don't need to notify anything.
+        // The change flags will be cleared after the frame has been fully drawn.
+        if(!Changed() && !ParentChanged())
+            {
+            return;
+            }
+
+        TRect dirty;
+        TBool transformedReport = EFalse;
+        
+        if(iTransform && /*!(Flags() & EHuiVisualFlagClipping) &&*/
+           iTransform->NonIdentityCount() > 0)
+            {
+            __ASSERT_DEBUG( Display() != NULL,
+                            THuiPanic::Panic(THuiPanic::EVisualHasNoDisplayDuringRefresh) );
+
+            if (display->UseTransformedDirtyRegions())
+                {
+                // There is a transformation and display would like to handle transformed dirty 
+                // rects...in practice this means that we are using bitgdi and in that case
+                // the transformations do not happen in 3D, so calculating transformed dirty
+                // rects might be possible. 
+                // -> so we enable transfromation during dirty area reporting. 
+                THuiRealRect displayRect = DisplayRect();
+                EnterLocalProjection(*display->Gc(), ETrue, 0.f, &displayRect);
+                Transform(*display->Gc(), ETrue, &displayRect);
+                dirty = TRect(HUI_ROUND_FLOAT_TO_INT(displayRect.iTl.iX), HUI_ROUND_FLOAT_TO_INT(displayRect.iTl.iY),
+                              HUI_ROUND_FLOAT_TO_INT(displayRect.iBr.iX), HUI_ROUND_FLOAT_TO_INT(displayRect.iBr.iY));
+                ExpandRectWithContent(dirty);
+                transformedReport = ETrue;                    
+                }
+            else
+                {
+                // Display says it does not want to handle transformed dirty rects.                   
+                // There is a transformation and the visual is not clipped. We
+                // could try to calculate where the visual's content may end up,
+                // but in a 3D projection this may be too complicated to yield
+                // any benefits. We will just assume that the entire display
+                // needs redrawing.
+                dirty = TRect(TPoint(0, 0), Display()->VisibleArea().Size());
+                }
+
+            }
+        else
+            {
+            THuiRealRect displayRect = DisplayRect();
+            dirty = TRect(HUI_ROUND_FLOAT_TO_INT(displayRect.iTl.iX), HUI_ROUND_FLOAT_TO_INT(displayRect.iTl.iY),
+                          HUI_ROUND_FLOAT_TO_INT(displayRect.iBr.iX), HUI_ROUND_FLOAT_TO_INT(displayRect.iBr.iY));
+            ExpandRectWithContent(dirty);
+            }
+
+		TRect& previousDrawn = display->IsDisplayTypeTvOut() ? iVisualData->iPreviousDrawnTvOut : iPreviousDrawn;
+        
+        // CombineAndAddDirtyRegion modifies "dirty" param by transforming it.
+        // "previousDrawn" is supposed to be already transformed. 
+        display->CombineAndAddDirtyRegion(previousDrawn, dirty);                
+        
+        // Note that "previousDrawn" is a reference so it updates correct member data.
+        previousDrawn = dirty;       
+
+        if (transformedReport)
+            {
+            EnterLocalProjection(*display->Gc(), EFalse);
+            Transform(*display->Gc(), EFalse);                                        
+            }
+            
+        }
+    }
+
+
+EXPORT_C void CHuiVisual::EnterLocalProjection(
+        CHuiGc& aGc, TBool aApply, TReal32 /*aExtraOffset*/,
+        const THuiRealRect* aVisibleRect) const __SOFTFP
+    {
+    TReal32 depthOffset = iDepthOffset.Now();
+        
+    if(aApply && depthOffset != 0)
+        {
+        aGc.Enable(CHuiGc::EFeatureDepthTest);        
+        aGc.Push(EHuiGcMatrixModel);
+        aGc.Translate(EHuiGcMatrixModel, 0.f, 0.f, depthOffset);
+        }
+        
+    if(aApply && (iFlags & EHuiVisualFlag3DProjection))
+        {
+        // Change to a 3D projection.
+        aGc.SetProjection(CHuiGc::EProjectionPerspective);
+
+        if(aVisibleRect && (Flags() & EHuiVisualFlagLocalHorizon))
+            {
+            aGc.SetFrustumOffset(aVisibleRect->Center());
+            }
+
+        if(iFlags & EHuiVisualFlagNoDepthOcclusion)
+            {
+            aGc.Disable(CHuiGc::EFeatureDepthTest);
+            }
+        else
+            {
+            aGc.Enable(CHuiGc::EFeatureDepthTest);
+            }
+        
+        if(iFlags & EHuiVisualFlagNoDepthUpdate)
+            {
+            aGc.Disable(CHuiGc::EFeatureDepthWrite);
+            }
+        else
+            {
+            aGc.Enable(CHuiGc::EFeatureDepthWrite);
+            }
+        }
+
+    if(!aApply)
+        {
+        // Back to normal.
+        aGc.Disable(CHuiGc::EFeatureDepthTest);
+        aGc.Enable(CHuiGc::EFeatureDepthWrite);
+        }
+
+    if(!aApply && (iFlags & EHuiVisualFlag3DProjection))
+        {
+        // Back to 2D projection.
+        aGc.SetProjection();
+        }
+        
+    if(!aApply && depthOffset != 0)
+        {
+        aGc.Pop(EHuiGcMatrixModel);
+        }
+    }
+
+
+EXPORT_C void CHuiVisual::Transform(CHuiGc& aGc, TBool aApply,
+                                    const THuiRealRect* aVisibleRect) const
+    {
+    if(iTransform)
+        {
+        if(aApply)
+            {
+            THuiRealPoint center;
+            aGc.Push(EHuiGcMatrixModel);
+            if(aVisibleRect)
+                {
+                center.iX = aVisibleRect->iTl.iX + aVisibleRect->Width() * iTransform->OriginPoint().iX.Now();
+                center.iY = aVisibleRect->iTl.iY + aVisibleRect->Height() * iTransform->OriginPoint().iY.Now();
+                aGc.Translate(EHuiGcMatrixModel, center.iX, center.iY, 0.f);
+                }
+            iTransform->Execute(EHuiGcMatrixModel, aGc);
+            if(aVisibleRect)
+                {
+                aGc.Translate(EHuiGcMatrixModel, -center.iX, -center.iY, 0.f);
+                }
+            }
+        else
+            {
+            aGc.Pop(EHuiGcMatrixModel);
+            }
+        }
+    }
+
+
+EXPORT_C void CHuiVisual::SetPadding(TInt aPadding)
+    {
+    iPadding = THuiBoxMetric(THuiXYMetric(aPadding, aPadding));
+    SetChanged();
+    }
+
+
+EXPORT_C void CHuiVisual::SetPadding(const TPoint& aPadding)
+    {
+    iPadding = THuiBoxMetric(THuiXYMetric(aPadding.iX, aPadding.iY));
+    SetChanged();
+    }
+
+
+EXPORT_C void CHuiVisual::SetPadding(const THuiBoxMetric& aPadding)
+    {
+    iPadding = aPadding;
+    SetChanged();
+    }
+    
+    
+EXPORT_C const THuiBoxMetric& CHuiVisual::Padding() const
+    {
+    return iPadding;
+    }
+    
+EXPORT_C THuiRealRect CHuiVisual::PaddingInPixels() const __SOFTFP
+    {
+    return PaddingInPixels(EHuiReferenceStateNow);
+    }
+    
+EXPORT_C THuiRealRect CHuiVisual::PaddingInPixels(THuiReferenceState aReferenceState) const __SOFTFP
+    {
+    THuiRealRect paddingInPixels;
+    BoxMetricToPixelRect(Padding(), paddingInPixels, aReferenceState);
+    return paddingInPixels;    
+    }
+        
+
+EXPORT_C void CHuiVisual::MoveToFront(TInt aTransitionTime)
+    {
+    if(iLayout)
+        {
+        // Make this the last child of the parent layout.
+        iLayout->MoveVisualToFront(*this, aTransitionTime);
+        }
+    else if(Display())
+        {
+        Display()->Roster().MoveVisualToFront(this);
+        }
+    else
+        {
+        // for PC lint
+        }
+    }
+
+
+EXPORT_C void CHuiVisual::GetDualAlpha(TReal32 aOpacity, TReal32 aSecondary,
+                              TInt& aPrimaryAlpha, TInt& aSecondaryAlpha)
+    {
+    // Default values.
+    aPrimaryAlpha = TInt(255 * aOpacity);
+    aSecondaryAlpha = 0;
+
+    if(aSecondary < 1 && aOpacity < 1)
+        {
+        /** This reduces the artifact where the sharp image is clearly
+                   visible during a transition even though secondary alpha
+                   has a value near to one. Not completely perfect, though. */
+        aPrimaryAlpha = TInt(255 * (aOpacity + aSecondary * .5 * (aOpacity - 1)));
+
+        if(aPrimaryAlpha < 0)
+            {
+            aPrimaryAlpha = 0;
+            }
+        }
+    else if(aSecondary >= 1)
+        {
+        aPrimaryAlpha = 0;
+        }
+    else
+        {
+        // for PC lint
+        }
+
+    if(aSecondary > 0)
+        {
+        aSecondaryAlpha = TInt(255 * aOpacity * aSecondary);
+        }
+    }
+
+
+EXPORT_C CHuiTransformation& CHuiVisual::Transformation()
+    {
+    if(!iTransform)
+        {
+        THuiPanic::Panic(THuiPanic::EVisualTransformNotEnabled);
+        }
+
+    return *iTransform;
+    }
+
+CHuiTransformation* CHuiVisual::Transformation() const
+    {
+    return iTransform;        
+    }
+
+
+EXPORT_C void CHuiVisual::EnableTransformationL(TBool aIsTransformed)
+    {
+    if(iTransform && !aIsTransformed)
+        {
+        // Disable scrolling.
+        delete iTransform;
+        iTransform = NULL;
+        }
+    else if(!iTransform && aIsTransformed)
+        {
+        // Enable scrolling.
+        iTransform = CHuiTransformation::NewL();
+        }
+    else
+        {
+        // for PC lint
+        }
+     
+    }
+
+
+EXPORT_C void CHuiVisual::DumpTree() const
+    {
+    TBuf<100> buf;
+    TBuf<100> className;
+    GetClassName(className);
+    GetInstanceName(buf);
+    buf.AppendFormat(_L(" [label=%S];"), &className);
+    CHuiStatic::Printf(buf);
+    }
+
+
+EXPORT_C void CHuiVisual::GetInstanceName(TDes& aName) const
+    {
+    GetClassName(aName);
+	TUint addr = TUint(this);
+	aName.AppendFormat(_L("%u"), addr);
+    }
+
+
+EXPORT_C void CHuiVisual::GetClassName(TDes& aName) const
+    {
+    aName = _L("CHuiVisual");
+    }
+
+
+EXPORT_C void CHuiVisual::EnableBrushesL(TBool aEnabled)
+    {
+    if(aEnabled && !iBrushes)
+        {
+        iBrushes = CHuiBrushArray::NewL();
+        }
+    else if(!aEnabled && iBrushes)
+        {
+        if ( iBrushes->Count() )
+            {
+            iFlags |= EHuiVisualChanged;
+            }
+        
+        delete iBrushes;
+        iBrushes = 0;
+        }
+    else
+        {
+        // for PC lint
+        }
+    }
+
+
+EXPORT_C CHuiBrushArray* CHuiVisual::Brushes()
+    {
+    return iBrushes;
+    }
+
+
+EXPORT_C void CHuiVisual::NotifySkinChangedL()
+    {
+    // Do nothing by default.
+    }
+
+
+EXPORT_C void CHuiVisual::ExpandRectWithContent(TRect& aRect) const
+    {
+    if(iBrushes)
+        {
+        iBrushes->ActivateBrushGuide(this);
+        iBrushes->ExpandVisualRect(aRect);
+        iBrushes->ActivateBrushGuide(NULL);
+        }
+/*
+    if (iVisualData->iEffect)
+        {
+        TRect visualArea;
+        iVisualData->iEffect->VisualArea(visualArea);
+        aRect.BoundingRect(visualArea);
+        }
+*/        
+    }
+
+
+EXPORT_C void CHuiVisual::SetTagL(const TDesC8& aTag)
+    {
+//    ASSERT(!iTag);
+    if ( iTag )
+        {
+        delete iTag;
+        iTag = NULL;
+        }
+    if ( aTag.Length() > 0 )
+        {
+        iTag = aTag.AllocL();
+        }
+    }
+
+
+EXPORT_C const TDesC8& CHuiVisual::Tag() const
+    {
+    if(iTag)
+        {
+        return *iTag;
+        }
+    return KHuiVisualUndefinedTag;
+    }
+
+
+EXPORT_C TBool CHuiVisual::IsTagged() const
+    {
+    return iTag != 0;
+    }
+
+
+EXPORT_C CHuiVisual* CHuiVisual::FindTag(const TDesC8& aTag)
+    {
+    // Look for the tag in this visual's tag descriptor.
+    if(iTag && HuiUtil::TagMatches(*iTag, aTag))
+        {
+        return this;
+        }
+    else
+        {
+        // Could not find it.
+        return NULL;
+        }
+    }
+
+EXPORT_C TReal32 CHuiVisual::BrushOpacity() const __SOFTFP
+    {
+    return EffectiveOpacity();
+    }
+
+
+EXPORT_C THuiRealRect CHuiVisual::BrushRect() const __SOFTFP
+    {
+    // Subclasses can override this to make content-dependent brush guides.
+    return DisplayRect();
+    }
+
+
+EXPORT_C CHuiSkin& CHuiVisual::BrushSkin() const
+    {
+    return Skin();
+    }
+
+HUI_SESSION_OBJECT_IMPL_EXPORT(CHuiVisual, ETypeVisual)
+
+EXPORT_C void CHuiVisual::VisualExtension(const TUid& /*aExtensionUid*/, TAny** /*aExtensionParams*/)
+    {
+    }
+
+EXPORT_C void CHuiVisual::UpdateSiblingLayout(TInt aTransitionTime)
+    {
+  	if(Layout() && !(Layout()->Flags() & EHuiVisualFlagFreezeLayout))
+  	    {
+  	    Layout()->UpdateChildrenLayout(aTransitionTime);
+  	    }
+    }
+
+EXPORT_C void CHuiVisual::BoxMetricToPixelRect(const THuiBoxMetric& aBox,
+                                               THuiRealRect& aRectInPixels, 
+                                               THuiReferenceState aReferenceState) const
+    {
+    aRectInPixels.iTl = MetricToPixels(THuiXYMetric(aBox.iLeft, aBox.iTop), aReferenceState);
+    aRectInPixels.iBr = MetricToPixels(THuiXYMetric(aBox.iRight, aBox.iBottom), aReferenceState);
+    }
+        
+EXPORT_C THuiRealPoint CHuiVisual::LocalPointInPixels(const THuiRealPoint& aLocalPoint, 
+                                                      THuiReferenceState aReferenceState) const __SOFTFP
+    {
+    return MetricToPixels(LocalBaseUnit().Abs() * aLocalPoint, aReferenceState);
+    }
+
+EXPORT_C THuiRealPoint CHuiVisual::PixelPointInLocal(const THuiRealPoint& aPixelPoint,
+                                                     THuiReferenceState aReferenceState) const __SOFTFP
+    {
+  	return PixelPointInUnits(aPixelPoint, LocalBaseUnit().Abs(), aReferenceState);
+  	}
+
+
+TInt CHuiVisual::FindTacticon( TInt aEventType ) const
+    {
+    for ( TInt i = 0 ; i < iVisualData->iTacticons.Count() ; i++ )
+        {
+        if ( iVisualData->iTacticons[i].iEventType == aEventType )
+            {
+            return i;
+            }       
+        }
+    return KErrNotFound;
+    }
+    
+TInt CHuiVisual::TactileFeedback( TInt aEventType ) const
+    {
+    TInt returnType = KErrNotFound;
+    TInt index = FindTacticon( aEventType );
+    
+    if ( index == KErrNotFound )
+        {
+        // Try the layout
+        CHuiVisual* layoutToCheck = Layout();
+        while ( layoutToCheck )
+            {
+            index = layoutToCheck->FindTacticon( aEventType );
+            if ( index != KErrNotFound )
+                {
+                returnType = layoutToCheck->iVisualData->iTacticons[index].iFeedbackType;
+                break;
+                }
+            
+            layoutToCheck = layoutToCheck->Layout();
+            }
+        }
+    else
+        {
+        returnType = iVisualData->iTacticons[index].iFeedbackType;
+        }
+        
+    return returnType;
+    }
+
+EXPORT_C void CHuiVisual::SetTactileFeedbackL( TInt aEventType, TInt aFeedbackType )
+    {
+    if ( aFeedbackType < 0 || aEventType < 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+    
+    // find if it exists already
+    const TInt index = FindTacticon( aEventType );
+    
+    if ( index != KErrNotFound )
+        {
+        iVisualData->iTacticons[index].iFeedbackType = aFeedbackType;
+        }
+    else
+        {            
+        // Create new item
+        THuiVisualPrivateData::TTacticon newTacticon;
+        newTacticon.iEventType = aEventType;
+        newTacticon.iFeedbackType = aFeedbackType;
+        
+        iVisualData->iTacticons.AppendL( newTacticon );
+        }
+    }
+    
+EXPORT_C TBool CHuiVisual::HasTactileFeedback( TInt aEventType ) const
+    {
+    if ( aEventType == KHuiTactileFeedbackEventTypeNone )
+        {
+        return iVisualData->iTacticons.Count();
+        }
+    
+    const TInt index = FindTacticon( aEventType );
+    return index != KErrNotFound;
+    }
+    
+EXPORT_C void CHuiVisual::RemoveTactileFeedback( TInt aEventType )
+    {
+    if ( aEventType == KHuiTactileFeedbackEventTypeNone )
+        {
+        iVisualData->iTacticons.Reset();
+        return;
+        }
+        
+    const TInt index = FindTacticon( aEventType );
+    if ( index != KErrNotFound )
+        {
+        iVisualData->iTacticons.Remove(index);
+        }
+    }
+    
+
+TBool CHuiVisual::IsTransformed() const
+    {
+    return iTransform != 0;    
+    }
+
+TBool CHuiVisual::ParentChanged() const
+    {
+    // Check if parent has been changed in a way that requires me to report myself as changed
+    // This may be a performance issue because this function is called often.
+    const CHuiLayout* iter = Layout(); // start from parent
+    const CHuiLayout* parent = Layout(); // Immediate parent
+    
+    while(iter)
+        {
+        // Parent scrolling, we check this before clipping because otherwise
+        // iPreviousDrawn would not get updated for children correctly as it
+        // is nowdays only updated in ReportChanged() method (and no more in the draw).
+        // NOTE: Only immediate parent is checked for better performance (no need to
+        // check others ?)
+        // TBD: Should transformations be also checked before clipping ?
+        if (parent->Scrolling() && parent->ScrollOffset().Changed())
+            {
+            return ETrue;    
+            }   
+
+        // If the parent is clipped, there is no need to check any more.
+        // If the parent in this case has been changed, the parent rect is added
+        // into the dirty regions and will be drawn anyways.
+        if ( iter->Clipping() )
+            {
+            return EFalse;
+            }
+        
+        
+        // Parent transformation affects dirty regions if visual is not clipped and outside parent
+        if(iter->IsTransformed() && iter->Transformation()->Changed())
+            {
+            return ETrue;
+            }
+        // Parent opacity affects this visuals opacity if visual is not clipped and outside parent
+        if (iter->iOpacity.Changed())
+            {
+            return ETrue;    
+            }    
+            
+        // Also position (and size) affects
+        if (iter->iPos.Changed() || iter->iSize.Changed())
+            {
+            return ETrue;    
+            }   
+            
+                    
+        iter = iter->Layout();
+        }
+    return EFalse;        
+    }
+
+void CHuiVisual::HandleFlagsChanged( TInt aOldFlags )
+    {
+    // If clipping setting is changed, refresh automatically.
+    const TBool oldClipping = aOldFlags & EHuiVisualFlagClipping;
+    const TBool newClipping = iFlags & EHuiVisualFlagClipping;
+    if ( ( oldClipping && !newClipping ) ||
+         ( !oldClipping && newClipping ) )
+        {
+        SetChanged();
+        }
+    }
+
+EXPORT_C void CHuiVisual::EnableDropShadowL( TBool aEnable )
+    {
+    if ( aEnable && !iVisualData->iDropShadow )
+        {
+        CHuiDropShadow* dropShadowHandler = new (ELeave) CHuiDropShadow;
+        CleanupStack::PushL( dropShadowHandler );
+        dropShadowHandler->ConstructL();
+        CleanupStack::Pop( dropShadowHandler );
+        iVisualData->iDropShadow = dropShadowHandler;
+        SetChanged();
+        }
+    else if ( !aEnable && iVisualData->iDropShadow )
+        {
+        delete iVisualData->iDropShadow;
+        iVisualData->iDropShadow = NULL;
+        SetChanged();
+        }
+    }
+    
+EXPORT_C CHuiDropShadow* CHuiVisual::DropShadowHandler() const
+    {
+    return iVisualData->iDropShadow;
+    }
+CHuiBrushArray* CHuiVisual::Brushes() const
+    {
+    return iBrushes;
+    }
+
+
+EXPORT_C CHuiFxEffect* CHuiVisual::Effect() const
+    {
+    if (!iVisualData)
+        return NULL;
+    else
+        return iVisualData->iEffect;
+    }
+
+EXPORT_C MHuiEffectable *CHuiVisual::Effectable() const
+    {
+    if (!iVisualData)
+        return NULL;
+    else
+        return iVisualData->iEffectable;
+    }
+
+TBool CHuiVisual::IsDelayedEffectSource() const
+    {
+    if (!Effectable())
+        return EFalse;
+    else
+        {
+        TBool b = Effectable()->EffectGetSource();
+        if (!b)
+            { // if not found from this object, try the parent
+            CHuiLayout *l = Layout();
+            if (l)
+                return Layout()->IsDelayedEffectSource();
+            }
+        return b;
+        }
+   }
+
+EXPORT_C void CHuiVisual::SetEffect(CHuiFxEffect* aEffect)
+    {
+    SetFreezeState(EFalse);
+
+    __ALFFXLOGSTRING1("CHuiVisual::SetEffect - : 0x%d ", aEffect );
+    // If effect is replaced by a new effect, we don't want the effect end callback
+    // as it would end the new effect
+    if ( iVisualData->iEffect )
+        {
+#ifdef _ALF_FXLOGGING
+        if ( aEffect )
+            {
+            __ALFFXLOGSTRING1("CHuiVisual::SetEffect - : Deleting previous 0x%x effect on this visual ", iVisualData->iEffect );
+            }
+#endif
+        iVisualData->iEffect->SetEffectEndObserver( NULL, 0 );
+        }
+    delete iVisualData->iEffect;
+    iVisualData->iEffect = aEffect;
+    // The parser must now go
+    delete iVisualData->iEffectParser;
+    iVisualData->iEffectParser = NULL; // the parser just died
+    SetChanged();
+    }
+    
+void CHuiVisual::SetEffectParser( CHuiFxEffectParser* aEffectParser )
+    {
+    delete iVisualData->iEffectParser;
+    iVisualData->iEffectParser = aEffectParser;
+    }