mmplugins/mmfwplugins/src/Plugin/subtitle/subtitlegraphicdrawer/mmfsubtitlegraphicdrawer.cpp
changeset 0 b8ed18f6c07b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/mmfwplugins/src/Plugin/subtitle/subtitlegraphicdrawer/mmfsubtitlegraphicdrawer.cpp	Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,293 @@
+// Copyright (c) 2008-2009 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:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <graphics/wsgraphicscontext.h>
+#include "mmfsubtitlegraphicdrawer.h"
+
+// Compensation value in microseconds to account for differences in the requested callback time and the actual
+// time the callback is delivered
+static const TInt KClockDrift=100000;
+
+CMMFSubtitleGraphicDrawer* CMMFSubtitleGraphicDrawer::NewL()
+    {
+    CMMFSubtitleGraphicDrawer* self = new(ELeave) CMMFSubtitleGraphicDrawer();  
+    return self;
+    }
+    
+CMMFSubtitleGraphicDrawer::~CMMFSubtitleGraphicDrawer()
+    {
+    delete iBitmap1;
+    delete iBitmap2;
+    delete iTempBitmap;
+    }
+
+void CMMFSubtitleGraphicDrawer::ConstructL(MWsGraphicDrawerEnvironment& aEnv, const TGraphicDrawerId& aId, MWsClient& aOwner, const TDesC8& /*aData*/)
+    {
+    // Note this method is called by the baseclass not CMMFSubtitleGraphicDrawer
+    BaseConstructL(aEnv, aId, aOwner);
+    
+    // Construct bitmap objects.  Do this here as we can leave usefully with
+    // any construction errors
+	iBitmap1 = new (ELeave) CFbsBitmap();
+	iBitmap2 = new (ELeave) CFbsBitmap();
+	iTempBitmap = new (ELeave) CFbsBitmap();
+    }
+
+
+// From CwsGraphicDrawer
+void CMMFSubtitleGraphicDrawer::HandleMessage(const TDesC8& aData)
+    {   
+    // Retreive message type from buffer
+    TInt8 msgType = aData[0];
+    
+    switch (msgType)
+    	{    	
+	case ESubtitleCrpMessageInit:
+		{
+		iCaptureRegion = ETrue;
+		TPckgBuf<TSubtitleCrpMsgInit> message;
+		message.Copy(aData);
+		ProcessMessageInit(message());
+		}
+		break;
+		
+	case ESubtitleCrpMessageInitSimple:
+		iCaptureRegion = ETrue;
+		iBitmap1Valid=EFalse;
+    	iBitmap2Valid=EFalse;
+    	iTempBitmapValid=ETrue;
+		break;
+		
+	case ESubtitleCrpMessageDrawFrame:
+		{
+		iState = ESubtitleGraphicStateDrawFrame;
+		TPckgBuf<TSubtitleCrpMsgDrawFrame> message;
+		message.Copy(aData);
+		ProcessMessageDrawFrame(message());
+		}
+		break;
+		
+	case ESubtitleCrpMessageSwapFrame:
+		{
+		iState = ESubtitleGraphicStateSwapFrame;
+		TPckgBuf<TSubtitleCrpMsgRenderSwapFrame> message;
+		message.Copy(aData);
+        ProcessMessageSwapFrame(message());
+		}
+        break;
+    	
+    case ESubtitleCrpMessageClear:
+    	iDisplayClearDue.UniversalTime();
+    	iState = ESubtitleGraphicStateClear;
+    	break;
+		
+	default:
+		// Silently ignore unrecognised messages
+		// Clear messages for example require no further processing
+		// Set the state to waiting so DoDraw will do nothing.
+		iState = ESubtitleGraphicStateWaiting;
+	break;
+    	}
+    
+    // Note clear messages require no further processing we just need to invalidate the display
+
+	// Ask WSERV to redraw the CRP
+    Invalidate();
+    }
+
+void CMMFSubtitleGraphicDrawer::DoDraw(MWsGc& aGc, const TRect& aRect, const TDesC8& /*aData*/) const
+	{	
+	// For some crp rendering states we need to ensure that this DoDraw has been called
+	// in response to Invalidate() and not generated in response to a portion of the CRP
+	// becoming invald for some reason (menus, dialogs etc)
+	
+	// Store the invalid region as our subtitle region to complete initialization.
+	if (iCaptureRegion)
+		{
+		iSubtitleRegion = aRect;
+		iCaptureRegion = EFalse;
+		}
+	
+	// If the current state is waiting we do dont need to do anything
+	if ((iSubtitleRegion.IsEmpty())||(iState==ESubtitleGraphicStateWaiting))
+		{
+		return;
+		}
+	
+	switch(iState)
+	    {   	
+	case ESubtitleGraphicStateDrawFrame:
+	case ESubtitleGraphicStateSwapFrame:	
+		// Blt new content
+		DoBitBlt(aGc, iDirtyRegion);
+		
+		if ( iDisplayDuration.Int64() > 0 )
+			{
+			// Schedule a clear frame to remove this subtitle after the requested time
+		    // Note clear messages require no further processing we just need to schedule a redraw
+			aGc.ScheduleAnimation(iSubtitleRegion, iDisplayDuration.Int64());
+			iDisplayClearDue.UniversalTime();
+			iDisplayClearDue=iDisplayDuration.Int64()+iDisplayClearDue.Int64()-KClockDrift;
+			iState = ESubtitleGraphicStateClear;
+			}
+		else
+			{
+			// Redraw this frames content until instructed to stop
+			iState = ESubtitleGraphicStateRefreshContent;
+			}
+	    break;
+	
+	case ESubtitleGraphicStateRefreshContent:
+		// Refresh current frame content
+		DoBitBlt(aGc, iDirtyRegion);
+		break;
+		
+	case ESubtitleGraphicStateClear:
+		{
+		// Clear is due, check to see if the clear is due now
+		TTime timeNow;
+		timeNow.UniversalTime();
+		TInt diff=iDisplayClearDue.Int64()-timeNow.Int64();
+		
+		if ( diff > 0 )
+			{
+			// Clear is not due do a standard bitblt		
+			DoBitBlt(aGc, iDirtyRegion);
+			}
+		else
+			{
+			// No further processing required as WSERV clears the region for us
+			iState = ESubtitleGraphicStateWaiting;
+			}
+		}
+		break;
+		
+	default:
+		// Should never happen
+#ifdef _DEBUG
+		RDebug::Printf("CMMFSubtitleGraphicDrawer::DoDraw() - Invalid State in Drawer should never happen");
+		User::Invariant();
+#endif
+	    break;
+	    }
+	}
+
+/**
+Renders the current bitmap frame
+*/
+void CMMFSubtitleGraphicDrawer::DoBitBlt(MWsGc& aGc, const TRect& aRect) const
+	{
+	MWsGraphicsContext* context = aGc.ObjectInterface<MWsGraphicsContext>();
+	if(!context)
+		{
+		RDebug::Printf("CMMFSubtitleGraphicDrawer::DoBitBlt can not get MWsGraphicsContext");
+		return;
+		}
+	context->Push();
+	
+	switch (iCurrentFrame)
+		{
+		case ESubtitleGraphicFrame1:
+			if (iBitmap1Valid)
+				{
+				context->BitBlt(iSubtitleRegion.iTl + aRect.iTl, *iBitmap1, aRect);
+				}
+			break;
+		
+		case ESubtitleGraphicFrame2:
+			if (iBitmap2Valid)
+				{
+				context->BitBlt(iSubtitleRegion.iTl + aRect.iTl, *iBitmap2, aRect);
+				}
+			break;
+		
+		case ESubtitleGraphicFrame3:
+			if (iTempBitmapValid)
+				{
+				context->BitBlt(iSubtitleRegion.iTl + aRect.iTl, *iTempBitmap, aRect);
+				}
+			break;
+		
+		default:
+			break;
+		}
+
+	context->Pop();	
+	}
+
+/**
+Process initialization message from client.  Readies the CRP for drawing
+@param aMessage Message data received from client
+*/
+void CMMFSubtitleGraphicDrawer::ProcessMessageInit(TSubtitleCrpMsgInit& aMessage)
+	{
+	// Duplicate client bitmap handles
+	// These are verified by the client before they are sent
+	iBitmap1->Reset();
+	TInt err = iBitmap1->Duplicate(aMessage.iBitmapHandle1);
+	
+	// This should never be a problem but check in debug modes just in case
+	// We dont do this in release mode as it panics the window server...
+	__ASSERT_DEBUG(KErrNone==err, User::Invariant());
+	
+	iBitmap2->Reset();
+	err = iBitmap2->Duplicate(aMessage.iBitmapHandle2);
+	// This should never be a problem but check in debug modes just in case
+	// We dont do this in release mode as it panics the window server...
+	__ASSERT_DEBUG(KErrNone==err, User::Invariant());
+	
+	iCurrentFrame=ESubtitleGraphicFrame1;
+	iBitmap1Valid=ETrue;
+	iBitmap2Valid=ETrue;
+	iTempBitmapValid=EFalse;
+	}
+
+/**
+Process draw frame message from client.  Draw the bitmap provided.
+@param aMessage Message data received from client
+*/
+void CMMFSubtitleGraphicDrawer::ProcessMessageDrawFrame(TSubtitleCrpMsgDrawFrame& aMessage)
+	{
+	// Duplicate client bitmap handle
+	iTempBitmap->Reset();
+	iTempBitmap->Duplicate(aMessage.iBitmapHandle);
+	
+    iOldDirtyRegion=iDirtyRegion;
+	iDirtyRegion=aMessage.iDirtyRegion;
+		
+    iDisplayDuration=aMessage.iDisplayDuration;
+    iCurrentFrame=ESubtitleGraphicFrame3;
+	}
+
+/**
+Process swap frame message from client.  Draws the current backbuffer provided.
+@param aMessage Message data received from client
+*/
+void CMMFSubtitleGraphicDrawer::ProcessMessageSwapFrame(TSubtitleCrpMsgRenderSwapFrame& aMessage)
+	{
+	__ASSERT_DEBUG((aMessage.iExpectedFrame==ESubtitleGraphicFrame1)||(aMessage.iExpectedFrame==ESubtitleGraphicFrame2), User::Invariant());
+	
+	iDisplayDuration = aMessage.iDisplayDuration;
+	iOldDirtyRegion=iDirtyRegion;
+	iDirtyRegion = aMessage.iDirtyRegion;
+	
+	// Swap the frame pointer
+	iCurrentFrame = static_cast<TSubtitleGraphicFrame>(aMessage.iExpectedFrame);
+	}