sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // CWsRedrawMsgWindow and associated classes definitions
sl@0: // 
sl@0: //
sl@0: 
sl@0: #ifndef __REDRAWMSGWINDOW_H__
sl@0: #define __REDRAWMSGWINDOW_H__
sl@0: 
sl@0: #include "wnredraw.h"
sl@0: #include "redrawmsgwindow.h"
sl@0: 
sl@0: class CWsFbsFont;
sl@0: class CWsDrawableSource;
sl@0: 
sl@0: // This class is intended to be used in cases, where it's needed to track how many times a CFbsBitmap
sl@0: // is referenced, e.g. in redraws, where already drawn bitmaps need to be re-drawn in different position.
sl@0: class CFbsBitmapRef : public CFbsBitmap
sl@0:     {
sl@0: public:
sl@0:     CFbsBitmapRef();
sl@0:     ~CFbsBitmapRef();
sl@0:     inline TInt RefCount() const;
sl@0:     inline void IncRefCount();
sl@0:     inline void DecRefCount();
sl@0: private:
sl@0:     TInt iRefCount;
sl@0:     };
sl@0: 
sl@0: class CWsRedrawMsgWindow : public CWsWindowRedraw
sl@0: 	{
sl@0: 	class CRedrawSegment;
sl@0: 	enum TFlags
sl@0: 		{
sl@0: 		EBackgroundClear=0x0001,		//Clear background when starting redraw
sl@0: 		EBeginEndRedraw=0x0002,			//This window is currently in the middle of a redraw, that is between client calls to BeginRedraw and EndRedraw.
sl@0: 		EPendingScheduledDraw=0x0004,   //We have scheduled a redraw but it hasn't happened yet
sl@0: 		EStoringEntireWindow=0x0008,    //If store commands for the entire window or only the viewport
sl@0: 		ECurrentRedrawFailedStorage=0x0010,		//The current redraw failed to store a command (is reset for each redraw). Is used to make sure we only request a redraw from the client once per failing redraw
sl@0: 		EPreviousRedrawFailedStorage=0x0020,	//The previous redraw failed to store a command. Is used to avoid infinite loops -- if two consecutive redraws fail (i.e. current and previous) then there is no use requesting yet another redraw from the client
sl@0: 		};
sl@0: 	enum TScope
sl@0: 		{
sl@0: 		EStoreEntireWindow,             //We try to obtain draw commands for the entire window
sl@0: 		EStoreViewport                  //We only try to obtain commands for the on screen viewport
sl@0: 		};
sl@0: public:
sl@0: 	enum TRedrawSegmentType
sl@0: 		{
sl@0: 		ESegmentTypePendingRedraw,      // A redraw segment still being received
sl@0: 		ESegmentTypeRedraw              // A segment received between a begin and end redraw
sl@0: 		};
sl@0: public:
sl@0: 	static void StaticInitL();
sl@0: 	CWsRedrawMsgWindow(CWsWindow *aWin);
sl@0: 	~CWsRedrawMsgWindow();
sl@0: 	void AddFbsBitmapsL(TInt aHandle, TInt aMaskHandle);
sl@0: 	void AddFbsBitmapRefL(TInt aHandle);
sl@0: 	void AddWsBitmapsL(TInt aHandle, TInt aMaskHandle);
sl@0: 	void AddWsFontL(TInt aHandle);
sl@0: 	void AddWsDrawableSourceL(TInt aHandle);
sl@0: 	void SetScope(TScope aStore);
sl@0: 	void CleanupBitmapRefArray(const RArray<TInt>& aHandleArray);
sl@0: 	
sl@0: public:	//from CWsWindowRedraw		
sl@0: 	void ConstructL();
sl@0: 	TBool CommandL(TInt aOpcode, TWsWinCmdUnion &aCmd);
sl@0: 	void ClipInvalidRegion(const TRect &aRect);
sl@0: 	TBool NeedsRedraw() const;
sl@0: 	TBool GetRedrawRect(TRect &aRect) const;
sl@0: 	const TRegion& BaseDrawRegion() const;
sl@0: 	const TRegion& InvalidArea() const;
sl@0: 	void ClearRedrawStore(TBool aClearPendingRedraw=EFalse);
sl@0: 	TBool DrawCommand(CWsGc* aGc,const TAny *aCmdData);
sl@0: 	void GcAttributeChange(CWsGc* aGc,const TAny *aCmdData);
sl@0: 	void GcDeactivate(CWsGc* aGc);
sl@0: 	void ClientExposing();
sl@0: 	void DrawWindow();
sl@0: 	void PrepareForResizeL(const TSize &aSize, TSize &aOldSize);
sl@0: 	void Moved();
sl@0: 	TBool Contains(const TArray<TGraphicDrawerId>& aDrawers,const TRegion& aRegion) const;
sl@0: 	TBool ReleaseMemory(MWsMemoryRelease::TMemoryReleaseLevel aLevel);
sl@0: 	void VisibleRegionChange();
sl@0: 	TBool ReadyToDraw() const;
sl@0: 	TInt SizeInBytes() const;
sl@0: 	TBool RedrawingInProgress() const;
sl@0: 	void WindowClosing();
sl@0: 	TBool IsRedrawStoreEmpty() const;
sl@0: 	TBool IsBackgroundClearEnabled() const;
sl@0: 	CFbsBitmap* BitmapFromHandle(TInt aHandle) const;
sl@0: 
sl@0: private: //from CWsWindowRedraw	
sl@0: 	void Invalidate(const TRect * aRect = 0);
sl@0: 	TRgb BackColor() const;
sl@0: 	void Scroll(const TRect &aClipRect, const TPoint &aOffset,const TRect &aRect);
sl@0: 	
sl@0: private:
sl@0: 	void RemoveFromRedrawQueueIfEmpty();
sl@0: 	const TRegion * ReadRegion(const TInt aRegionNum);
sl@0: 	void BeginRedraw(const TRect* aRect);
sl@0: 	void DoBeginRedrawL(const TRect* aRect);
sl@0: 	void SubtractRectFromSegmentArray(const TRect& aRect);
sl@0: 	void EndRedraw();
sl@0: 	void ValidateRect(const TRect *aRect);
sl@0: 	void StoreDrawCommandL(CWsGc* aGc,const TAny *aCmdData);
sl@0: 	void AppendCommandL(const TAny* aCmdData, const TUint16 aOpcodeFlags = 0);
sl@0: 	void StoreAllGcAttributesL(CWsGc* aGc);
sl@0: 	void DrawCommandsL();
sl@0: 	void DiscardStoredCommands();
sl@0: 	TBool DiscardSegmentsOutsideViewport();
sl@0: 	inline TBool NoBuffer() const;
sl@0: 	void DiscardStoredCommandsIfError(TInt aError);
sl@0: 	inline TBool IsFbsBitmapOperation(TInt aOpCode) const;
sl@0: 	inline TBool IsWsBitmapOperation(TInt aOpCode) const;
sl@0: 	inline TBool IsRemoteReadRequired(TInt aOpCode) const;
sl@0: 	inline TBool IsWsFontOperation(TInt aOpCode) const;
sl@0: 	inline TBool IsDrawWsGraphicOperation(TInt aOpCode) const;
sl@0: 	inline TBool IsWsDrawableSourceOperation(TInt aOpCode) const;
sl@0: 	void ReplaceAndAppendCommandL(TInt aOpcode,const TAny* aCmdData);
sl@0: 	// CRedrawSegment related methods
sl@0: 	inline TInt CurrentCommandBufferWritePos() const;
sl@0: 	inline CBufSeg* CurrentDrawCommandBuffer() const;
sl@0: 	void ExpandCommandBufferL(TInt aLength);
sl@0: 	void CommandBufferWrite(const TDesC8& aDes, TInt aLength);
sl@0: 	void CommandBufferWrite(const TAny* aPtr,TInt aLength);
sl@0: 	void CreateNewSegmentL(const TRect& aRect, TRedrawSegmentType aRegionType);
sl@0: 	inline TBool InRedraw() const;
sl@0: 	void PromotePendingSegment();
sl@0: 	void Lock();
sl@0: 	void Unlock();
sl@0: 	void ReleaseRedrawSegments();
sl@0: private:
sl@0: 	static TBool iAtomic;
sl@0: 	RPointerArray<CFbsBitmapRef> iFbsBitmapRefArray;
sl@0: private:
sl@0: 	class CRedrawSegment : public CBase
sl@0: 		{
sl@0: 	public:
sl@0: 		static CRedrawSegment* NewLC(const TRect& aRect, TRedrawSegmentType aNewRegionType, CWsRedrawMsgWindow& aRedraw);
sl@0: 		~CRedrawSegment();
sl@0: 		void AddWsBitmapL(DWsBitmap* bitmap);
sl@0: 		void AddWsDrawableSourceL(CWsDrawableSource* aDrawableSource);
sl@0: 		void AddDrawerL(TGraphicDrawerId aDrawerId);
sl@0: 		TBool ContainsDrawers(const TArray<TGraphicDrawerId>& aDrawers,const TRegion& aRegion) const;
sl@0: 		TInt SizeInBytes() const;
sl@0: 		TBool AppendNonDuplicateBitmapHandleL(TInt aHandle);
sl@0: 	private:
sl@0: 		CRedrawSegment(CWsRedrawMsgWindow& aRedraw);
sl@0: 		void ConstructL(const TRect& aRect, TRedrawSegmentType aNewRegionType);
sl@0: 		void ReleaseFontsBitmapsDrawableSources();
sl@0: 	public:
sl@0: 		TRedrawSegmentType iRedrawSegmentType;
sl@0: 		CBufSeg* iDrawCommands;
sl@0: 		TInt iCurrentCommandBufferWritePos;
sl@0: 		RWsRegion iRegion;
sl@0: 		RPointerArray<DWsBitmap> iWsBitmapArray;
sl@0: 		RPointerArray<CWsFbsFont> iWsFontArray;
sl@0: 		RArray<TGraphicDrawerId> iDrawerArray;
sl@0: 		RPointerArray<CWsDrawableSource> iWsDrawableSourceArray;
sl@0: 		TTime iCreationTime;
sl@0: 	private:
sl@0: 	    CWsRedrawMsgWindow& iRedraw;
sl@0: 	    RArray<TInt> iBitmapHandleArray;
sl@0: 		};
sl@0: 	RWsRegion iInvalid; // Region we haven't been sent a begin redraw for.
sl@0: 	TRect iRedrawRect;
sl@0: 	TRgb iBackColor;
sl@0: 	TInt iFlags;
sl@0: 	// Regions currently in use for drawing this window:
sl@0: 	RPointerArray<CRedrawSegment> iRedrawSegments;
sl@0: 	// The segment we are currently storing to.  This is allowed to be null!
sl@0: 	CRedrawSegment * iCurrentSegment;
sl@0: 	// The last GC we drew with so we can detect changes
sl@0: 	CWsGc* iLastDrawGc;
sl@0: 	// During a scheduled draw, this is the area being drawn to (see comments on ReadRegion)
sl@0: 	RWsRegion iLocalRedrawRegion;
sl@0: 	TInt iMemoryLock;
sl@0: 	TBool iOSBStatus;
sl@0: 	};
sl@0: 
sl@0: inline TBool CWsRedrawMsgWindow::IsRemoteReadRequired(TInt aOpCode) const
sl@0: 	{
sl@0: 	return (aOpCode==EWsGcOpDrawTextPtr || aOpCode==EWsGcOpDrawTextVerticalPtr || 
sl@0: 		aOpCode==EWsGcOpDrawBoxTextPtr || aOpCode==EWsGcOpDrawBoxTextVerticalPtr);
sl@0: 	}
sl@0: 
sl@0: inline TInt CWsRedrawMsgWindow::CurrentCommandBufferWritePos() const
sl@0: 	{
sl@0: 	WS_ASSERT_DEBUG(iCurrentSegment, EWsPanicDrawCommandsInvalidState);
sl@0: 	return iCurrentSegment->iCurrentCommandBufferWritePos;
sl@0: 	}
sl@0: 
sl@0: inline CBufSeg* CWsRedrawMsgWindow::CurrentDrawCommandBuffer() const
sl@0: 	{
sl@0: 	WS_ASSERT_DEBUG(iCurrentSegment, EWsPanicDrawCommandsInvalidState);
sl@0: 	return iCurrentSegment->iDrawCommands;
sl@0: 	}
sl@0: 
sl@0: inline TBool CWsRedrawMsgWindow::InRedraw() const
sl@0: 	{
sl@0: 	return iFlags&EBeginEndRedraw;
sl@0: 	}
sl@0: 	
sl@0: inline TInt CFbsBitmapRef::RefCount() const
sl@0:     {
sl@0:     return iRefCount;
sl@0:     }
sl@0: 
sl@0: inline void CFbsBitmapRef::IncRefCount()
sl@0:     {
sl@0:     ++iRefCount;
sl@0:     }
sl@0: 
sl@0: inline void CFbsBitmapRef::DecRefCount()
sl@0:     {
sl@0:     WS_ASSERT_DEBUG(iRefCount>0,EWsPanicCounterValue);
sl@0:     --iRefCount;
sl@0:     }
sl@0: 	
sl@0: #endif