--- /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;
+ }