diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiVisual.cpp --- /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 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; + }