--- /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;
+ }
+ }
+