diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiCanvasVisual.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiCanvasVisual.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,1270 @@ +/* +* 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: Implementation of CHuiCanvasVisual. +* +*/ + + + +#include "uiacceltk/HuiCanvasVisual.h" +#include "HuiRenderPlugin.h" +#include "uiacceltk/HuiGc.h" +#include "uiacceltk/HuiPanic.h" +#include "uiacceltk/HuiUtil.h" +#include "uiacceltk/HuiStatic.h" +#include "uiacceltk/HuiEnv.h" +#include "uiacceltk/HuiControl.h" +#include "uiacceltk/HuiVisual.h" +#include "uiacceltk/HuiLayout.h" +#include "uiacceltk/HuiTextMesh.h" +#include "uiacceltk/HuiCanvasCmdBufferReader.h" +#include "uiacceltk/HuiTransformation.h" +#include "huicanvasgc.h" +#include "HuiRenderSurface.h" +#include "huicanvastexturecache.h" +#include "huicanvasbackground.h" +#include +#include +#include +#include "huicanvasalfpainter.h" +#include "huicanvaswspainter.h" +#include "HuiRosterImpl.h" +#include "huilayoutdata.h" +#include "Matrix.h" + + +#include "HuiFxEffect.h" +#include "HuiCmdBufferBrush.h" + +/** Flag to convienintly disable/enable canvas render buffer usage if needed */ +/* Turned to EFalse as DFS77 was having booting problems in wk26 */ +/* Now checked dynamically from CHuiRenderer to allow different behaviour in DFS77 and DFS79 */ +//const TBool KHuiCanvasVisualUseRenderBuffer = EFalse; + +NONSHARABLE_STRUCT( CHuiCanvasVisual::THuiCanvasVisualData ) + { + THuiCanvasVisualData(){}; + TInt iCommandSetType; + TInt iCanvasFlags; + + // Canvas background + CHuiCanvasBackground* iBackground; + CHuiCanvasPainter* iCanvasPainter; + + // External draw content. Can be layout visual that have child visuals. + CHuiVisual* iExternalContentVisual; // Not owned + + CHuiCanvasVisual* iParentCanvas; // Not owned + RPointerArray iChildCanvasList; // Does not own contained visuals + RRegionBuf<5> iClipRegion; + RRegionBuf<20> iPaintedRegion; + CHuiCanvasRenderBuffer* iStoredRenderBuffer; + + // For handling possible background surface that window may have + TBool iLayerUsesAlphaFlag; + TRect iLayerExtent; + }; + +EXPORT_C CHuiCanvasVisual* CHuiCanvasVisual::AddNewL(CHuiControl& aOwnerControl, + CHuiLayout* aParentLayout) + { + CHuiCanvasVisual* canvas = STATIC_CAST(CHuiCanvasVisual*, + aOwnerControl.AppendVisualL(EHuiVisualTypeCanvas, aParentLayout)); + return canvas; + } + + +CHuiCanvasVisual::CHuiCanvasVisual(MHuiVisualOwner& aOwner) + : CHuiLayout(aOwner) + { + } + +void CHuiCanvasVisual::ConstructL() + { + CHuiLayout::ConstructL(); + + iCanvasVisualData = new (ELeave) THuiCanvasVisualData; + iCanvasVisualData->iCommandSetType = ECommandBufferWs; + iCanvasVisualData->iCanvasFlags = 0; + iCanvasVisualData->iExternalContentVisual = NULL; + iCanvasVisualData->iParentCanvas = NULL; + iCanvasVisualData->iBackground = NULL; + iCanvasVisualData->iCanvasPainter = NULL; + + iCanvasVisualData->iBackground = CHuiCanvasBackground::NewL(); + iCanvasVisualData->iBackground->SetVisual(this); + + iCanvasVisualData->iCanvasPainter = CHuiCanvasWsPainter::NewL(); + iCanvasVisualData->iCanvasPainter->SetVisual(this); + iCanvasVisualData->iStoredRenderBuffer = 0; + + TBool useCanvasRenderBuffer = CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowVisualPBufferSurfaces); + iCanvasVisualData->iCanvasPainter->EnableRenderBuffer(useCanvasRenderBuffer); + + iCanvasVisualData->iLayerUsesAlphaFlag = EFalse; + iCanvasVisualData->iLayerExtent = TRect(); + + // subwindow effects + EnableBrushesL(ETrue); + } + + +CHuiCanvasVisual::~CHuiCanvasVisual() + { + FreeRenderBuffer(); + if(iCanvasVisualData->iExternalContentVisual) + { + // Allow the external content visual to be drawn normally + iCanvasVisualData->iExternalContentVisual->ClearFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + } + + if (iCanvasVisualData) + { + ClearCommandSet(); + delete iCanvasVisualData->iBackground; + iCanvasVisualData->iBackground = NULL; + delete iCanvasVisualData->iCanvasPainter; + iCanvasVisualData->iCanvasPainter = NULL; + iCanvasVisualData->iExternalContentVisual = NULL; + + // Tell parent that we are destructed + if (iCanvasVisualData->iParentCanvas) + { + iCanvasVisualData->iParentCanvas->RemoveChildCanvas(this); + } + + // Tell children + for (TInt i=0; iiChildCanvasList.Count(); i++) + { + iCanvasVisualData->iChildCanvasList[i]->SetParentCanvas(NULL); + } + + iCanvasVisualData->iPaintedRegion.Close(); + iCanvasVisualData->iClipRegion.Close(); + iCanvasVisualData->iChildCanvasList.Close(); + } + + delete iCanvasVisualData; + iCanvasVisualData = NULL; + + } + +CHuiCanvasGc& CHuiCanvasVisual::CanvasGc() const + { + return iCanvasVisualData->iCanvasPainter->CanvasGc(); + } + +EXPORT_C void CHuiCanvasVisual::SetClearBackground(CHuiDisplay::TClearMode aClearBackground) + { + if (iCanvasVisualData->iBackground->ClearBackground() != aClearBackground) + { + iCanvasVisualData->iBackground->SetClearBackground(aClearBackground); + SetChanged(); + } + } + +EXPORT_C void CHuiCanvasVisual::SetBackgroundColor(const TRgb& aBackgroundColor) + { + if (iCanvasVisualData->iBackground->BackgroundColor() != aBackgroundColor) + { + iCanvasVisualData->iBackground->SetBackgroundColor(aBackgroundColor); + SetChanged(); + } + } + +EXPORT_C void CHuiCanvasVisual::SetBackgroundItems(const RArray& aItems) + { + iCanvasVisualData->iBackground->SetBackgroundItems(aItems); + } + + +EXPORT_C void CHuiCanvasVisual::SetExternalContentL(CHuiVisual* aVisual) + { + if (aVisual) + { + // Clip external content to canvas visual rect + SetClipping(ETrue); + } + else + { + SetClipping(EFalse); + } + + iCanvasVisualData->iExternalContentVisual = aVisual; + } + +EXPORT_C CHuiVisual* CHuiCanvasVisual::ExternalContent() + { + return iCanvasVisualData->iExternalContentVisual; + } + + +void CHuiCanvasVisual::ExpandRectWithContent(TRect& aRect) const + { + TRect scannedRect(0,0,0,0); + + // HandleBuffer tries to return area where the drawing actually happens, area + // may be smaller than the visuals displayarea. In that case we dont expand + // rect but make it smaller. + HandleBuffer(scannedRect, EScanBuffer, NULL); + + // Note: this could be improved to take care of dirty rects + if (Effect() && Display()) + { + // If there is effect enabled, we cannot say anything about dirty area so + // we set whole screen dirty. + scannedRect = TRect(TPoint(0,0), Display()->VisibleArea().Size()); + } + else if (IsBackgroundDrawingEnabled() || IsExternalContentDrawingEnabled()) + { + // If the visual has external content or draws background, + // set always the whole window area as a content. + scannedRect = aRect; + } + + if (scannedRect != TRect(0,0,0,0)) + { + if (!Brushes()) + { + aRect = scannedRect; + } + else + { + // However if there are brushes they need to know the visual displayrect + // so incase scanned rect is smaller we use bounding rect as the expanded rect + if (!Clipping()) + { + aRect.BoundingRect(scannedRect); + } + } + } + + CHuiLayout::ExpandRectWithContent(aRect); + } + +void CHuiCanvasVisual::HandleBuffer(TRect& aDisplayRect, TInt aAction, CHuiGc* aGc) const + { + if (iCanvasVisualData->iCommandSetType == ECommandBufferWs || iCanvasVisualData->iCommandSetType == ECommandBufferAlf) + { + TRAPD(err, iCanvasVisualData->iCanvasPainter->HandleBufferL(aDisplayRect, aAction, *this, aGc, DisplayRect().iTl.Round())); + if (err) + { + HUI_DEBUG2(_L("CHuiCanvasVisual::HandleBufferL returned:%d command type was: %d"), err,iCanvasVisualData->iCommandSetType); + } + } + else + { + // do nothing + } + + } + + +TBool CHuiCanvasVisual::PrepareDrawL() + { + 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 ETrue; + } + } + + TBool ret = CHuiLayout::PrepareDrawL(); + + if (ret && IsExternalContentDrawingEnabled()) + { + if (Display()) + { + // Enable drawing external visual tree + Display()->RosterImpl().SetDrawingExternalContent(ETrue); + ret = iCanvasVisualData->iExternalContentVisual->PrepareDrawL(); + Display()->RosterImpl().SetDrawingExternalContent(EFalse); + } + } + return ret; + } + + +void CHuiCanvasVisual::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; + } + } + + TBool semiTranparentEffectActive = (Effect() && Effect()->IsSemitransparent()); + TBool childWindowEffectActive = (Effect() && EffectIsAppliedToChildren()); + TBool invisible = (iOpacity.Now() <= EPSILON && !semiTranparentEffectActive); + + if( invisible || + (!HasCommandBuffers(ETrue /*include children*/) && + !childWindowEffectActive && + !IsBackgroundDrawingEnabled() && + !IsExternalContentDrawingEnabled()&& + !IsExternalContentDrawingEnabled(ETrue /*include children*/) + + )) + { + // This will not be visible due to being completely transparent, or the visual does not actually draw anything + + // However, the draw should continue, if the effect is possibly manipulating the opacity of the visual. See CHuiFxVisualLayer::Draw. + return; + } + + if ((IsDelayedEffectSource() || Freezed())) + { + if (StoredRenderBuffer()) + { + DrawStoredFullScreenRenderBuffer(aGc); + return; + } + else if (iCanvasVisualData->iStoredRenderBuffer) + { + DrawStoredVisualRenderBuffer(); + return; + } + } + + // If this visual is completely under another visual, then this visual + // shouldn't draw anything, but of course there might still be children + // that should be drawn. + // For example, consider the case where you have two visuals: + // - visual B is child of window A. + // - visual A and B have exactly same position and size. + // - both are opaque. + // Thus, window A can have 'under opaque' hint, but not window B. + const TBool drawVisualContent = !( Flags() & EHuiVisualFlagUnderOpaqueHint ); + + THuiRealRect area = DisplayRect(); + + // Apply local transformation. + EnterLocalProjection(aGc, ETrue, 0.f, &area); + Transform(aGc, ETrue, &area); + + if (drawVisualContent) + { + DrawBrushes(aGc, EHuiBrushLayerBackground); + } + + if(Clipping()) + { + // @todo Clipping not going to work if there is a transformation? + // Layout clipping is not affected by transformation. + aGc.Enable(CHuiGc::EFeatureClipping); + aGc.PushClip(); + aGc.Clip(area); + } + + // Flag to know what we did + TBool didDrawEffect = EFalse; + + if (EffectActive()) + { + // Note that EHuiVisualFlagOpaqueHint improves performance a lot in cached effect drawing + TBool transparent = EFalse; + transparent |= (!(Flags() & EHuiVisualFlagOpaqueHint)); // Does not have opaque hint -> always transparent + transparent |= iOpacity.Now() < 1.0f; // Opacity less than 1.0f -> always transparent + + TBool refreshCache = EFalse; + if (EffectIsAppliedToChildren()) + { + refreshCache |= ChildTreeChanged(EHuiCanvasFlagExcludeFromParentEffect); + } + else + { + refreshCache |= Changed(); + } + + // TODO: We could update this somewhere else, not here everytime + iCanvasVisualData->iPaintedRegion.Clear(); + TInt paintedAreaCount = PaintedAreaCount(); + for (TInt i=0; iiPaintedRegion.AddRect( CanvasPaintedArea(i).iPaintedRect.Round() ); + } + + didDrawEffect = Effect()->CachedDraw(aGc, area, refreshCache, !transparent, iCanvasVisualData->iPaintedRegion); + } + + if ( !didDrawEffect ) + { + DrawSelf(aGc, area); + } + else + { + // Effect was drawn, OpenGLES/OpenVG may be in different state than what Gc thinks so we restore it. + aGc.RestoreState(); + } + + if (!didDrawEffect) + { + // Draw all children + DrawCanvasChildren(aGc, 0, 0); + } + else if (didDrawEffect && !EffectIsAppliedToChildren()) + { + // Draw all children + DrawCanvasChildren(aGc, 0, 0); + } + else if (didDrawEffect && EffectIsAppliedToChildren()) + { + // Draw only children which do not want to have parent effect applied to them + DrawCanvasChildren(aGc, EHuiCanvasFlagExcludeFromParentEffect, 0); + } + + if (drawVisualContent && IsContentDrawingEnabled() && IsExternalContentDrawingEnabled()) + { + if (Display()) + { + // Enable drawing external visual tree + Display()->RosterImpl().SetDrawingExternalContent(ETrue); + // The possible effect has been attached to the layout of the visual itself + // If the external content needs an effect, too, it should probably be defined + // separately, or alternatively the drawing of an effect should be able to + // handle the external content, too. + iCanvasVisualData->iExternalContentVisual->Draw(aGc); + Display()->RosterImpl().SetDrawingExternalContent(EFalse); + } + } + + if(Clipping()) + { + // Restore original clipping rectangle. + aGc.PopClip(); + } + + if (drawVisualContent) + { + DrawBrushes(aGc, EHuiBrushLayerForeground); + } + + // Restore original transformation. + Transform(aGc, EFalse); + EnterLocalProjection(aGc, EFalse); + } + + +void CHuiCanvasVisual::DrawSelf(CHuiGc& aGc, const TRect& aDisplayRect) const + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( Tracking() ) + { + RDebug::Print(_L("CHuiCanvasVisual::DrawSelf - tracked visual")); + } +#endif + + TReal32 effectiveOpacity = EffectiveOpacity(); + + if (effectiveOpacity <= 0 || !HasCommandBuffers(ETrue)) + { + // In case background drawing is enabled, and even if we don't have command buffers we still + // want to issue clear. If the background drawing is enabled here, it means that the + // window bound to this visual has a background surface. If we dont do the clear, the + // surface will be covered by the Alf surface, ie. the underlying surface is not visible + // It's quite common for applications using Khronos APIs not to issue any drawing commands, + // as the drawing goes directly via Khronos APIs. + // In that case, the background clearing should only be skipped if the window is not + // visible (ie. the visual is inactive), and that should already be handled elsewhere. + if (!IsBackgroundDrawingEnabled()) + { + return; + } + } + + if ((IsDelayedEffectSource() || Freezed())) + { + if (StoredRenderBuffer()) + { + DrawStoredFullScreenRenderBuffer(aGc); + return; + } + else if (iCanvasVisualData->iStoredRenderBuffer) + { + DrawStoredVisualRenderBuffer(); + return; + } + } + + // Use 'under opaque' hint to optimize drawing. + // See comment from CHuiCanvasVisual::Draw for further details. + const TBool drawVisualContent = !( Flags() & EHuiVisualFlagUnderOpaqueHint ); + + // Canvas clipping is done in DrawSelf instead of Draw so that canvas clipping does not clip effects + if (IsCanvasClippingEnabled()) + { + aGc.Enable(CHuiGc::EFeatureClipping); + aGc.PushClip(); + aGc.Clip(ClipRegion()); + } + + // Draws background if it has been defined + if (drawVisualContent && IsBackgroundDrawingEnabled()) + { + iCanvasVisualData->iBackground->DrawSelf(aGc, aDisplayRect); + } + + aGc.Push(EHuiGcMatrixModel); + + TRect displayRect = aDisplayRect; + + if (IsContentDrawingEnabled()) + { + // Handle buffer normally unless layered subwindow effects are active + if (drawVisualContent && !IsContentDrawingLayered()) + { + HandleBuffer(displayRect, EDrawBuffer, &aGc); + } + + if (EffectActive() && EffectIsAppliedToChildren()) + { + DrawCanvasChildren(aGc, 0, EHuiCanvasFlagExcludeFromParentEffect); + } + } + + aGc.Pop(EHuiGcMatrixModel); + + if(IsCanvasClippingEnabled()) + { + // Restore original clipping rectangle. + aGc.PopClip(); + } + } + +void CHuiCanvasVisual::DrawChildren(CHuiGc& aGc) const + { + // Draw child windows, begin + TBool afterOthers = EFalse; + const TInt count = Count(); + for(TInt i = 0; i < count; ++i) + { + CHuiVisual* visual = iHuiLayoutPrivateData->iChildren[i]; + //Ignore inactive child visuals + if ( visual->Flags()& EHuiVisualFlagInactive ) + { + continue; + } + if(visual->Flags() & EHuiVisualFlagDrawAfterOthers) + { + afterOthers = ETrue; + continue; + } + + // @todo No need to draw children that won't be visible. + visual->Draw(aGc); + } + if(afterOthers) + { + for(TInt i = 0; i < count; ++i) + { + if(iHuiLayoutPrivateData->iChildren[i]->Flags() & EHuiVisualFlagDrawAfterOthers) + { + iHuiLayoutPrivateData->iChildren[i]->Draw(aGc); + } + } + } + } + +void CHuiCanvasVisual::DrawCanvasChildren(CHuiGc& aGc, TInt aIncludeCanvasFlags, TInt aExcludeCanvasFlags) const + { + // Draw child windows, begin + TBool afterOthers = EFalse; + const TInt count = Count(); + for(TInt i = 0; i < count; ++i) + { + // This cast is not really safe, but dynamic cast is slow + CHuiCanvasVisual* visual = (CHuiCanvasVisual*) iHuiLayoutPrivateData->iChildren[i]; + //Ignore inactive child visuals + if ((visual->Flags()& EHuiVisualFlagInactive)) + { + continue; + } + + if (aIncludeCanvasFlags && !(visual->CanvasFlags()& aIncludeCanvasFlags)) + { + continue; + } + + if (aExcludeCanvasFlags && (visual->CanvasFlags()& aExcludeCanvasFlags)) + { + continue; + } + + if(visual->Flags() & EHuiVisualFlagDrawAfterOthers) + { + afterOthers = ETrue; + continue; + } + + // @todo No need to draw children that won't be visible. + visual->Draw(aGc); + } + if(afterOthers) + { + for(TInt i = 0; i < count; ++i) + { + if(iHuiLayoutPrivateData->iChildren[i]->Flags() & EHuiVisualFlagDrawAfterOthers) + { + iHuiLayoutPrivateData->iChildren[i]->Draw(aGc); + } + } + } + } + +TBool CHuiCanvasVisual::Changed() const + { + if (iCanvasVisualData->iCanvasPainter->BuffersChanged()) + { + return ETrue; + } + else if(CHuiLayout::Changed()) + { + return ETrue; + } + + TBool hasChanged = EFalse; + if (IsExternalContentDrawingEnabled()) + { + hasChanged = iCanvasVisualData->iExternalContentVisual->Changed(); + } + + return hasChanged; + } + +TBool CHuiCanvasVisual::ChildTreeChanged(TInt aExcludeCanvasFlags) const + { + // CHuiLayout::Changed() does not check children. + // This utility method checks whole child tree below this visual. + TBool changed = EFalse; + + // Check wheter we should include this visual or igonre it. + if (aExcludeCanvasFlags) + { + if (!(iCanvasVisualData->iCanvasFlags & aExcludeCanvasFlags)) + { + changed |= Changed(); + } + } + + const TInt count = Count(); + for(TInt i = 0; i < count; ++i) + { + CHuiCanvasVisual* visual = (CHuiCanvasVisual*) iHuiLayoutPrivateData->iChildren[i]; + changed |= visual->ChildTreeChanged(aExcludeCanvasFlags); + if (changed) + { + break; + } + } + return changed; + } + + +EXPORT_C void CHuiCanvasVisual::ClearChanged() + { + iCanvasVisualData->iCanvasPainter->ClearAllBuffersChanged(); + CHuiLayout::ClearChanged(); + } + +EXPORT_C void CHuiCanvasVisual::SetChanged() + { + iCanvasVisualData->iCanvasPainter->SetAllBuffersChanged(ETrue); + CHuiLayout::SetChanged(); + } + +EXPORT_C void CHuiCanvasVisual::SetCommandSetL( const TDesC8& aCommands ) + { + Env().CanvasTextureCache().EnableTouchCountCheck(); + ClearCommandSet(); + TRAP_IGNORE(iCanvasVisualData->iCanvasPainter->SetCommandSetL(aCommands)); + + // Memory optimization. Do not prepare cache if visual is inactive. + TBool rosterFrozen = Display() && Display()->Roster().IsVisibleContentFrozen(); + TBool inactive = EFalse; + inactive |= Flags() & EHuiVisualFlagInactive; + inactive |= Flags() & EHuiVisualFlagUnderOpaqueHint; + + if (rosterFrozen || inactive) + { + ClearCache(); + } + else + { + PrepareCache(); + } + + SetChanged(); + Env().CanvasTextureCache().EnableTouchCountCheck(EFalse); + } + +THuiRealPoint CHuiCanvasVisual::ConvertPoint(const THuiRealPoint& aPointInUnits) const + { + // Convert first from units to pixels + THuiRealPoint converted = LocalPointInPixels(aPointInUnits); + + // Pixels are relative to the canvas visual itself, change to display relative + THuiRealRect displayRect = DisplayRect(); + converted.iX += displayRect.iTl.iX; + converted.iY += displayRect.iTl.iY; + + return converted; + } + +void CHuiCanvasVisual::ExpandRect(TRect& aRectToExpand, const TRect& aNewRect) const + { + if (aRectToExpand == TRect(0,0,0,0)) + { + aRectToExpand = aNewRect; + } + else + { + aRectToExpand.BoundingRect(aNewRect); + } + } + +EXPORT_C void CHuiCanvasVisual::SetCommandType( TInt aCommandType ) + { + TRAP_IGNORE(SetCommandTypeL(aCommandType)); + } + +EXPORT_C void CHuiCanvasVisual::ClearCommandSet() + { + iCanvasVisualData->iCanvasPainter->ClearCommandSet(); + SetChanged(); + } + +#ifdef HUI_DEBUG_TRACK_DRAWING +EXPORT_C void CHuiCanvasVisual::SetTrackCommandSet( TFileName& aFileName, TBool aTrack ) + { + iCanvasVisualData->iCanvasPainter->SetTrackCommandSet( aFileName, aTrack || iTrackVisual ); + } +#else +EXPORT_C void CHuiCanvasVisual::SetTrackCommandSet( TFileName&, TBool){ + } +#endif + + +EXPORT_C void CHuiCanvasVisual::AddCommandSetL( const TDesC8& aMoreCommands ) + { + Env().CanvasTextureCache().EnableTouchCountCheck(); + TRAP_IGNORE(iCanvasVisualData->iCanvasPainter->AddCommandSetL(aMoreCommands)); + + // Memory optimization. Do not prepare cache if visual is inactive. + TBool rosterFrozen = Display() && Display()->Roster().IsVisibleContentFrozen(); + TBool inactive = EFalse; + inactive |= Flags() & EHuiVisualFlagInactive; + inactive |= Flags() & EHuiVisualFlagUnderOpaqueHint; + + if (rosterFrozen || inactive) + { + ClearCache(); + } + else + { + PrepareCache(); + } + + SetChanged(); + Env().CanvasTextureCache().EnableTouchCountCheck(EFalse); + } + +EXPORT_C void CHuiCanvasVisual::AddPartialCommandSetL( const TDesC8& aMoreCommands, TBool aLastPart ) + { + iCanvasVisualData->iCanvasPainter->AddPartialCommandSetL(aMoreCommands, aLastPart); + } + + +EXPORT_C void CHuiCanvasVisual::ClearCache() + { + iCanvasVisualData->iCanvasPainter->ClearCache(); + } + +EXPORT_C void CHuiCanvasVisual::PrepareCache() + { + if (iCanvasVisualData->iCanvasPainter->HasCommandBuffers()) + { + TRect displayRect = DisplayRect(); + HandleBuffer(displayRect, EScanBuffer, NULL); + } + } + +void CHuiCanvasVisual::SetCommandTypeL(TInt aCommandType) + { + if (iCanvasVisualData->iCommandSetType == aCommandType) + { + return; + } + + if (aCommandType == ECommandBufferAlf) + { + delete iCanvasVisualData->iCanvasPainter; + iCanvasVisualData->iCanvasPainter = NULL; + iCanvasVisualData->iCommandSetType = ECommandBufferAlf; + iCanvasVisualData->iCanvasPainter = CHuiCanvasAlfPainter::NewL(); + iCanvasVisualData->iCanvasPainter->SetVisual(this); + } + else if (aCommandType == ECommandBufferWs) + { + delete iCanvasVisualData->iCanvasPainter; + iCanvasVisualData->iCanvasPainter = NULL; + iCanvasVisualData->iCommandSetType = ECommandBufferWs; + iCanvasVisualData->iCanvasPainter = CHuiCanvasWsPainter::NewL(); + iCanvasVisualData->iCanvasPainter->SetVisual(this); + TBool useCanvasRenderBuffer = CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowVisualPBufferSurfaces); + iCanvasVisualData->iCanvasPainter->EnableRenderBuffer(useCanvasRenderBuffer); + } + else + { + // For pc lint + } + } + +EXPORT_C TInt CHuiCanvasVisual::PaintedAreaCount() const + { + TInt count = 0; + + count = iCanvasVisualData->iCanvasPainter->PaintedAreaCount(); + + // Check if there is background clearing, it may increase painted area count + if (IsBackgroundDrawingEnabled()) + { + TInt backgroundItemCount = iCanvasVisualData->iBackground->BackgroundItemsCount(); + + if (backgroundItemCount > 0) + { + // Background items + count += backgroundItemCount; + } + else + { + // If there are no background items, then color clearing is used. + count += 1; + } + } + + return count; + } + +EXPORT_C THuiCanvasPaintedArea CHuiCanvasVisual::PaintedArea(TInt aIndex) + { + return CanvasPaintedArea(aIndex); + } + +THuiCanvasPaintedArea CHuiCanvasVisual::CanvasPaintedArea(TInt aIndex) const + { + if (IsBackgroundDrawingEnabled()) + { + // Check if there is background clearing, it may increase painted area count + THuiCanvasPaintedArea background; + TInt backgroundItemCount = iCanvasVisualData->iBackground->BackgroundItemsCount(); + + if (backgroundItemCount > 0) + { + // Background items + if (aIndex < backgroundItemCount) + { + RArray backgroundItems; + iCanvasVisualData->iBackground->GetBackgroundItems(backgroundItems); + + if (backgroundItems[aIndex].ClearMode() == CHuiDisplay::EClearNone) + { + // No clearing -> transparent + background.iPaintType = EHuiCanvasPaintTypeTransparent; + } + else if (backgroundItems[aIndex].ClearMode() == CHuiDisplay::EClearWithColor) + { + // Clearing with color, transparency does NOT depend on alpha but is always opaque + // because clearing is done with "fast" clear and it just writes the alpha + // instead of blending + background.iPaintType = EHuiCanvasPaintTypeOpaque; + } + else + { + // By default assume opaque + background.iPaintType = EHuiCanvasPaintTypeOpaque; + } + + background.iPaintedRect = backgroundItems[aIndex].Rect(); + return background; + } + else + { + return iCanvasVisualData->iCanvasPainter->PaintedArea(aIndex - backgroundItemCount); + } + } + else + { + // If there are no background items, then color clearing is used. + if (aIndex == 0) + { + background.iPaintedRect = DisplayRect(); + background.iPaintType = /*(iCanvasVisualData->iBackground->BackgroundColor().Alpha() == 255) ?*/ EHuiCanvasPaintTypeOpaque;// : EHuiCanvasPaintTypeTransparent; + return background; + } + } + } + + return iCanvasVisualData->iCanvasPainter->PaintedArea(aIndex); + } + +EXPORT_C TInt CHuiCanvasVisual::SetCapturingBufferL(CFbsBitmap* aTargetBuffer) + { + return iCanvasVisualData->iCanvasPainter->SetCapturingBufferL(aTargetBuffer); + } + +EXPORT_C void CHuiCanvasVisual::SetCanvasFlags(TInt aCanvasFlags) + { + TInt oldFlags = iCanvasVisualData->iCanvasFlags; + iCanvasVisualData->iCanvasFlags |= aCanvasFlags; + + // Set visual changed if flags were really changed + if (oldFlags != iCanvasVisualData->iCanvasFlags) + { + SetChanged(); + } + } + +EXPORT_C void CHuiCanvasVisual::ClearCanvasFlags(TInt aCanvasFlags) + { + TInt oldFlags = iCanvasVisualData->iCanvasFlags; + iCanvasVisualData->iCanvasFlags &= ~aCanvasFlags; + + // Set visual changed if flags were really changed + if (oldFlags != iCanvasVisualData->iCanvasFlags) + { + SetChanged(); + } + } + +EXPORT_C TInt CHuiCanvasVisual::CanvasFlags() + { + return iCanvasVisualData->iCanvasFlags; + } + + +EXPORT_C TBool CHuiCanvasVisual::IsBackgroundDrawingEnabled() const + { + TBool drawBackground = EFalse; + drawBackground |= (iCanvasVisualData->iBackground->ClearBackground() != CHuiDisplay::EClearNone); + drawBackground |= (iCanvasVisualData->iBackground->BackgroundItemsCount() > 0); + + if (iCanvasVisualData->iCanvasFlags & EHuiCanvasFlagDisableCanvasBackground) + { + drawBackground = EFalse; + } + return drawBackground; + } + +TBool CHuiCanvasVisual::IsContentDrawingEnabled() const + { + TBool drawContent = ETrue; + if (iCanvasVisualData->iCanvasFlags & EHuiCanvasFlagDisableCanvasContent) + { + drawContent = EFalse; + } + return drawContent; + } + +TBool CHuiCanvasVisual::IsExternalContentDrawingEnabled(TBool aIncludeChildren) const + { + TBool drawExternalContent = EFalse; + if (iCanvasVisualData->iExternalContentVisual) + { + drawExternalContent = ETrue; + } + if (aIncludeChildren) + { + for (TInt i=0; !drawExternalContent && iIsExternalContentDrawingEnabled(ETrue); + } + } + return drawExternalContent; + } + +EXPORT_C void CHuiCanvasVisual::SetParentCanvas(CHuiCanvasVisual* aParent) + { + iCanvasVisualData->iParentCanvas = aParent; + if (aParent) + { + aParent->AddChildCanvas(this); + } + } + +const TRegion& CHuiCanvasVisual::ClipRegion() const + { + iCanvasVisualData->iClipRegion.Clear(); + // TODO: This should be region in cases when canvas shape is non-rectangular, + // for now just use display rect. Window Shape is currently only known by the wspainter, + // so new interface is needed to query it. + iCanvasVisualData->iClipRegion.AddRect(DisplayRect().Round()); + + CHuiCanvasVisual* parent = iCanvasVisualData->iParentCanvas; + if (parent) + { + const TRegion& parentClipRegion = parent->ClipRegion(); + iCanvasVisualData->iClipRegion.Intersect(parentClipRegion); + } + + return iCanvasVisualData->iClipRegion; + } + +void CHuiCanvasVisual::AddChildCanvas(CHuiCanvasVisual* aChild) + { + if (iCanvasVisualData->iChildCanvasList.Find(aChild) == KErrNotFound) + { + iCanvasVisualData->iChildCanvasList.Append(aChild); + } + } + +void CHuiCanvasVisual::RemoveChildCanvas(CHuiCanvasVisual* aChild) + { + for (TInt i=0; iiChildCanvasList.Count(); i++) + { + if (iCanvasVisualData->iChildCanvasList[i] == aChild) + { + iCanvasVisualData->iChildCanvasList.Remove(i); + break; + } + } + } + +EXPORT_C TBool CHuiCanvasVisual::LayerUsesAlphaFlag() + { + return iCanvasVisualData->iLayerUsesAlphaFlag; + } + +EXPORT_C void CHuiCanvasVisual::SetLayerUsesAlphaFlag(TBool aEnabled) + { + iCanvasVisualData->iLayerUsesAlphaFlag = aEnabled; + } + +EXPORT_C TRect& CHuiCanvasVisual::LayerExtent() + { + return iCanvasVisualData->iLayerExtent; + } + +EXPORT_C void CHuiCanvasVisual::SetLayerExtent(TRect& aExtent) + { + iCanvasVisualData->iLayerExtent = aExtent; + if(0)// aExtent != TRect() ) // background surface was set or moved to new place + { + EnableTransformationL(); + CHuiTransformation& transformation = Transformation(); + + TPoint extentPos = aExtent.iTl; + TPoint visualPos = Pos().Now(); + + TReal32 xDif = (TReal32)(extentPos.iX - visualPos.iX); + TReal32 yDif = (TReal32)(extentPos.iY - visualPos.iY); + + TSize extentSize = aExtent.Size(); + TPoint visualSize = Size().Now(); + + TReal32 hVisualWidth = (TReal32)visualSize.iX/2; + TReal32 hVisualHeigth = (TReal32)visualSize.iY/2; + + + TReal32 xScale = (TReal32)extentSize.iWidth/visualSize.iX; + TReal32 yScale = (TReal32)extentSize.iHeight/visualSize.iY; + + // create transformation when applying first time + if(transformation.Count() == 0) + { + transformation.Translate(xDif,yDif); + // for moving the visual origo to visual's top left corner + transformation.Translate(-hVisualWidth,-hVisualHeigth); + transformation.Scale(xScale,yScale); + // move back + transformation.Translate(hVisualWidth,hVisualHeigth); + } + else // update existing transformations + { + CHuiTransformation::TTransform& translate = transformation[0]; + translate.iParams[EHuiTransformParamTranslateX] = xDif; + translate.iParams[EHuiTransformParamTranslateY] = yDif; + + CHuiTransformation::TTransform& translateforscale = transformation[1]; + translateforscale.iParams[EHuiTransformParamTranslateX] = -hVisualWidth; + translateforscale.iParams[EHuiTransformParamTranslateY] = -hVisualHeigth; + + CHuiTransformation::TTransform& scale = transformation[2]; + scale.iParams[EHuiTransformParamScaleX] = xScale; + scale.iParams[EHuiTransformParamScaleY] = yScale; + + CHuiTransformation::TTransform& translateback = transformation[3]; + translateback.iParams[EHuiTransformParamTranslateX] = hVisualWidth; + translateback.iParams[EHuiTransformParamTranslateY] = hVisualHeigth; + } + } + else // background surface was removed + { + EnableTransformationL(EFalse); + } + } + + +TBool CHuiCanvasVisual::IsCanvasClippingEnabled() const + { + return iCanvasVisualData->iCanvasFlags & EHuiCanvasFlagEnableCanvasClipping; + } + +TBool CHuiCanvasVisual::EffectActive() const + { + return Effect() && !LoadingEffect(); + } + +TBool CHuiCanvasVisual::IsContentDrawingLayered() const + { + // TODO: real flag here to check if drawing normally or layered with brushes + return (Brushes() && (Brushes()->Count() > 0)); + } + +EXPORT_C void CHuiCanvasVisual::StoreRenderBufferL() + { + CHuiCanvasGc& gc = CanvasGc(); + CHuiCanvasRenderBuffer *content_rb = Env().CanvasTextureCache().FindCachedRenderBuffer(*this); + if (content_rb) + { + if (!iCanvasVisualData->iStoredRenderBuffer) + { + iCanvasVisualData->iStoredRenderBuffer = gc.CreateRenderBufferL(TSize(0,0)); + } + iCanvasVisualData->iStoredRenderBuffer->InitializeL(content_rb->Size()); + iCanvasVisualData->iStoredRenderBuffer->Copy(*content_rb); + } + } + +void CHuiCanvasVisual::DrawStoredVisualRenderBuffer() const + { + CHuiCanvasGc& gc = CanvasGc(); + THuiRealPoint dest_point = DisplayRect().iTl; + CHuiCanvasRenderBuffer *stored = iCanvasVisualData->iStoredRenderBuffer; + gc.DrawImage(*stored, dest_point); + } + +void CHuiCanvasVisual::DrawStoredFullScreenRenderBuffer(CHuiGc& aGc) const + { + if (!Display()) return; + CHuiCanvasGc& gc = *iHuiLayoutPrivateData->iGc; + gc.SetGc(aGc); + gc.SetDefaults(); + gc.PushTransformationMatrix(); + + TRect displayArea = Display()->VisibleArea(); + TInt h = displayArea.Height(); + + // Pixels are upside down in OpenVG canvas render buffer + if (CHuiStatic::Env().Renderer() == EHuiRendererVg10) + { + gc.Translate(0.0f, h, 0.0f); + gc.Scale(1.f, -1.f, 1.f); + } + + THuiRealPoint dest_point = DisplayRect().iTl; + CHuiCanvasRenderBuffer *stored = StoredRenderBuffer(); + gc.DrawImage(*stored, dest_point); + + gc.PopTransformationMatrix(); + } + +EXPORT_C void CHuiCanvasVisual::FreeRenderBuffer() + { + if (iCanvasVisualData) + { + if (iCanvasVisualData->iStoredRenderBuffer) + { + delete iCanvasVisualData->iStoredRenderBuffer; + iCanvasVisualData->iStoredRenderBuffer = NULL; + } + } + } + +EXPORT_C TBool CHuiCanvasVisual::HasCommandBuffers(TBool aIncludeChildren) const + { + TBool hasCommandBuffers = iCanvasVisualData->iCanvasPainter->HasCommandBuffers(); + if (aIncludeChildren) + { + for (TInt i=0; iHasCommandBuffers(aIncludeChildren); + if (hasCommandBuffers) + { + break; + } + } + } + return hasCommandBuffers; + } + + +void CHuiCanvasVisual::SetSize(const THuiRealSize& aSize, TInt aTransitionTime) + { + CHuiLayout::SetSize(aSize, aTransitionTime); + UpdateChildrenLayout(aTransitionTime); + } + +TBool CHuiCanvasVisual::ChildSize(TInt aOrdinal, TSize& aSize) + { + TBool result(EFalse); + THuiRealRect rect; + TInt childRectStatus(THuiLayoutChildRectUpdateNotNeeded); + childRectStatus = ChildRect(aOrdinal, rect); + if(childRectStatus != THuiLayoutChildRectNotImplemented) + { + result = (childRectStatus & THuiLayoutChildRectSizeUpdateNeeded); + if(result) + { + THuiRealPoint size(rect.Width(), rect.Height()); + aSize = LocalPointInPixels(size).AsSize(); + } + } + return result; + } + +TBool CHuiCanvasVisual::ChildPos(TInt aOrdinal, TPoint& aPos) + { + TBool result(EFalse); + THuiRealRect rect; + TInt childRectStatus(THuiLayoutChildRectUpdateNotNeeded); + childRectStatus = ChildRect(aOrdinal, rect); + if(childRectStatus != THuiLayoutChildRectNotImplemented) + { + result = (childRectStatus & THuiLayoutChildRectPosUpdateNeeded); + if(result) + { + aPos = LocalPointInPixels(rect.iTl); + } + } + return result; + } + +TInt CHuiCanvasVisual::ChildRect(TInt /*aOrdinal*/, THuiRealRect& aPos) + { + THuiRealSize innerSize = InnerSize(); + aPos.iTl = InnerTopLeft(); + aPos.iBr = aPos.iTl + THuiRealPoint(innerSize.iWidth, innerSize.iHeight) ; + return THuiLayoutChildRectLayoutUpdateNeeded; + } + +