mmplugins/imagingplugins/imagedisplay/plugins/mng/PixelConsumer.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/imagedisplay/plugins/mng/PixelConsumer.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,333 @@
+// Copyright (c) 2004-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
+	@internalTechnology */
+#include <fbs.h>
+
+#include "PixelConsumer.h"
+
+inline 
+void SetRgbPixel(TUint8* ptr,const TUint aR, const TUint aG,const TUint aB)
+	{
+	*ptr   	= TUint8(aB);
+	ptr[1]	= TUint8(aG);
+	ptr[2]  = TUint8(aR);
+	}
+
+inline 
+void SetRgbaPixel(TUint8* ptr,const TUint aR, const TUint aG,const TUint aB, const TUint aA)
+	{
+	*ptr	= TUint8(aB);
+	ptr[1]	= TUint8(aG);
+	ptr[2]	= TUint8(aR);
+	ptr[3]  = TUint8(aA);
+	}
+
+void CPixelConsumerBase::InitL(const TSize& aFrameSize)
+	{
+	ASSERT(iFrameBuffer == NULL);
+	iFrameSize	= aFrameSize;
+	iFrameBufferSize = iFrameSize.iHeight*iFrameSize.iWidth*iPixelSize;
+	
+	iFrameBuffer= new (ELeave) TUint8[ iFrameBufferSize ];
+	
+	if(iPixelSize == KRgbaPixelSize)
+		{
+		TUint32* ptr = reinterpret_cast<TUint32*>(iFrameBuffer);
+		TUint32* end = ptr+(iFrameBufferSize/iPixelSize);
+		while(ptr < end)
+			{
+			*ptr++ = 0xFF000000; // initialise 32bit RGB buffer with opaque alpha (for both 16MU and 16MA)
+			}
+		}
+	else
+		{
+		Mem::Fill(iFrameBuffer, iFrameBufferSize, 0);	
+		}
+
+	iImageRect = TRect(TPoint(0,0),iFrameSize.AsPoint());
+	SetClippingRect(iImageRect);
+	iNeedBufferFlush = ETrue;
+	}
+
+CPixelConsumerBase::~CPixelConsumerBase()
+	{
+	delete [] iFrameBuffer;
+	}
+
+void CPixelConsumerBase::Prepare()
+	{
+	iNeedBufferFlush = ETrue;
+	GetBuffer();
+	iCurrentPos.SetXY(0,0);
+	}
+
+void CPixelConsumerBase::SetClippingRect(const TRect& aRect)
+	{
+	iClippingRect	= aRect;
+	iRealOutputRect	= aRect;
+	iRealOutputRect.Intersection(iImageRect);
+	}
+
+void CPixelConsumerBase::GetBitmap(CFbsBitmap& aBitmap, const TRect& aSourceRect)
+	{
+	ASSERT(aBitmap.DisplayMode()==EColor16M || aBitmap.DisplayMode()==EColor16MA || 
+			aBitmap.DisplayMode()==EColor16MU || aBitmap.DisplayMode()==EGray256);
+	
+	TRect imgRect(TPoint(0,0), iFrameSize.AsPoint() );
+	imgRect.Intersection(aSourceRect);
+	ASSERT(imgRect == aSourceRect); // ensure that source rect is within the buffer
+
+	if (iNeedBufferFlush)
+		{
+		TUint8* DataAddr=reinterpret_cast<TUint8*>( aBitmap.DataAddress() );
+		const TUint8* FrameBufAddr	=iFrameBuffer + iPixelSize*( aSourceRect.iTl.iY*iFrameSize.iWidth+aSourceRect.iTl.iX );
+		const TInt KLineSize		=iPixelSize*aSourceRect.Width();
+		const TInt KFrameBufLineSize=iPixelSize*iFrameSize.iWidth;
+		const TInt KBmpScanLineLength= CFbsBitmap::ScanLineLength(aBitmap.SizeInPixels().iWidth, aBitmap.DisplayMode() );
+		for (TInt y=aSourceRect.iBr.iY-aSourceRect.iTl.iY; y; --y, DataAddr +=KBmpScanLineLength, FrameBufAddr+=KFrameBufLineSize)
+			{
+			Mem::Copy(DataAddr, FrameBufAddr, KLineSize);
+			}
+		}
+	iNeedBufferFlush = EFalse;
+	}
+
+void CPixelConsumerBase::Clear(TUint aColour, const TRect& aRect)
+	{
+	GetBuffer();
+	const TInt width=aRect.Width();
+	if (width<1)
+		{
+		return;
+		}
+	
+	switch(iPixelSize)
+		{
+		case KRgbPixelSize:
+			{
+			const TUint r=Red(aColour);
+			const TUint g=Green(aColour);
+			const TUint b=Blue(aColour);
+			for (TInt y=aRect.iTl.iY; y < aRect.iBr.iY; ++y)
+				{
+				TUint8* pPixel=(iFrameBuffer+KRgbPixelSize*(y*iFrameSize.iWidth+aRect.iTl.iX));
+				TInt x=width;
+				do {
+					SetRgbPixel(pPixel, r, g, b);
+					pPixel+=KRgbPixelSize;
+					} while (--x);
+				}
+			break;
+			}
+		case KRgbaPixelSize:
+			{
+			const TUint r=Red(aColour);
+			const TUint g=Green(aColour);
+			const TUint b=Blue(aColour);
+			const TUint a=Alpha(aColour);
+			for (TInt y=aRect.iTl.iY; y < aRect.iBr.iY; ++y)
+				{
+				TUint8* pPixel=(iFrameBuffer+KRgbaPixelSize*(y*iFrameSize.iWidth+aRect.iTl.iX));
+				TInt x=width;
+				do {
+					SetRgbaPixel(pPixel, r, g, b, a);
+					pPixel+=KRgbaPixelSize;
+					} while (--x);
+				}
+			break;
+			}
+		case KAlphaPixelSize:
+			{
+			TUint8* pPixel=iFrameBuffer+KAlphaPixelSize*(aRect.iTl.iY*iFrameSize.iWidth+aRect.iTl.iX);
+			for (TInt y=aRect.iTl.iY; y < aRect.iBr.iY; ++y)
+				{
+				Mem::Fill(pPixel, width, aColour );
+				pPixel += iFrameSize.iWidth;
+				}
+			break;
+			}
+		default:
+			ASSERT(EFalse);
+		}
+	}
+
+void CPixelConsumerBase::ClearAlpha(TUint aColour, const TRect& aRect)
+	{
+	ASSERT(iPixelSize == KRgbaPixelSize);
+	
+	GetBuffer();
+	const TInt width=aRect.Width();
+	if (width<1)
+		{
+		return;
+		}
+
+	const TUint a=Alpha(aColour);
+	for (TInt y=aRect.iTl.iY; y < aRect.iBr.iY; ++y)
+		{
+		TUint8* pPixel=(iFrameBuffer+KRgbaPixelSize*(y*iFrameSize.iWidth+aRect.iTl.iX));
+		TInt x=width;
+		do 
+			{
+			pPixel[3] = a;
+			pPixel+=KRgbaPixelSize;
+			} while (--x);
+		}
+	}
+
+void CRgbPixelConsumer::SetRGBPixel(TRgbaColour aPixelColour)
+	{
+	const TPoint RealPos( iOrigin.iX + iCurrentPos.iX, iOrigin.iY + iCurrentPos.iY );
+	if (Contains(iRealOutputRect, RealPos))
+		{
+		
+		if (NULL != iAlphaConsumer)
+			{
+// IF AlphaConsumer (if trans or alpha), then get alpha value
+			const TUint alpha= (iAlphaConsumer->Enabled()? Alpha(aPixelColour) : KOpaqueAlpha );
+//
+// alpha blending is: 
+//			Aresult * Cresult	= Afg*Cfg + Abg*Cbg - Afg*Abg*Cbg OR Afg*Cfg + Cbg * Abg*(1 - Afg)
+//			Aresult				= Afg + (1 - Afg) * Abg
+//			where 0 <= Alpha < 1
+//			However we are using fixed point where
+//				  0 <= Alpha <= 0xff
+//
+			if (alpha)
+				{
+				const TInt bufferOffset=RealPos.iY*iFrameSize.iWidth+RealPos.iX;
+				TUint8* ptr=iFrameBuffer+KRgbPixelSize*bufferOffset;
+
+				if (alpha < KOpaqueAlpha)
+					{
+					const TUint oldA = iAlphaConsumer->GetPixel(bufferOffset);
+					if (oldA)
+						{
+						const TUint a2=(oldA*(0xffu-alpha)+0x80)>>8;
+						
+						TUint oldC=TUint(*ptr);
+						*ptr++ = TUint8(( Blue(aPixelColour)*alpha + oldC*a2)>>8);
+												
+						oldC=TUint(*ptr);
+						*ptr++ = TUint8(( Green(aPixelColour)*alpha + oldC*a2)>>8);
+
+						oldC=*ptr;
+						*ptr   = TUint8(( Red(aPixelColour)*alpha + a2*oldC )>>8 );
+
+						iAlphaConsumer->SetPixelByBufferOffset(bufferOffset, alpha + a2 );
+						}
+					else
+						{
+						// "old" pixel alpha is fully transparent, so set the pixel and its alpha
+						// in the first pass, it will be 0x00 so set both pixel and alpha
+						iAlphaConsumer->SetPixelByBufferOffset(bufferOffset, alpha);
+						SetRgbPixel(ptr, 	Red(aPixelColour), Green(aPixelColour), Blue(aPixelColour));
+						}
+					}
+				else
+					{
+					// pixel alpha is opaque, so set the pixel and its alpha
+					iAlphaConsumer->SetPixelByBufferOffset(bufferOffset, alpha);
+					SetRgbPixel(ptr, 	Red(aPixelColour), Green(aPixelColour), Blue(aPixelColour));
+					}
+				}
+			}
+		else
+			{
+			// no Alpha blending just set the pixel
+			TUint8* ptr=iFrameBuffer+KRgbPixelSize*(RealPos.iY*iFrameSize.iWidth+RealPos.iX);
+			SetRgbPixel(ptr, 	Red(aPixelColour), Green(aPixelColour), Blue(aPixelColour));
+			}
+		}
+
+	if (++iCurrentPos.iX >= iFrameSize.iWidth)
+		{
+		iCurrentPos.iX = 0;
+		++iCurrentPos.iY;
+		}
+	}
+
+void CRgbPixelConsumer::SetRGBAPixel(TRgbaColour aPixelColour)
+	{
+		const TPoint RealPos( iOrigin.iX + iCurrentPos.iX, iOrigin.iY + iCurrentPos.iY );
+	if (Contains(iRealOutputRect, RealPos))
+		{
+		const TInt bufferOffset=RealPos.iY*iFrameSize.iWidth+RealPos.iX;
+		TUint8* ptr=iFrameBuffer+KRgbaPixelSize*bufferOffset;
+		
+		if (NULL != iAlphaConsumer)
+			{
+// IF AlphaConsumer (if trans or alpha), then get alpha value
+			const TUint alpha= (iAlphaConsumer->Enabled()? Alpha(aPixelColour) : KOpaqueAlpha );
+// alpha blending is: 
+//			Aresult * Cresult	= Afg*Cfg + Abg*Cbg - Afg*Abg*Cbg OR Afg*Cfg + Cbg * Abg*(1 - Afg)
+//			Aresult				= Afg + (1 - Afg) * Abg
+//			where 0 <= Alpha < 1
+//			However we are using fixed point where
+//				  0 <= Alpha <= 0xff
+
+			if (alpha)
+				{
+				if (alpha < KOpaqueAlpha)
+					{
+					const TUint oldA = iAlphaConsumer->GetPixel(bufferOffset);
+					if (oldA)
+						{
+						const TUint a2=(oldA*(0xffu-alpha)+0x80)>>8;
+						
+						TUint oldC=TUint(*ptr);
+						*ptr++ = TUint8(( Blue(aPixelColour)*alpha + oldC*a2)>>8);
+												
+						oldC=TUint(*ptr);
+						*ptr++ = TUint8(( Green(aPixelColour)*alpha + oldC*a2)>>8);
+
+						oldC=*ptr;
+						*ptr++   = TUint8(( Red(aPixelColour)*alpha + a2*oldC )>>8 );
+						
+						*ptr	= iAlphaEnabled ? TUint8(Alpha((alpha + a2) << KAlphaShift)) : KOpaqueAlpha;
+						
+						iAlphaConsumer->SetPixelByBufferOffset(bufferOffset, alpha + a2);
+						}
+					else
+						{
+						// "old" pixel alpha is fully transparent, so set the pixel and its alpha
+						// in the first pass, it will be 0x00 so set both pixel and alpha
+						iAlphaConsumer->SetPixelByBufferOffset(bufferOffset, alpha);
+						SetRgbaPixel(ptr, 	Red(aPixelColour), Green(aPixelColour), Blue(aPixelColour), iAlphaEnabled ? Alpha((alpha) << KAlphaShift) : KOpaqueAlpha);
+						}
+					}
+				else
+					{
+					iAlphaConsumer->SetPixelByBufferOffset(bufferOffset, alpha);
+					SetRgbaPixel(ptr, 	Red(aPixelColour), Green(aPixelColour), Blue(aPixelColour), KOpaqueAlpha);
+					}
+				}
+			}
+		else // dealing with source with no transparency
+			{
+			// Just set the pixel to fully opaque
+			SetRgbaPixel(ptr, Red(aPixelColour), Green(aPixelColour), Blue(aPixelColour), KOpaqueAlpha);
+			}
+		}
+
+	if (++iCurrentPos.iX >= iFrameSize.iWidth)
+		{
+		iCurrentPos.iX = 0;
+		++iCurrentPos.iY;
+		}
+	}
+