--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/bitgdi/sbit/BITBLT.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2645 @@
+// Copyright (c) 1997-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:
+//
+
+#include "BITPANIC.H"
+#include <fntstore.h>
+#include <bitmap.h>
+#include <bitstd.h>
+#include <bitdev.h>
+#include <bitdraw.h>
+#include <bitdrawscaling.h>
+#include <bitdrawinterfaceid.h>
+#include <bmalphablend.h>
+#include <graphics/fbsrasterizer.h>
+#include <graphics/bitmap.inl>
+#include <graphics/gdi/gdiinline.inl>
+
+GLREF_C void XorBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes);
+GLREF_C void AndBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes);
+GLREF_C void InvertBuffer(TUint32* aDestBuffer,TInt aNumBytes);
+GLREF_C void InvertBuffer(TUint8* aDestBuffer,TInt aNumBytes);
+LOCAL_C void TileScanLine(TPtr8& aScanLine,
+ TInt aLengthInPixels,
+ const TPoint& aSrcPt,
+ const CBitwiseBitmap* aMaskBitmap,
+ TLineScanningPosition& aScanLinePos,
+ TUint32* aMaskBase,
+ TDisplayMode aDisplayMode
+ );
+
+/** Draws from another CFbsBitGc.
+
+@param aPoint The position to draw the top left corner of the piece of bitmap
+@param aGc The source bitmap graphics context */
+EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,const CFbsBitGc& aGc)
+ {
+ TRect deviceRect;
+ aGc.iDevice->iDrawDevice->GetDrawRect(deviceRect);
+ BitBlt(aDest,aGc,deviceRect);
+ }
+
+/** Draws a particular rectangle from another CFbsBitGc.
+
+@param aPoint The position to draw the top left corner of the piece of bitmap.
+@param aGc The source bitmap graphics context.
+@param aSrceRect A rectangle defining the piece of the source to be drawn. */
+EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,
+ const CFbsBitGc& aGc,
+ const TRect& aSrceRect)
+ {
+ if (CheckDevice(aSrceRect))
+ return;
+ aGc.CheckDevice();
+ CFbsDevice* srceDevice = aGc.iDevice;
+ if (!srceDevice)
+ return;
+
+ TRect srceRect(aSrceRect);
+ TRect deviceRect;
+ srceDevice->GetDrawRect(deviceRect);
+ if (!srceRect.Intersects(deviceRect))
+ return;
+ srceRect.Intersection(deviceRect);
+
+ const TPoint destPoint(aDest + iOrigin + srceRect.iTl - aSrceRect.iTl);
+ const TRect destRect(destPoint,srceRect.Size());
+ const TPoint offset(srceRect.iTl - destPoint);
+
+ TRect clippedDestRect(destRect);
+ AddRect(clippedDestRect);
+ if (UserClipRect(clippedDestRect))
+ return;
+
+ SetupDevice();
+ aGc.iDevice->DrawingBegin();
+ iDevice->DrawingBegin();
+
+ const TInt limit = iDefaultRegionPtr->Count();
+ TBool opaqueSource = (!IsAlphaChannel(srceDevice->DisplayMode())) && (iDrawMode == EDrawModePEN);
+ for(TInt count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(clippedDestRect))
+ continue;
+ iClipRect.Intersection(clippedDestRect);
+
+ TRect clippedSrceRect(iClipRect);
+ clippedSrceRect.Move(offset);
+
+ if (opaqueSource)
+ iDrawMode = EDrawModeWriteAlpha;// ie write rather then blend
+ DoBitBlt(iClipRect.iTl,srceDevice,clippedSrceRect);
+ if (opaqueSource)
+ iDrawMode = EDrawModePEN;// set it back how it was
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+
+ aGc.iDevice->DrawingEnd();
+ iDevice->DrawingEnd();
+ }
+
+
+/** Draws the whole of a CFbsBitmap.
+
+@param aDest The position to draw the top left corner of the bitmap.
+@param aBitmap The source bitmap. */
+EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,const CFbsBitmap* aBitmap)
+ {
+ if (aBitmap == NULL || !aBitmap->Handle())
+ return;
+
+ aBitmap->BeginDataAccess();
+ BitBlt(aDest,aBitmap,TRect(aBitmap->SizeInPixels()));
+ aBitmap->EndDataAccess(ETrue);
+ }
+
+
+/** Draws a particular rectangle from a CFbsBitmap.
+
+@param aDest The position to draw the top left corner of the bitmap.
+@param aBitmap The source bitmap.
+@param aSrceRect A rectangle defining the piece of the source to be drawn. */
+EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,
+ const CFbsBitmap* aBitmap,
+ const TRect& aSrceRect)
+ {
+ if (aBitmap == NULL || !aBitmap->Handle()|| CheckDevice(aSrceRect))
+ return;
+
+ aBitmap->BeginDataAccess();
+
+ TRect srceRect(aSrceRect);
+ const TRect area(aBitmap->SizeInPixels());
+ if (!srceRect.Intersects(area))
+ {
+ aBitmap->EndDataAccess(ETrue);
+ return;
+ }
+ srceRect.Intersection(area);
+
+ const TPoint destPoint(aDest + iOrigin + srceRect.iTl - aSrceRect.iTl);
+ const TPoint offset(srceRect.iTl - destPoint);
+
+ TRect targetRect(destPoint,srceRect.Size());
+ AddRect(targetRect);
+ if (UserClipRect(targetRect))
+ {
+ aBitmap->EndDataAccess(ETrue);
+ return;
+ }
+
+ SetupDevice();
+ iDevice->DrawingBegin();
+
+ CBitwiseBitmap* srce = ((CFbsBitGcBitmap*)aBitmap)->Address();
+ BG_ASSERT_DEBUG(srce,EBitgdiPanicInvalidBitmap);
+
+ CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aBitmap, targetRect, offset);
+
+ TInt count;
+ const TInt limit = iDefaultRegionPtr->Count();
+ CGraphicsAccelerator* ga = GraphicsAccelerator();
+ TBool opaqueSource = (!IsAlphaChannel(aBitmap->DisplayMode())) && (iDrawMode == EDrawModePEN);
+
+ if(ga && (iShadowMode == CFbsDrawDevice::ENoShadow))
+ {
+ TInt gaOperationResult = KErrUnknown;
+ TAcceleratedBitmapSpec bitmapSpec(const_cast<CFbsBitmap*>(aBitmap));
+ iDevice->DrawingEnd();
+
+ for(count=0;count<limit;count++)
+ {
+
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(targetRect))
+ continue;
+ iClipRect.Intersection(targetRect);
+
+ TRect clippedSrceRect(iClipRect);
+ clippedSrceRect.Move(offset);
+
+ gaOperationResult = ga->Operation(TGopBitBlt(iClipRect.iTl,bitmapSpec,clippedSrceRect));
+ if(gaOperationResult != KErrNone)
+ break;
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+ if(gaOperationResult == KErrNone)
+ goto finish;
+ iDevice->DrawingBegin();
+ }
+
+ for(count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(targetRect))
+ continue;
+ iClipRect.Intersection(targetRect);
+
+ TRect clippedSrceRect(iClipRect);
+ clippedSrceRect.Move(offset);
+
+ if (opaqueSource)
+ iDrawMode = EDrawModeWriteAlpha;// ie write rather then blend
+ DoBitBlt(iClipRect.iTl,srce,aBitmap->DataAddress(),aBitmap->DataStride(),clippedSrceRect);
+ if (opaqueSource)
+ iDrawMode = EDrawModePEN;// set it back how it was
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+
+ iDevice->DrawingEnd();
+finish:
+ if (rasterizer)
+ {
+ rasterizer->EndBitmap(aBitmap->SerialNumber());
+ }
+ aBitmap->EndDataAccess(ETrue);
+ }
+
+
+/** Performs a masked bitmap block transfer.
+
+The function provides a concrete implementation of the pure virtual
+function CBitmapContext::BitBltMasked(). The function
+behaviour is the same as documented in that class.
+
+There are several points to note about this implementation of
+BitBltMasked():
+
+1.For best performance the aMaskBitmap and source aBitmap should
+have the same display mode as the destination device/bitmap.
+
+2.For performance reasons this implementation does not validate
+the contents of the aMaskBitmap. The caller must ensure the mask
+pixels are either black or white otherwise undefined blitting causing
+unpredictable discoloration will result. This is especially true
+for index (where pixel is palette entry) display modes (e.g. EColor16).
+It is up to the caller to decide if they wish to utilise
+CFbsBitmap::IsMonochrome().
+
+3.Alpha blending is used when the display mode of the mask bitmap aMaskBitmap
+is EGray256.
+
+@see CBitmapContext::BitBltMasked() */
+EXPORT_C void CFbsBitGc::BitBltMasked(const TPoint& aDest,
+ const CFbsBitmap* aBitmap,
+ const TRect& aSourceRect,
+ const CFbsBitmap* aMaskBitmap,
+ TBool aInvertMask)
+ {
+ if (aBitmap == NULL || !aBitmap->Handle() ||
+ aMaskBitmap == NULL || !aMaskBitmap->Handle() ||
+ CheckDevice(aSourceRect))
+ return;
+
+ aBitmap->BeginDataAccess();
+ aMaskBitmap->BeginDataAccess();
+
+ TRect srceRect(aSourceRect);
+ const TRect area(aBitmap->SizeInPixels());
+ if (!srceRect.Intersects(area))
+ {
+ aBitmap->EndDataAccess(ETrue);
+ aMaskBitmap->EndDataAccess(ETrue);
+ return;
+ }
+ srceRect.Intersection(area);
+
+ const TPoint destPoint(aDest + iOrigin + srceRect.iTl - aSourceRect.iTl);
+ const TRect destRect(destPoint,srceRect.Size());
+ const TPoint offset(srceRect.iTl - destPoint);
+ const TPoint ditherorigin(iDitherOrigin + aDest);
+
+ TRect clippedDestRect(destRect);
+ AddRect(clippedDestRect);
+ if (UserClipRect(clippedDestRect))
+ {
+ aBitmap->EndDataAccess(ETrue);
+ aMaskBitmap->EndDataAccess(ETrue);
+ return;
+ }
+
+ SetupDevice();
+ iDevice->DrawingBegin();
+
+
+ CBitwiseBitmap* srcebmp = ((CFbsBitGcBitmap*)aBitmap)->Address();
+ CBitwiseBitmap* maskbmp = ((CFbsBitGcBitmap*)aMaskBitmap)->Address();
+ BG_ASSERT_DEBUG(srcebmp,EBitgdiPanicInvalidBitmap);
+ BG_ASSERT_DEBUG(maskbmp,EBitgdiPanicInvalidBitmap);
+
+ const TDisplayMode maskMode = maskbmp->DisplayMode();
+
+ // Do the background fill the lazy way with flicker if any of the following are true:
+ // 1. There is no anti-flicker buffer
+ // 2. The source and mask bitmaps are the same
+ // 3. The brush style is patterned and the mask is an alpha mask
+ // 4. The brush style is not null or solid or patterned
+
+ if (!iDevice->iBitBltMaskedBuffer ||
+ srcebmp == maskbmp ||
+ (maskMode == EGray256 && iBrushStyle == EPatternedBrush) ||
+ iBrushStyle > EPatternedBrush)
+ {
+ iBrushBitmap.BeginDataAccess();
+ CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+ RectFill(destRect);
+ if (brushRasterizer)
+ {
+ brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+ }
+ iBrushBitmap.EndDataAccess(ETrue);
+ }
+
+ const TInt8 shadowMode = iShadowMode;
+ iShadowMode = CFbsDrawDevice::ENoShadow;
+ SetupDevice();
+
+ CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aBitmap, clippedDestRect, offset);
+ CFbsRasterizer* maskRasterizer = NULL;
+ if (srcebmp != maskbmp)
+ {
+ if (aMaskBitmap->SizeInPixels().iWidth >= aBitmap->SizeInPixels().iWidth
+ && aMaskBitmap->SizeInPixels().iHeight >= aBitmap->SizeInPixels().iHeight)
+ {
+ // Mask is not tiled. Pass same region of interest as source bitmap to rasterizer.
+ maskRasterizer = PrepareRasterizerForExtendedBitmap(*aMaskBitmap, clippedDestRect, offset);
+ }
+ else
+ {
+ // Mask is tiled. Do not pass any region of interest to rasterizer.
+ maskRasterizer = PrepareRasterizerForExtendedBitmap(*aMaskBitmap);
+ }
+ }
+
+ TInt count;
+ const TInt limit = iDefaultRegionPtr->Count();
+ CGraphicsAccelerator* ga = GraphicsAccelerator();
+ TBool opaqueSource = (!IsAlphaChannel(aBitmap->DisplayMode())) && (iDrawMode == EDrawModePEN);
+
+ if(ga)
+ {
+ if((iBrushStyle == ENullBrush) && aInvertMask &&
+ (shadowMode == CFbsDrawDevice::ENoShadow))
+ {
+ TInt gaOperationResult = KErrUnknown;
+ TAcceleratedBitmapSpec bitmapSpec(const_cast<CFbsBitmap*>(aBitmap));
+ TAcceleratedBitmapSpec bitmapMaskSpec(const_cast<CFbsBitmap*>(aMaskBitmap));
+ iDevice->DrawingEnd();
+
+ for(count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(clippedDestRect))
+ continue;
+ iClipRect.Intersection(clippedDestRect);
+ TRect clippedSrceRect(iClipRect);
+ clippedSrceRect.Move(offset);
+
+ if(maskbmp->DisplayMode() == EGray256)
+ gaOperationResult = ga->Operation(TGopBitBltAlphaBitmap(iClipRect.iTl,
+ bitmapSpec,
+ clippedSrceRect,
+ bitmapMaskSpec));
+ else
+ gaOperationResult = ga->Operation(TGopBitBltMasked(iClipRect.iTl,
+ bitmapSpec,
+ clippedSrceRect,
+ bitmapMaskSpec));
+
+ if(gaOperationResult != KErrNone)
+ break;
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+ if(gaOperationResult == KErrNone)
+ goto finish;
+ iDevice->DrawingBegin();
+ }
+ }
+
+ for(count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if (!iClipRect.Intersects(clippedDestRect))
+ continue;
+ iClipRect.Intersection(clippedDestRect);
+
+ TRect clippedSrceRect(iClipRect);
+ clippedSrceRect.Move(offset);
+
+ if (opaqueSource)
+ iDrawMode = EDrawModeWriteAlpha;// ie write rather then blend
+ DoBitBltMasked(iClipRect.iTl,
+ srcebmp,
+ aBitmap->DataAddress(),
+ clippedSrceRect,
+ maskbmp,
+ aMaskBitmap->DataAddress(),
+ aInvertMask,
+ ditherorigin,
+ shadowMode);
+ if (opaqueSource)
+ iDrawMode = EDrawModePEN;// set it back how it was
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+
+ iDevice->DrawingEnd();
+finish:
+ if (rasterizer)
+ {
+ rasterizer->EndBitmap(aBitmap->SerialNumber());
+ }
+ if (maskRasterizer)
+ {
+ maskRasterizer->EndBitmap(aMaskBitmap->SerialNumber());
+ }
+ aBitmap->EndDataAccess(ETrue);
+ aMaskBitmap->EndDataAccess(ETrue);
+ iShadowMode = shadowMode;
+ }
+/**
+Does BitBlt operation of source and bitmap per scanline.
+
+*/
+void CFbsBitGc::DoBitBlt(const TPoint& aDest,CFbsDevice* aSrce,const TRect& aSrceRect)
+ {
+ const TInt width = aSrceRect.Width();
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+#ifdef _DEBUG
+ TRect deviceSrcRect;
+ aSrce->iDrawDevice->GetDrawRect(deviceSrcRect);
+ TRect deviceDestRect;
+ drawDevice->GetDrawRect(deviceDestRect);
+#endif
+ BG_ASSERT_DEBUG(aSrceRect.iTl.iX >= deviceSrcRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aSrceRect.iTl.iY >= deviceSrcRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aSrceRect.iBr.iX <= deviceSrcRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aSrceRect.iBr.iY <= deviceSrcRect.iBr.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDest.iX + aSrceRect.Width()) <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
+
+ CFbsDrawDevice* srcDrawDevice = aSrce->iDrawDevice;
+ TAny* interface=NULL;
+ if (iDrawMode==EDrawModeWriteAlpha &&
+ iShadowMode == CFbsDrawDevice::ENoShadow &&
+ (aSrceRect.iTl.iX >= 0) && (aSrceRect.iTl.iY >= 0) &&
+ (aDest.iX >= 0) && (aDest.iY >= 0) &&
+ srcDrawDevice->DisplayMode() == drawDevice->DisplayMode() &&
+ drawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone)
+ {
+ // Conditions in CFbsBitGc allow for optimised blitting.
+ // The draw device supports the optimised blitting function.
+ // Operation may fail regardless due to unacceptable conditions in the draw device.
+ BG_ASSERT_DEBUG(interface!=NULL, EBitgdiPanicNullPointer);
+ MFastBlit2* fastBlit = reinterpret_cast<MFastBlit2*>(interface);
+ if (fastBlit->WriteBitmapBlock(aDest, srcDrawDevice, aSrceRect) == KErrNone)
+ {
+ return;
+ }
+ }
+ MFastBlend* fastBlend=NULL;
+ if (FastBlendInterface(NULL,NULL,fastBlend)==KErrNone)
+ {
+ if (fastBlend->FastBlendBitmap(aDest, srcDrawDevice, aSrceRect, iDrawMode, iShadowMode)==KErrNone)
+ {
+ return;
+ }
+ }
+ //scanLineBuffer is destination scanline buffer.
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+ //dispMode is destination display mode.
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ TInt destY = aDest.iY;
+ //Gets the scanline from the source, into the buffer scanLineDes.
+ //The DoGetScanLine operation is also responsible for converting
+ // the buffer pixel format to destination display format.
+
+ for (TInt row = aSrceRect.iTl.iY; row < aSrceRect.iBr.iY; row++,destY++)
+ {
+ aSrce->DoGetScanLine(scanLineDes,TPoint(aSrceRect.iTl.iX,row),width,dispMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,iDrawMode);
+ }
+ }
+
+/**
+Calculates the position into the scanline for the given x coordinate
+*/
+TUint CFbsBitGc::MemoryOffsetForPixelPitch(TUint aX, TDisplayMode aDisplayMode)
+ {
+ switch (aDisplayMode)
+ {
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ return aX << 2;
+
+ case EColor16M:
+ return aX * 3;
+
+ case EColor4K:
+ case EColor64K:
+ return aX << 1;
+
+ case EGray256:
+ case EColor256:
+ return aX;
+
+ default:
+ BG_PANIC_DEBUG(EBitgdiPanicInvalidDisplayMode);
+ break;
+ }
+ return 0;
+ }
+
+/**
+Gets the scanline pointer with the offset
+*/
+TUint32* CFbsBitGc::GetScanLineOffsetPtr(CBitwiseBitmap* aSrce, TUint32*& aSlptr, TInt aLength, TPoint aPixel,TUint32* aBase, TLineScanningPosition& aLineScanningPosition, TUint aXOffset)
+ {
+ aSrce->GetScanLinePtr(aSlptr, aLength, aPixel, aBase, aLineScanningPosition);
+ return (TUint32*)((TUint8*)aSlptr + aXOffset);
+ }
+
+void CFbsBitGc::DoBitBlt(const TPoint& aDest,
+ CBitwiseBitmap* aSrce,
+ TUint32* aBase,
+ TInt aStride,
+ const TRect& aSrceRect)
+ {
+ // Does multiple bitmap widths for painting rects only
+ const TInt width = aSrceRect.Width();
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+#ifdef _DEBUG
+ TRect deviceDestRect;
+ drawDevice->GetDrawRect(deviceDestRect);
+#endif
+ BG_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDest.iX + aSrceRect.Width()) <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
+
+ TSize srcSize = aSrce->SizeInPixels();
+ if (srcSize.iWidth == 0 || srcSize.iHeight == 0)
+ return; //no point doing anything if asked to draw zero size bitmap
+
+ TAny* interface=NULL;
+ if (iDrawMode==EDrawModeWriteAlpha &&
+ iShadowMode == CFbsDrawDevice::ENoShadow &&
+ aSrceRect.iTl.iX >= 0 &&
+ aSrceRect.iTl.iY >= 0 &&
+ aSrceRect.iBr.iX <= srcSize.iWidth &&
+ aSrceRect.iBr.iY <= srcSize.iHeight &&
+ (aDest.iX >= 0) && (aDest.iY >= 0) &&
+ !aSrce->IsCompressed() &&
+ aSrce->DisplayMode() == drawDevice->DisplayMode() &&
+ drawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone)
+ {
+ // Conditions in CFbsBitGc allow for optimised blitting.
+ // The draw device supports the optimised blitting function.
+ // Operation may fail regardless due to unacceptable conditions in the draw device.
+ BG_ASSERT_DEBUG(interface!=NULL, EBitgdiPanicNullPointer);
+ MFastBlit2* fastBlit = reinterpret_cast<MFastBlit2*>(interface);
+ if (fastBlit && (fastBlit->WriteBitmapBlock(aDest, aBase, aStride, srcSize, aSrceRect) == KErrNone))
+ {
+ return;
+ }
+ }
+ MFastBlend* fastBlend=NULL;
+ if (FastBlendInterface(aSrce,NULL,fastBlend)==KErrNone)
+ {
+ if (fastBlend->FastBlendBitmap(aDest, aBase, aStride, srcSize, aSrceRect, aSrce->DisplayMode(), iDrawMode, iShadowMode)== KErrNone)
+ {
+ return;
+ }
+ }
+
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+
+ const TBool useScanLinePtr = (!iShadowMode) && (dispMode == aSrce->DisplayMode()) && (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8);
+ TUint32* slptr=NULL;
+ TUint offset = 0;
+ TUint32* lastScanLine = NULL;
+ if (useScanLinePtr)
+ lastScanLine = aSrce->ScanLineAddress(aBase,aSrceRect.iBr.iY-1);
+
+ TInt srceWidth = srcSize.iWidth;
+ TInt partlinestart = 0;
+ partlinestart = aSrceRect.iTl.iX % srceWidth;
+ if (partlinestart < 0)
+ partlinestart += srceWidth;
+ const TInt partlinelength = Min(srceWidth - partlinestart,width);
+ TInt destX = aDest.iX;
+ const TInt destXlimit=destX+width;
+
+ // first part line
+ if (partlinestart > 0 && partlinelength > 0)
+ {
+ TPoint srcecoord1(partlinestart,aSrceRect.iTl.iY);
+ TInt desty = aDest.iY;
+ TPoint ditherorigin(iDitherOrigin);
+ ditherorigin.iX += aDest.iX;
+ ditherorigin.iY += desty;
+
+ TLineScanningPosition lineScanPos(aBase);
+
+ if (useScanLinePtr)
+ {
+ offset = MemoryOffsetForPixelPitch(partlinestart, dispMode);
+ if (aSrce->IsCompressed())
+ {
+ while (srcecoord1.iY < aSrceRect.iBr.iY)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, partlinelength, srcecoord1, aBase, lineScanPos, offset);
+ if (srcecoord1.iY==aSrceRect.iTl.iY)
+ {
+ aSrce->SetCompressionBookmark(lineScanPos,aBase,NULL);
+ }
+ drawDevice->WriteLine(aDest.iX,desty,partlinelength, scanLineBuffer,iDrawMode);
+ srcecoord1.iY++,desty++,ditherorigin.iY++;
+ }
+ }
+ else
+ {
+ while (srcecoord1.iY < aSrceRect.iBr.iY)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, partlinelength, srcecoord1, aBase, lineScanPos, offset);
+ do
+ {
+ drawDevice->WriteLine(aDest.iX,desty,partlinelength, scanLineBuffer,iDrawMode);
+ scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
+ srcecoord1.iY++,desty++,ditherorigin.iY++;
+ }
+ while ((srcecoord1.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
+ }
+ }
+ }
+ else
+ {
+ for (; srcecoord1.iY < aSrceRect.iBr.iY; srcecoord1.iY++,desty++,ditherorigin.iY++)
+ {
+ aSrce->GetScanLine(scanLineDes,srcecoord1,partlinelength,ETrue,
+ ditherorigin,dispMode,aBase, lineScanPos);
+ if (srcecoord1.iY==aSrceRect.iTl.iY)
+ {
+ aSrce->SetCompressionBookmark(lineScanPos,aBase,NULL);
+ }
+ drawDevice->WriteLine(aDest.iX,desty,partlinelength, scanLineBuffer,iDrawMode);
+ }
+ }
+
+ destX+=partlinelength;
+ }
+
+ // multiple complete lines - columns
+ TInt numcolumns = 0;
+ numcolumns = (destXlimit - destX) / srceWidth;
+ if (numcolumns > 0)
+ {
+ TPoint srcecoord2(0,aSrceRect.iTl.iY);
+ TInt desty = aDest.iY;
+ TPoint ditherorigin(iDitherOrigin);
+ ditherorigin.iX += destX;
+ ditherorigin.iY += desty;
+
+ TLineScanningPosition lineScanPos(aBase);
+
+ if (useScanLinePtr)
+ {
+ if (aSrce->IsCompressed())
+ {
+ while (srcecoord2.iY < aSrceRect.iBr.iY)
+ {
+ TPoint coord(srcecoord2);
+ aSrce->GetScanLinePtr(slptr, srceWidth, coord,aBase, lineScanPos);
+ if (srcecoord2.iY==aSrceRect.iTl.iY)
+ {
+ aSrce->SetCompressionBookmark(lineScanPos, aBase,NULL);
+ }
+ TInt tempdestX = destX;
+ for (TInt count = 0; count < numcolumns; count++,tempdestX+=srceWidth)
+ {
+ drawDevice->WriteLine(tempdestX,desty,srceWidth, slptr,iDrawMode);
+ ditherorigin.iX += srceWidth;
+ }
+ srcecoord2.iY++,desty++,ditherorigin.iY++;
+ }
+ }
+ else
+ {
+ while (srcecoord2.iY < aSrceRect.iBr.iY)
+ {
+ TPoint coord(srcecoord2);
+ aSrce->GetScanLinePtr(slptr, srceWidth, coord,aBase, lineScanPos);
+ do
+ {
+ TInt tempdestX = destX;
+ for (TInt count = 0; count < numcolumns; count++,tempdestX+=srceWidth)
+ {
+ drawDevice->WriteLine(tempdestX,desty,srceWidth, slptr,iDrawMode);
+ ditherorigin.iX += srceWidth;
+ }
+ slptr = (TUint32*)((TUint8*)slptr + aStride);
+ srcecoord2.iY++,desty++,ditherorigin.iY++;
+ }
+ while ((srcecoord2.iY < aSrceRect.iBr.iY) && (slptr < lastScanLine));
+ }
+ }
+ }
+ else
+ {
+ for (; srcecoord2.iY < aSrceRect.iBr.iY; srcecoord2.iY++,desty++,ditherorigin.iY++)
+ {
+ TInt tempdestX = destX;
+ TPoint coord(srcecoord2);
+ aSrce->GetScanLinePtr(slptr, srceWidth, coord,aBase, lineScanPos);
+ if (srcecoord2.iY==aSrceRect.iTl.iY)
+ {
+ aSrce->SetCompressionBookmark(lineScanPos, aBase,NULL);
+ }
+ for (TInt count = 0; count < numcolumns; count++,tempdestX+=srceWidth)
+ {
+ aSrce->GetScanLine(slptr, scanLineDes,coord,srceWidth,ETrue,
+ ditherorigin,dispMode);
+ drawDevice->WriteLine(tempdestX,desty,srceWidth, scanLineBuffer,iDrawMode);
+ ditherorigin.iX += srceWidth;
+ }
+ }
+ }
+
+ destX += numcolumns * srceWidth;
+ }
+
+ // final part line
+ if (destX < destXlimit)
+ {
+ const TInt restofline = destXlimit - destX;
+ TPoint srcecoord3(0,aSrceRect.iTl.iY);
+ TInt desty = aDest.iY;
+ TPoint ditherorigin(iDitherOrigin);
+ ditherorigin.iX += destX;
+ ditherorigin.iY += desty;
+
+ TLineScanningPosition lineScanPos(aBase);
+
+ if (useScanLinePtr)
+ {
+ offset = 0;
+ if (aSrce->IsCompressed())
+ {
+ while (srcecoord3.iY < aSrceRect.iBr.iY)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, srceWidth, srcecoord3, aBase, lineScanPos, offset);
+ if (srcecoord3.iY==aSrceRect.iTl.iY)
+ {
+ aSrce->SetCompressionBookmark(lineScanPos,aBase,NULL);
+ }
+ drawDevice->WriteLine(destX,desty,restofline,scanLineBuffer,iDrawMode);
+ srcecoord3.iY++,desty++,ditherorigin.iY++;
+ }
+ }
+ else
+ {
+ while (srcecoord3.iY < aSrceRect.iBr.iY)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, srceWidth, srcecoord3, aBase, lineScanPos, offset);
+ do
+ {
+ drawDevice->WriteLine(destX,desty,restofline,scanLineBuffer,iDrawMode);
+ scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
+ srcecoord3.iY++,desty++,ditherorigin.iY++;
+ }
+ while ((srcecoord3.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
+ }
+ }
+ }
+ else
+ {
+ for (; srcecoord3.iY < aSrceRect.iBr.iY; srcecoord3.iY++,desty++,ditherorigin.iY++)
+ {
+ aSrce->GetScanLine(scanLineDes,srcecoord3,srceWidth,ETrue,
+ ditherorigin,dispMode,aBase,lineScanPos);
+ if (srcecoord3.iY==aSrceRect.iTl.iY)
+ {
+ aSrce->SetCompressionBookmark(lineScanPos, aBase,NULL);
+ }
+ drawDevice->WriteLine(destX,desty,restofline,scanLineBuffer,iDrawMode);
+ }
+ }
+ }
+ }
+
+void CFbsBitGc::DoBitBltMasked(const TPoint& aDest,
+ CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,
+ const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,
+ TUint32* aMaskBase,
+ TBool aInvertMask,
+ const TPoint& aDitherOrigin,
+ TInt aShadowMode)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+#ifdef _DEBUG
+ TRect deviceDestRect;
+ drawDevice->GetDrawRect(deviceDestRect);
+#endif
+ BG_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDest.iX + aSourceRect.Width()) <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDest.iY + aSourceRect.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
+
+ MFastBlend* fastBlend=NULL;
+ if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
+ {
+ if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
+ aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aSourceRect.iTl, aInvertMask,
+ iDrawMode, aShadowMode)==KErrNone)
+ {
+ return;
+ }
+ }
+
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ if (aMaskBitmap->DisplayMode() == EGray256)
+ {
+ DoBitBltAlpha(aDest,aSourceBitmap,aSourceBase,aSourceRect,
+ aMaskBitmap,aMaskBase,aSourceRect.iTl,aShadowMode, EFalse);
+ }
+ // if screen driver is 16MAP we avoid logical operator pen modes by using DoBitBltAlpha() for blitting
+ else if (dispMode == EColor16MAP)
+ {
+ DoBitBltAlpha(aDest,aSourceBitmap,aSourceBase,aSourceRect,
+ aMaskBitmap,aMaskBase,aSourceRect.iTl,aShadowMode, aInvertMask);
+ }
+
+ else if (aSourceBitmap == aMaskBitmap)
+ {
+ const TInt width = aSourceRect.Width();
+ TPoint ditherOrigin(aDitherOrigin + aDest);
+ const TDrawMode drawMode = aInvertMask ? EDrawModeAND : EDrawModeOR;
+ TPoint srcePoint(aSourceRect.iTl);
+ TInt destY = aDest.iY;
+
+ TLineScanningPosition lineScanPos(aSourceBase);
+
+ const TBool useScanLinePtr = (!aShadowMode) && (dispMode == aSourceBitmap->DisplayMode() && (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8));
+ if (useScanLinePtr)
+ {
+ TUint32* scanLineBuffer = NULL;
+ TUint32* slptr=NULL;
+ TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode);
+
+ if (aSourceBitmap->IsCompressed())
+ {
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+ }
+ }
+ else
+ {
+ TUint stride = aSourceBitmap->DataStride();
+ TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
+
+ while (srcePoint.iY < aSourceRect.iBr.iY)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+ do
+ {
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+ scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + stride);
+ destY++,srcePoint.iY++,ditherOrigin.iY++;
+ }
+ while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
+ }
+ }
+ }
+ else
+ {
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,
+ ETrue,ditherOrigin,dispMode,aSourceBase,lineScanPos);
+
+ if (aShadowMode)
+ {
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+ drawDevice->ShadowBuffer(width,scanLineBuffer);
+ drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ }
+
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+ }
+ }
+ }
+ else
+ {
+ if (iDevice->iBitBltMaskedBuffer)
+ {
+ if (iBrushStyle == ESolidBrush)
+ DoBitBltMaskedNonFlickerSolid(aDest,aSourceBitmap,aSourceBase,aSourceRect,
+ aMaskBitmap,aMaskBase,aInvertMask,aDitherOrigin,
+ aShadowMode);
+ else if (iBrushStyle == EPatternedBrush)
+ DoBitBltMaskedNonFlickerPatterned(aDest,aSourceBitmap,aSourceBase,aSourceRect,
+ aMaskBitmap,aMaskBase,aInvertMask,
+ aDitherOrigin,aShadowMode);
+ else
+ DoBitBltMaskedNonFlicker(aDest,aSourceBitmap,aSourceBase,aSourceRect,
+ aMaskBitmap,aMaskBase,aInvertMask,aDitherOrigin,
+ aShadowMode);
+ }
+ else
+ DoBitBltMaskedFlicker(aDest,aSourceBitmap,aSourceBase,aSourceRect,aMaskBitmap,
+ aMaskBase,aInvertMask,aDitherOrigin,aShadowMode);
+ }
+ }
+
+void CFbsBitGc::DoBitBltMaskedFlicker(const TPoint& aDest,
+ CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,
+ const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,
+ TUint32* aMaskBase,
+ TBool aInvertMask,
+ const TPoint& aDitherOrigin,
+ TInt aShadowMode)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+ const TInt width = aSourceRect.Width();
+ TInt destY = aDest.iY;
+ TPoint srcePoint(aSourceRect.iTl);
+
+ TLineScanningPosition lineScanPos(aSourceBase);
+ TLineScanningPosition lineScanPosMask(aMaskBase);
+
+ const TDisplayMode srcFormat = aSourceBitmap->DisplayMode();
+ const TDisplayMode maskFormat = aMaskBitmap->DisplayMode();
+
+ if (aMaskBitmap->IsCompressed())
+ {
+ HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4);
+ if (!hBuf)
+ return; // Out of memory so do not draw anything
+ lineScanPosMask.iScanLineBuffer = hBuf;
+ }
+
+ TAny* interface=NULL;
+ if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) &&
+ maskFormat == EGray2 &&
+ !aShadowMode &&
+ aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
+ aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
+ drawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
+ {
+ // Parameters allow optimised code path
+ TInt length = width;
+ TUint32* srcPtr=NULL;
+ TUint32* maskPtr=NULL;
+ MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+
+ while (srcePoint.iY < aSourceRect.iBr.iY)
+ {
+ aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos);
+ aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask);
+
+ fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask);
+
+ destY++;
+ ++srcePoint.iY;
+ }
+ return;
+ }
+
+ TPoint ditherOrigin(aDitherOrigin + aDest);
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ const TDrawMode drawMode = aInvertMask ? EDrawModeAND : EDrawModeANDNOT;
+
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+
+ TLineScanningPosition lineScanPos2(aSourceBase);
+
+ //scanline modifications required if using shadows, different modes, bits per pixel less than 8
+ if ((!aShadowMode) && (dispMode == aSourceBitmap->DisplayMode()) && (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8))
+ {
+ TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode);
+ TUint32* slptr=NULL;
+ //mask scanline modifications required for EInvertPen, different screen modes
+ if ((drawMode != EDrawModeANDNOT) && (dispMode == aMaskBitmap->DisplayMode()))
+ {
+ TUint32* scanLineBufferMask = NULL;
+ //stride jumping not possible with compressed bitmaps
+ if (aSourceBitmap->IsCompressed() || aMaskBitmap->IsCompressed())
+ {
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
+ scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
+ }
+ }
+ else
+ {
+ TUint strideSrc = aSourceBitmap->DataStride();
+ TUint strideMask = aMaskBitmap->DataStride();
+ TUint32* lastScanLineSrc = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
+ TUint32* lastScanLineMask = aMaskBitmap->ScanLineAddress(aMaskBase,aSourceRect.iBr.iY-1);
+
+ while (srcePoint.iY < aSourceRect.iBr.iY)
+ {
+ scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+ scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
+
+ do
+ {
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
+ destY++,srcePoint.iY++,ditherOrigin.iY++;
+ }
+ while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLineSrc) && (scanLineBufferMask < lastScanLineMask)
+ && ((scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + strideSrc))>(TUint32*)0)
+ && ((scanLineBufferMask = (TUint32*)((TUint8*)scanLineBufferMask + strideMask))>(TUint32*)0)
+ );
+ }
+ }
+ }
+ else
+ {
+ TUint32* scanLineBufferPtr = NULL;
+ //stride jumping not possible with compressed bitmaps
+ if (aSourceBitmap->IsCompressed())
+ {
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
+ aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode, aMaskBase, lineScanPosMask);
+ ::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
+ }
+ }
+ else
+ {
+ TUint stride = aSourceBitmap->DataStride();
+ TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
+ while (srcePoint.iY < aSourceRect.iBr.iY)
+ {
+ scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
+ do
+ {
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
+ aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,aMaskBase, lineScanPosMask);
+ ::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
+ destY++,srcePoint.iY++,ditherOrigin.iY++;
+ }
+ while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBufferPtr < lastScanLine)
+ && ((scanLineBufferPtr = (TUint32*)((TUint8*)scanLineBufferPtr + stride))>(TUint32*)0));
+ }
+ }
+ }
+ }
+ else
+ {
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,
+ dispMode,aSourceBase,lineScanPos);
+
+ if (aShadowMode)
+ {
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+ drawDevice->ShadowBuffer(width,scanLineBuffer);
+ drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ }
+
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
+
+ aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,
+ aMaskBase, lineScanPosMask);
+ ::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask,
+ aMaskBase, dispMode);
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
+
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,dispMode,
+ aSourceBase,lineScanPos2);
+
+ if(aShadowMode)
+ {
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+ drawDevice->ShadowBuffer(width,scanLineBuffer);
+ drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ }
+
+ drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
+ }
+ }
+ }
+
+void CFbsBitGc::DoBitBltMaskedNonFlicker(const TPoint& aDest,
+ CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,
+ const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,
+ TUint32* aMaskBase,
+ TBool aInvertMask,
+ const TPoint& aDitherOrigin,
+ TInt aShadowMode)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+ const TInt width = aSourceRect.Width();
+ TInt destY = aDest.iY;
+ TPoint srcePoint(aSourceRect.iTl);
+
+ TLineScanningPosition lineScanPos(aSourceBase);
+ TLineScanningPosition lineScanPosMask(aMaskBase);
+
+ const TDisplayMode srcFormat = aSourceBitmap->DisplayMode();
+ const TDisplayMode maskFormat = aMaskBitmap->DisplayMode();
+
+ if (aMaskBitmap->IsCompressed())
+ {
+ HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4);
+ if (!hBuf)
+ return; // Out of memory so do not draw anything
+ lineScanPosMask.iScanLineBuffer = hBuf;
+ }
+
+ TAny* interface=NULL;
+ if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) &&
+ maskFormat == EGray2 &&
+ !aShadowMode &&
+ aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
+ aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
+ drawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
+ {
+ // Parameters allow optimised code path
+ TInt length = width;
+ TUint32* srcPtr=NULL;
+ TUint32* maskPtr=NULL;
+ MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+
+ while (srcePoint.iY < aSourceRect.iBr.iY)
+ {
+ aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos);
+ aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask);
+
+ fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask);
+
+ destY++;
+ ++srcePoint.iY;
+ }
+
+ return;
+ }
+
+ TPoint ditherOrigin(aDitherOrigin + aDest);
+
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+
+ TUint32* bitBltBuffer = (TUint32*)iDevice->iBitBltMaskedBuffer;
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ const TInt bufferBytes = CFbsBitmap::ScanLineLength(width, dispMode);
+ TUint32* scanLineCopy = (TUint32*) new TUint8[bufferBytes];
+
+ TLineScanningPosition lineScanPos2(aSourceBase);
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ drawDevice->ReadLine(aDest.iX,destY,width,bitBltBuffer,dispMode);
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,dispMode,
+ aSourceBase,lineScanPos);
+
+ if (scanLineCopy)
+ {
+ Mem::Copy(scanLineCopy,scanLineBuffer,bufferBytes);
+ }
+
+ if (aShadowMode)
+ {
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+ drawDevice->ShadowBuffer(width,scanLineBuffer);
+ drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ }
+
+ XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+
+ aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,
+ aMaskBase,lineScanPosMask);
+ ::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask,
+ aMaskBase, dispMode);
+
+ if (!aInvertMask)
+ InvertBuffer(scanLineBuffer,bufferBytes);
+ AndBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+
+ // Slow call when memory low?
+ TUint32* scanLine;
+ if (!scanLineCopy)
+ {
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,
+ dispMode,aSourceBase,lineScanPos2);
+ scanLine = scanLineBuffer;
+ }
+ else
+ scanLine = scanLineCopy;
+
+ if(aShadowMode)
+ {
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+ drawDevice->ShadowBuffer(width,scanLine);
+ drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ }
+
+ XorBuffers(bitBltBuffer,scanLine,bufferBytes);
+
+ drawDevice->WriteLine(aDest.iX,destY,width,bitBltBuffer,iDrawMode);
+ }
+ if (scanLineCopy)
+ {
+ delete[] scanLineCopy;
+ }
+ }
+
+void CFbsBitGc::DoBitBltMaskedNonFlickerSolid(const TPoint& aDest,
+ CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,
+ const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,
+ TUint32* aMaskBase,
+ TBool aInvertMask,
+ const TPoint& aDitherOrigin,
+ TInt aShadowMode)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+ const TInt width = aSourceRect.Width();
+ TPoint ditherOrigin(aDitherOrigin + aDest);
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ TInt destY = aDest.iY;
+ TPoint srcePoint(aSourceRect.iTl);
+
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+
+ TUint32* bitBltBuffer = (TUint32*)iDevice->iBitBltMaskedBuffer;
+ TUint32* backgroundBuffer = (TUint32*)(iDevice->iBitBltMaskedBuffer + scanLineBytes);
+ const TInt bufferBytes = CFbsBitmap::ScanLineLength(width, dispMode);
+
+ drawDevice->WriteRgbMulti(aDest.iX,aDest.iY,width,1,iBrushColor,iDrawMode);
+ drawDevice->ReadLine(aDest.iX,destY,width,backgroundBuffer,dispMode);
+
+ TLineScanningPosition lineScanPos(aSourceBase);
+ TLineScanningPosition lineScanPos2(aSourceBase);
+ TLineScanningPosition lineScanPosMask(aMaskBase);
+
+ for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
+ {
+ Mem::Copy(bitBltBuffer,backgroundBuffer,bufferBytes);
+
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,dispMode,
+ aSourceBase,lineScanPos);
+ XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+
+ aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,
+ aMaskBase,lineScanPosMask);
+ ::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask,
+ aMaskBase, dispMode);
+
+ if (!aInvertMask)
+ InvertBuffer(scanLineBuffer,bufferBytes);
+ AndBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+ aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,
+ dispMode,aSourceBase,lineScanPos2);
+
+ XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+
+ if(aShadowMode)
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+
+ drawDevice->WriteLine(aDest.iX,destY,width,bitBltBuffer,iDrawMode);
+
+ if(aShadowMode)
+ drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ }
+ }
+
+void CFbsBitGc::DoBitBltMaskedNonFlickerPatterned(const TPoint& aDest,
+ CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,
+ const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,
+ TUint32* aMaskBase,
+ TBool aInvertMask,
+ const TPoint& aDitherOrigin,
+ TInt aShadowMode)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+
+ iBrushBitmap.BeginDataAccess();
+ CBitwiseBitmap* brushBitmap = iBrushBitmap.Address();
+ BG_ASSERT_ALWAYS(iBrushUsed, EBitgdiPanicInvalidBitmap);
+ BG_ASSERT_ALWAYS(brushBitmap != NULL, EBitgdiPanicInvalidBitmap);
+
+ CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+ TUint32* brushData = iBrushBitmap.DataAddress();
+ TPoint brushSourcePoint(aDest - iBrushOrigin - iOrigin);
+ const TSize brushSize(iBrushBitmap.SizeInPixels());
+ if (brushSourcePoint.iX < 0 || brushSourcePoint.iX >= brushSize.iWidth)
+ brushSourcePoint.iX %= brushSize.iWidth;
+ if (brushSourcePoint.iX < 0)
+ brushSourcePoint.iX += brushSize.iWidth;
+
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
+
+ TUint32* bitBltBuffer = (TUint32*)iDevice->iBitBltMaskedBuffer;
+ TPtr8 bitBltDes(iDevice->iBitBltMaskedBuffer, scanLineBytes, scanLineBytes);
+
+ TInt widthRemaining = aSourceRect.Width();
+ TPoint sourcePoint(aSourceRect.iTl);
+ TInt destX = aDest.iX;
+
+ TInt width = Min(widthRemaining,brushSize.iWidth);
+
+ if (brushSourcePoint.iX + widthRemaining > brushSize.iWidth)
+ width = brushSize.iWidth - brushSourcePoint.iX;
+
+ while (widthRemaining > 0)
+ {
+ TInt destY = aDest.iY;
+ sourcePoint.iY = aSourceRect.iTl.iY;
+ brushSourcePoint.iY = aDest.iY - iBrushOrigin.iY - iOrigin.iY;
+ TPoint ditherOrigin(aDitherOrigin + TPoint(destX,aDest.iY));
+ const TInt bufferBytes = CFbsBitmap::ScanLineLength(width, dispMode);
+
+ TLineScanningPosition lineScanPosBrush(brushData);
+ TLineScanningPosition lineScanPosMask(aMaskBase);
+ TLineScanningPosition lineScanPosSrc(aSourceBase);
+ TLineScanningPosition lineScanPosSrc2(aSourceBase);
+
+ for ( ;sourcePoint.iY < aSourceRect.iBr.iY;
+ destY++,sourcePoint.iY++,ditherOrigin.iY++,brushSourcePoint.iY++)
+ {
+ brushBitmap->GetScanLine(bitBltDes,brushSourcePoint,width,ETrue,ditherOrigin,
+ dispMode,brushData,lineScanPosBrush);
+ aSourceBitmap->GetScanLine(scanLineDes,sourcePoint,width,ETrue,ditherOrigin,
+ dispMode,aSourceBase,lineScanPosSrc);
+ XorBuffers(bitBltBuffer,scanLineBuffer,scanLineBytes);
+
+ aMaskBitmap->GetScanLine(scanLineDes,sourcePoint,width,EFalse,ditherOrigin,
+ dispMode,aMaskBase,lineScanPosMask);
+ ::TileScanLine(scanLineDes, width, sourcePoint, aMaskBitmap, lineScanPosMask,
+ aMaskBase, dispMode);
+
+ if (!aInvertMask)
+ InvertBuffer(scanLineBuffer,bufferBytes);
+ AndBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+
+ aSourceBitmap->GetScanLine(scanLineDes,sourcePoint,width,ETrue,ditherOrigin,
+ dispMode,aSourceBase,lineScanPosSrc2);
+ XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
+
+ drawDevice->WriteLine(destX,destY,width,bitBltBuffer,iDrawMode);
+ }
+
+ widthRemaining -= width;
+ sourcePoint.iX += width;
+ brushSourcePoint.iX += width;
+ destX += width;
+
+ width = Min(widthRemaining,brushSize.iWidth);
+ }
+ if (brushRasterizer)
+ {
+ brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+ }
+ iBrushBitmap.EndDataAccess(ETrue);
+ }
+
+void CFbsBitGc::DoBitBltAlpha(const TPoint& aDest,CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,TUint32* aMaskBase,
+ const TPoint& aAlphaPoint,TInt aShadowMode, TBool aInvertMask)
+ {
+ MFastBlend* fastBlend=NULL;
+ if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
+ {
+ if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
+ aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aAlphaPoint, aInvertMask,
+ iDrawMode, aShadowMode)==KErrNone)
+ {
+ return;
+ }
+ }
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+ const TPoint KZeroPoint(0,0);
+ const TInt KScanLineLength = 256;
+ const TInt KRgbSize = 4;
+
+ TUint8 srceRgbBuffer[KScanLineLength * KRgbSize];
+ TUint8 maskBuffer[KScanLineLength];
+ TUint8* srceRgbBufferPtr(srceRgbBuffer);
+
+ TPtr8 srceRgbDes(srceRgbBuffer,KScanLineLength * KRgbSize,KScanLineLength * KRgbSize);
+ TPtr8 maskDes(maskBuffer,KScanLineLength,KScanLineLength);
+
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+
+ const TSize sourceSize = aSourceBitmap->SizeInPixels();
+ // Convert negative or large offsets into sensible positive ones.
+ TPoint alphaOffset(aAlphaPoint.iX % sourceSize.iWidth, aAlphaPoint.iY % sourceSize.iHeight);
+ if ( alphaOffset.iX < 0 )
+ alphaOffset.iX += sourceSize.iWidth;
+ if ( alphaOffset.iY < 0 )
+ alphaOffset.iY += sourceSize.iHeight;
+
+ TInt srceY = aSourceRect.iTl.iY;
+ TInt destY = aDest.iY;
+ TInt alphaY = alphaOffset.iY;
+
+ TLineScanningPosition lineScanPosSrc(aSourceBase);
+ TLineScanningPosition lineScanPosMask(aMaskBase);
+
+ TDisplayMode sourceMode = aSourceBitmap->DisplayMode();
+
+ if (aMaskBitmap->IsCompressed())
+ {
+ HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
+ if (!hBuf)
+ {
+ return; // Out of memory so do not draw anything
+ }
+ lineScanPosMask.iScanLineBuffer = hBuf;
+ }
+
+ TAny* interface=NULL;
+ if ( (sourceMode == EColor16MU || sourceMode == EColor64K) &&
+ aMaskBitmap->DisplayMode() == EGray256 && // ensure a monochrome mask isn't passed in as an alpha channel
+ aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
+ aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
+ drawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
+ {
+ TInt length = aSourceRect.Width();
+ const TInt srceX = aSourceRect.iTl.iX;
+ const TInt alphaX = alphaOffset.iX;
+ const TInt destX = aDest.iX;
+ MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+
+ while (srceY < aSourceRect.iBr.iY)
+ {
+ TUint32* srcPtr;
+ TUint32* maskPtr;
+ TPoint srcPoint(srceX, srceY);
+ TPoint maskPoint(alphaX, alphaY);
+
+ aSourceBitmap->GetScanLinePtr(srcPtr, length, srcPoint, aSourceBase, lineScanPosSrc);
+ aMaskBitmap->GetScanLinePtr(maskPtr, length, maskPoint, aMaskBase, lineScanPosMask);
+
+ fastBlit->WriteAlphaLineEx(destX,destY,length,srceX,srcPtr,sourceMode,alphaX,maskPtr,MAlphaBlend::EShdwBefore);
+
+ srceY++;
+ destY++;
+ alphaY++;
+ }
+ return;
+ }
+
+ const TBool useScanLinePtr = ((!aShadowMode) && (EColor16MA == aSourceBitmap->DisplayMode()));
+ TUint32* slptr=NULL;
+ TUint offset = 0;
+ TDisplayMode srcMode = ERgb;
+
+ while (srceY < aSourceRect.iBr.iY)
+ {
+ TInt srceX = aSourceRect.iTl.iX;
+ TInt destX = aDest.iX;
+ TInt alphaX = alphaOffset.iX;
+
+ while (srceX < aSourceRect.iBr.iX)
+ {
+ TPoint srcePoint(srceX,srceY);
+ TPoint alphaPoint(alphaX,alphaY);
+ const TInt width = Min(KScanLineLength,aSourceRect.iBr.iX - srceX);
+
+ if (useScanLinePtr)
+ {
+ offset = MemoryOffsetForPixelPitch(srceX, EColor16MU);
+ srceRgbBufferPtr = (TUint8*)GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPosSrc, offset);
+ }
+ else
+ {
+ aSourceBitmap->GetScanLine(srceRgbDes,srcePoint,width,EFalse,KZeroPoint,
+ srcMode,aSourceBase,lineScanPosSrc);
+ }
+
+ aMaskBitmap->GetScanLine(maskDes,alphaPoint,width,EFalse,KZeroPoint,
+ EGray256,aMaskBase,lineScanPosMask);
+ ::TileScanLine(maskDes, width, alphaPoint, aMaskBitmap, lineScanPosMask,
+ aMaskBase, EGray256);
+ // aInvertMask is not used for alpha channels (EGray256 mask)
+ if (aInvertMask && aMaskBitmap->DisplayMode() != EGray256)
+ {
+ for (TInt i = 0; i < width; ++i)
+ maskBuffer[i] = ~maskBuffer[i];
+ }
+ drawDevice->WriteRgbAlphaLine(destX,destY,width,srceRgbBufferPtr,maskBuffer,iDrawMode);
+
+ srceX += KScanLineLength;
+ destX += KScanLineLength;
+ alphaX += KScanLineLength;
+ }
+
+ srceY++;
+ destY++;
+ alphaY++;
+ }
+ }
+
+/**
+The method performs an alpha blending of the source data - aSrcBmp1 and aSrcBmp2, using
+the data from aAlphaBmp as an alpha blending factor.
+@internalComponent
+@see CFbsBitGc::AlphaBlendBitmaps.
+*/
+void CFbsBitGc::DoBitBltAlpha(const TPoint& aDestPt,
+ const CBitwiseBitmap* aSrcBmp1,
+ TUint32* aSrcBmpDataAddr1,
+ const CBitwiseBitmap* aSrcBmp2,
+ TUint32* aSrcBmpDataAddr2,
+ const CBitwiseBitmap* aAlphaBmp,
+ TUint32* aAlphaBmpDataAddr,
+ const TRect& aSrcRect1,
+ const TPoint& aSrcPt2,
+ const TPoint& aAlphaPt,
+ TInt aShadowMode)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+#ifdef _DEBUG
+ TRect deviceDestRect;
+ drawDevice->GetDrawRect(deviceDestRect);
+#endif
+ //Check the destination point.
+ BG_ASSERT_DEBUG(aDestPt.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(aDestPt.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDestPt.iX + aSrcRect1.Width()) <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG((aDestPt.iY + aSrcRect1.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
+
+ const TPoint KZeroPoint(0,0);
+ const TInt KScanLineLength = 256;//128 is not enough to fill buffer for 16MA and 16MU display modes
+ const TInt KRgbSize = 4;
+
+ TUint8 srceRgbBuffer1[KScanLineLength * KRgbSize];
+ TUint8 srceBuffer2[KScanLineLength * KRgbSize];
+ TUint8 alphaBuffer[KScanLineLength];
+
+ TPtr8 srceRgbDes1(srceRgbBuffer1,KScanLineLength * KRgbSize,KScanLineLength * KRgbSize);
+ TPtr8 srceDes2(srceBuffer2,KScanLineLength * KRgbSize,KScanLineLength * KRgbSize);
+ TPtr8 alphaDes(alphaBuffer,KScanLineLength,KScanLineLength);
+
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
+
+ TInt srceY1 = aSrcRect1.iTl.iY;
+ TInt srceY2 = aSrcPt2.iY;
+ TInt alphaY = aAlphaPt.iY;
+ TInt destY = aDestPt.iY;
+
+ TLineScanningPosition lineScanPosSrc1(aSrcBmpDataAddr1);
+ TLineScanningPosition lineScanPosSrc2(aSrcBmpDataAddr2);
+ TLineScanningPosition lineScanPosAlpha(aAlphaBmpDataAddr);
+
+ while (srceY1 < aSrcRect1.iBr.iY)
+ {
+ TInt srceX1 = aSrcRect1.iTl.iX;
+ TInt srceX2 = aSrcPt2.iX;
+ TInt alphaX = aAlphaPt.iX;
+ TInt destX = aDestPt.iX;
+
+ while (srceX1 < aSrcRect1.iBr.iX)
+ {
+ TPoint srcePoint1(srceX1,srceY1);
+ TPoint srcePoint2(srceX2,srceY2);
+ TPoint alphaPoint(alphaX,alphaY);
+ const TInt width = Min(KScanLineLength,aSrcRect1.iBr.iX - srceX1);
+
+ aSrcBmp1->GetScanLine(srceRgbDes1,srcePoint1,width,EFalse,KZeroPoint,EColor16MU,
+ aSrcBmpDataAddr1,lineScanPosSrc1);
+ aSrcBmp2->GetScanLine(srceDes2,srcePoint2,width,EFalse,KZeroPoint,dispMode,
+ aSrcBmpDataAddr2,lineScanPosSrc2);
+ aAlphaBmp->GetScanLine(alphaDes,alphaPoint,width,EFalse,KZeroPoint,EGray256,
+ aAlphaBmpDataAddr,lineScanPosAlpha);
+ ::TileScanLine(alphaDes, width, alphaPoint, aAlphaBmp, lineScanPosAlpha, aAlphaBmpDataAddr, EGray256);
+
+ drawDevice->WriteRgbAlphaLine(destX,
+ destY,
+ width,
+ srceRgbBuffer1,
+ srceBuffer2,
+ alphaBuffer,
+ iDrawMode);
+
+ srceX1 += KScanLineLength;
+ srceX2 += KScanLineLength;
+ alphaX += KScanLineLength;
+ destX += KScanLineLength;
+ }
+
+ srceY1++;
+ srceY2++;
+ alphaY++;
+ destY++;
+ }
+ }
+
+/**
+The method performs an alpha blending of the source data - aSrcBmp1 and aSrcBmp2, using
+the data from aAlphaBmp as an alpha blending factor.
+The formula used for that, is:
+(C1 * A + C2 * (255 - A)) / 255, where:
+- C1 - a pixel from aSrcBmp1;
+- C2 - a pixel from aSrcBmp2;
+- A - a pixel from aAlphaBmp;
+The content of source and alpha bitmap is preserved.
+The calculated alpha blended pixels are written to the destination - the screen or a bitmap.
+@publishedAll
+@released
+@param aDestPt Position in the target the result should be drawn to.
+@param aSrcBmp1 A pointer to the source bitmap 1.
+@param aSrcBmp2 A pointer to the source bitmap 2.
+@param aAlphaBmp A pointer to the bitmap used as an alpha blending factor.
+@param aSrcRect1 A part of bitmap 1 that should be used as a source for the alpha blending.
+@param aSrcPt2 Position of the first pixel in bitmap 2 that should be used as a source
+ for the alpha blending. The size of the area is the same as the
+ bitmap 1 area - aSrcRect1 parameter.
+@param aAlphaPt Position of the first pixel in the alpha bitmap that should be used as a source
+ for the alpha blending. The size of the area is the same as the
+ bitmap 1 area - aSrcRect1 parameter.
+@pre !aSrcRect1.IsEmpty()
+@pre aSrcBmp1 != NULL
+@pre aSrcBmp1->Handle() != NULL
+@pre aSrcBmp2 != NULL
+@pre aSrcBmp2->Handle() != NULL
+@pre aAlphaBmp != NULL
+@pre aAlphaBmp->Handle() != NULL
+@pre aAlphaBmp->DisplayMode() <= EGray256
+@return KErrNone If the call is successful, KErrArgument otherwise.
+*/
+EXPORT_C TInt CFbsBitGc::AlphaBlendBitmaps(const TPoint& aDestPt,
+ const CFbsBitmap* aSrcBmp1,
+ const CFbsBitmap* aSrcBmp2,
+ const TRect& aSrcRect1,
+ const TPoint& aSrcPt2,
+ const CFbsBitmap* aAlphaBmp,
+ const TPoint& aAlphaPt)
+ {
+ //Check the bitmap pointers and handles. Check the CFbsDevice instance -
+ //it shouldn't be NULL - that means - CFbsBitGc instance (this pointer)
+ //should be created either using CFbsDevice::CreateContext() or CFbsBitGc::Activate() -
+ //before the method was called.
+ if(!aSrcBmp1 || !aSrcBmp1->Handle() || !aSrcBmp2 || !aSrcBmp2->Handle() ||
+ !aAlphaBmp || !aAlphaBmp->Handle() || CheckDevice(aSrcRect1))
+ {
+ return KErrArgument;
+ }
+
+ aSrcBmp1->BeginDataAccess();
+ aSrcBmp2->BeginDataAccess();
+ aAlphaBmp->BeginDataAccess();
+
+ //Check display mode of the alpha bitmap. Bitmaps which display mode is greater than
+ //EGray256 can't be used as alpha bitmaps.
+ if(aAlphaBmp->DisplayMode() > EGray256)
+ {
+ aSrcBmp1->EndDataAccess(ETrue);
+ aSrcBmp2->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ //Check source rect 1. Bitmap 1 must contain the whole source rect 1.
+ TRect srcRect1(aSrcRect1);
+ TRect area1(aSrcBmp1->SizeInPixels());
+ srcRect1.Intersection(area1);
+ if(srcRect1 != aSrcRect1)
+ {
+ aSrcBmp1->EndDataAccess(ETrue);
+ aSrcBmp2->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ //Create and check source rect 2. Bitmap 2 must contain the whole source rect 2.
+ TRect srcRect2(TSize(aSrcRect1.Width(), aSrcRect1.Height()));
+ srcRect2.Move(aSrcPt2);
+ TRect srcRect2t(srcRect2);
+ TRect area2(aSrcBmp2->SizeInPixels());
+ srcRect2.Intersection(area2);
+ if(srcRect2 != srcRect2t)
+ {
+ aSrcBmp1->EndDataAccess(ETrue);
+ aSrcBmp2->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ //Calculate the destination rect
+ TPoint destPt(aDestPt + iOrigin);
+ TRect destRect(destPt, srcRect1.Size());
+ TPoint offset(srcRect1.iTl - destPt);
+ TPoint offset2(srcRect2.iTl - destPt);
+ TRect clippedDestRect(destRect);
+ AddRect(clippedDestRect);
+ if(UserClipRect(clippedDestRect))
+ {
+ aSrcBmp1->EndDataAccess(ETrue);
+ aSrcBmp2->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ //Save current shadow mode
+ TInt8 shadowMode = iShadowMode;
+ iShadowMode = CFbsDrawDevice::ENoShadow;
+ //Setup the device and prevent the bitmaps from being cleaned away by client code.
+ //Drawing begins.
+ SetupDevice();
+ iDevice->DrawingBegin();
+ CBitwiseBitmap* srcBmp1 = ((CFbsBitGcBitmap*)aSrcBmp1)->Address();
+ CBitwiseBitmap* srcBmp2 = ((CFbsBitGcBitmap*)aSrcBmp2)->Address();
+ CBitwiseBitmap* alphaBmp = ((CFbsBitGcBitmap*)aAlphaBmp)->Address();
+ BG_ASSERT_DEBUG(srcBmp1, EBitgdiPanicInvalidBitmap);
+ BG_ASSERT_DEBUG(srcBmp2, EBitgdiPanicInvalidBitmap);
+ BG_ASSERT_DEBUG(alphaBmp, EBitgdiPanicInvalidBitmap);
+
+ TUint32* srcDataAddr1 = aSrcBmp1->DataAddress();
+ TUint32* srcDataAddr2 = aSrcBmp2->DataAddress();
+ TUint32* alphaDataAddr = aAlphaBmp->DataAddress();
+
+ CFbsRasterizer* rasterizer1 = PrepareRasterizerForExtendedBitmap(*aSrcBmp1, clippedDestRect, offset);
+ CFbsRasterizer* rasterizer2 = PrepareRasterizerForExtendedBitmap(*aSrcBmp2, clippedDestRect, offset2);
+ CFbsRasterizer* alphaRasterizer;
+ if (aAlphaPt.iX >= 0 && aAlphaPt.iY >= 0
+ && aAlphaPt.iX + aSrcRect1.Width() <= aAlphaBmp->SizeInPixels().iWidth
+ && aAlphaPt.iY + aSrcRect1.Height() <= aAlphaBmp->SizeInPixels().iHeight)
+ {
+ // Alpha blending bitmap is not tiled. Pass same region of interest as source bitmaps to rasterizer.
+ alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp, clippedDestRect, aAlphaPt - destPt);
+ }
+ else
+ {
+ // Alpha blending bitmap is tiled. Do not pass any region of interest to rasterizer.
+ alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp);
+ }
+
+ //For each region - find the clipping rect and draw
+ TInt limit = iDefaultRegionPtr->Count();
+ CGraphicsAccelerator* ga = GraphicsAccelerator();
+ // Code for Graphics Accelerated Drawing
+ if(ga && (shadowMode == CFbsDrawDevice::ENoShadow))
+ {
+ TInt gaOperationResult = KErrUnknown;
+ TAcceleratedBitmapSpec srcBmp1Spec(const_cast<CFbsBitmap*>(aSrcBmp1));
+ TAcceleratedBitmapSpec srcBmp2Spec(const_cast<CFbsBitmap*>(aSrcBmp2));
+ TAcceleratedBitmapSpec alphaBmpSpec(const_cast<CFbsBitmap*>(aAlphaBmp));
+ iDevice->DrawingEnd();
+
+ for(TInt count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(clippedDestRect))
+ {
+ continue;
+ }
+ //clippedDestRect was constructed from destRect. destRect was constructed from srcRect1.
+ iClipRect.Intersection(clippedDestRect);
+ TRect clippedSrcRect(iClipRect);
+ clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect1 now.
+ TPoint shift(clippedSrcRect.iTl - srcRect1.iTl);
+ BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
+ BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
+
+ gaOperationResult = ga->Operation(TGopAlphaBlendTwoBitmaps(iClipRect.iTl,srcBmp1Spec,srcBmp2Spec,clippedSrcRect,aSrcPt2 + shift,alphaBmpSpec,aAlphaPt + shift));
+ if(gaOperationResult != KErrNone)
+ break;
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+ if(gaOperationResult == KErrNone)
+ goto finish;
+ iDevice->DrawingBegin();
+ }
+
+ // Code for non- Graphics Accelerated Drawing
+ for(TInt count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(clippedDestRect))
+ {
+ continue;
+ }
+ //clippedDestRect was constructed from destRect. destRect was constructed from srcRect1.
+ iClipRect.Intersection(clippedDestRect);
+ TRect clippedSrcRect(iClipRect);
+ clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect1 now.
+ TPoint shift(clippedSrcRect.iTl - srcRect1.iTl);
+ BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
+ BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
+
+ TDrawMode drawMode = iDrawMode;
+ iDrawMode = EDrawModeWriteAlpha; // this is the only mode currently supported
+ DoBitBltAlpha(iClipRect.iTl,
+ srcBmp1,
+ srcDataAddr1,
+ srcBmp2,
+ srcDataAddr2,
+ alphaBmp,
+ alphaDataAddr,
+ clippedSrcRect,
+ aSrcPt2 + shift,
+ aAlphaPt + shift,
+ shadowMode);
+ iDrawMode = drawMode; // restore the previous draw mode
+
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+
+ //Drawig ends. Restore the previous shadow mode
+ iDevice->DrawingEnd();
+finish:
+ if (rasterizer1)
+ {
+ rasterizer1->EndBitmap(aSrcBmp1->SerialNumber());
+ }
+ if (rasterizer2)
+ {
+ rasterizer2->EndBitmap(aSrcBmp2->SerialNumber());
+ }
+ if (alphaRasterizer)
+ {
+ alphaRasterizer->EndBitmap(aAlphaBmp->SerialNumber());
+ }
+ aSrcBmp1->EndDataAccess(ETrue);
+ aSrcBmp2->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ iShadowMode = shadowMode;
+
+ return KErrNone;
+ }
+
+/**
+The method performs an alpha blending of the source data - aSrcBmp - with the existing image, using
+the data from aAlphaBmp as an alpha blending factor.
+The formula used for that, is:
+(C * A + D * (255 - A)) / 255, where:
+- C - a pixel from aSrcBmp;
+- D - a pixel from the destination;
+- A - a pixel from aAlphaBmp;
+The content of source and alpha bitmap is preserved.
+The calculated alpha blended pixels are written to the destination - the screen or a bitmap.
+@publishedAll
+@released
+@param aDestPt Position in the target the result should be drawn to.
+@param aSrcBmp A pointer to the source bitmap.
+@param aAlphaBmp A pointer to the bitmap used as an alpha blending factor.
+@param aSrcRect A part of aSrcBmp that should be used as a source for the alpha blending.
+ DISCLAIMER: if aSrcRect is bigger (width and/or height) the behaviour is undefined
+@param aAlphaPt Position of the first pixel in the alpha bitmap that should be used as a source
+ for the alpha blending. The size of the area is
+ the same as the aSrcRect parameter (read DISCLAIMER above).
+@pre !aSrcRect.IsEmpty()
+@pre aSrcBmp != NULL
+@pre aSrcBmp->Handle() != NULL
+@pre aAlphaBmp != NULL
+@pre aAlphaBmp->Handle() != NULL
+@pre aAlphaBmp->DisplayMode() <= EGray256
+@return KErrNone If the call is successfull, KErrArgument otherwise.
+*/
+EXPORT_C TInt CFbsBitGc::AlphaBlendBitmaps(const TPoint& aDestPt,
+ const CFbsBitmap* aSrcBmp,
+ const TRect& aSrcRect,
+ const CFbsBitmap* aAlphaBmp,
+ const TPoint& aAlphaPt)
+ {
+ //Check the bitmap pointers and handles. Check the CFbsDevice instance -
+ //it shouldn't be NULL - that means - CFbsBitGc instance (this pointer)
+ //should be created either using CFbsDevice::CreateContext() or CFbsBitGc::Activate() -
+ //before the method was called.
+ if(!aSrcBmp || !aSrcBmp->Handle() ||
+ !aAlphaBmp || !aAlphaBmp->Handle() || CheckDevice(aSrcRect))
+ {
+ return KErrArgument;
+ }
+
+ aSrcBmp->BeginDataAccess();
+ aAlphaBmp->BeginDataAccess();
+
+ //Check display mode of the alpha bitmap. Bitmaps which display mode is greater than
+ //EGray256 can't be used as alpha bitmaps.
+ if(aAlphaBmp->DisplayMode() > EGray256)
+ {
+ aSrcBmp->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ //Taking the actual part of the source rect contained in the Bitmap.
+ TRect srcRect(aSrcRect);
+ TRect area(aSrcBmp->SizeInPixels());
+ if(!srcRect.Intersects(area))
+ {
+ aSrcBmp->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ srcRect.Intersection(area);
+ //Calculate the destination rect
+ TPoint destPt(aDestPt + iOrigin);
+ TRect destRect(destPt, srcRect.Size());
+ TPoint offset(srcRect.iTl - destPt);
+ TRect clippedDestRect(destRect);
+ AddRect(clippedDestRect);
+ if(UserClipRect(clippedDestRect))
+ {
+ aSrcBmp->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ return KErrArgument;
+ }
+ //Save current shadow mode
+ TInt8 shadowMode = iShadowMode;
+ iShadowMode = CFbsDrawDevice::ENoShadow;
+ //Setup the device and prevent the bitmaps from being cleaned away by client code.
+ //Drawing begins.
+ SetupDevice();
+ iDevice->DrawingBegin();
+
+ CBitwiseBitmap* srcBmp = ((CFbsBitGcBitmap*)aSrcBmp)->Address();
+ CBitwiseBitmap* alphaBmp = ((CFbsBitGcBitmap*)aAlphaBmp)->Address();
+ BG_ASSERT_DEBUG(srcBmp, EBitgdiPanicInvalidBitmap);
+ BG_ASSERT_DEBUG(alphaBmp, EBitgdiPanicInvalidBitmap);
+ TUint32* srcDataAddr = aSrcBmp->DataAddress();
+ TUint32* alphaDataAddr = aAlphaBmp->DataAddress();
+
+ CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aSrcBmp, clippedDestRect, offset);
+ CFbsRasterizer* alphaRasterizer;
+ if (aAlphaPt.iX >= 0 && aAlphaPt.iY >= 0
+ && aAlphaPt.iX + srcRect.Width() <= aAlphaBmp->SizeInPixels().iWidth
+ && aAlphaPt.iY + srcRect.Height() <= aAlphaBmp->SizeInPixels().iHeight)
+ {
+ // Alpha blending bitmap is not tiled. Pass same region of interest as source bitmap to rasterizer.
+ alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp, clippedDestRect, aAlphaPt - destPt);
+ }
+ else
+ {
+ // Alpha blending bitmap is tiled. Do not pass any region of interest to rasterizer.
+ alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp);
+ }
+
+ //For each region - find the clipping rect and draw
+ TInt limit = iDefaultRegionPtr->Count();
+ CGraphicsAccelerator* ga = GraphicsAccelerator();
+ // Code for Graphics Accelerated Drawing
+ if(ga && (shadowMode == CFbsDrawDevice::ENoShadow))
+ {
+ TInt gaOperationResult = KErrUnknown;
+ TAcceleratedBitmapSpec srcBmpSpec(const_cast<CFbsBitmap*>(aSrcBmp));
+ TAcceleratedBitmapSpec alphaBmpSpec(const_cast<CFbsBitmap*>(aAlphaBmp));
+ iDevice->DrawingEnd();
+
+ for(TInt count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(clippedDestRect))
+ {
+ continue;
+ }
+ //clippedDestRect was constructed from destRect. destRect was constructed from srcRect.
+ iClipRect.Intersection(clippedDestRect);
+ TRect clippedSrcRect(iClipRect);
+ clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect now.
+ TPoint shift(clippedSrcRect.iTl - srcRect.iTl);
+ BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
+ BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
+
+ gaOperationResult = ga->Operation(TGopAlphaBlendOneBitmap(iClipRect.iTl,srcBmpSpec,clippedSrcRect,alphaBmpSpec,aAlphaPt + shift));
+ if(gaOperationResult != KErrNone)
+ break;
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+ if(gaOperationResult == KErrNone)
+ goto finish;
+ iDevice->DrawingBegin();
+ }
+
+ // Code for non- Graphics Accelerated Drawing
+ for(TInt count=0;count<limit;count++)
+ {
+ iClipRect=(*iDefaultRegionPtr)[count];
+ if(!iClipRect.Intersects(clippedDestRect))
+ {
+ continue;
+ }
+ //clippedDestRect was constructed from destRect. destRect was constructed from srcRect.
+ iClipRect.Intersection(clippedDestRect);
+ TRect clippedSrcRect(iClipRect);
+ clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect now.
+ TPoint shift(clippedSrcRect.iTl - srcRect.iTl);
+ BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
+ BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
+ DoBitBltAlpha(iClipRect.iTl,
+ srcBmp,
+ srcDataAddr,
+ clippedSrcRect,
+ alphaBmp,
+ alphaDataAddr,
+ aAlphaPt + shift,
+ shadowMode,
+ EFalse);
+ iDevice->iDrawDevice->UpdateRegion(iClipRect);
+ }
+
+ // Drawing ends. Restore the previous shadow mode.
+ iDevice->DrawingEnd();
+finish:
+ if (rasterizer)
+ {
+ rasterizer->EndBitmap(aSrcBmp->SerialNumber());
+ }
+ if (alphaRasterizer)
+ {
+ alphaRasterizer->EndBitmap(aAlphaBmp->SerialNumber());
+ }
+ aSrcBmp->EndDataAccess(ETrue);
+ aAlphaBmp->EndDataAccess(ETrue);
+ iShadowMode = shadowMode;
+
+ return KErrNone;
+ }
+
+GLDEF_C void XorBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes)
+ {
+ // Round up to nearest word boundary
+ const TUint32* const destBufferLimit = aDestBuffer + ((aNumBytes + sizeof(TUint32) - 1) / sizeof(TUint32));
+
+ while (aDestBuffer < destBufferLimit)
+ *aDestBuffer++ ^= *aSrceBuffer++;
+ }
+
+GLDEF_C void AndBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes)
+ {
+ // Round up to nearest word boundary
+ const TUint32* const destBufferLimit = aDestBuffer + ((aNumBytes + sizeof(TUint32) - 1) / sizeof(TUint32));
+
+ while (aDestBuffer < destBufferLimit)
+ *aDestBuffer++ &= *aSrceBuffer++;
+ }
+
+GLDEF_C void InvertBuffer(TUint32* aDestBuffer,TInt aNumBytes)
+ {
+ // Round up to nearest word boundary
+ const TUint32* const destBufferLimit = aDestBuffer + ((aNumBytes + sizeof(TUint32) - 1) / sizeof(TUint32));
+
+ while (aDestBuffer < destBufferLimit)
+ {
+ *aDestBuffer = *aDestBuffer ^ KMaxTUint32;
+ ++aDestBuffer;
+ }
+ }
+
+GLDEF_C void InvertBuffer(TUint8* aDestBuffer,TInt aNumBytes)
+ {
+ const TUint8* const destBufferLimit = aDestBuffer + aNumBytes;
+
+ while (aDestBuffer < destBufferLimit)
+ {
+ *aDestBuffer = static_cast<TUint8>(*aDestBuffer ^ KMaxTUint8);
+ ++aDestBuffer;
+ }
+ }
+
+/**
+The method tiles the scan line if its length in pixels is less than
+aLengthInPixels argument.
+@internalComponent
+@param aScanLine A pointer to the scan line buffer.
+@param aLengthInPixels The scan line buffer should have that count of pixels after the method call.
+@param aSrcPt Position of the first pixel in aMaskBitmap that should be used as a source
+ for the pixels in scan line buffer.
+@param aMaskBitmap Any additional pixels for the scan line buffer will be taken from here.
+@param aScanLinePos This argument is used for some internal optimizations. It should not be
+ modified by the caller.
+@param aMaskBase The base address of aMaskBitmap data.
+@param aDisplayMode Any additional pixels should be taken from aMaskBitmap using aDisplayMode
+ as an argument for GetScanLine() call.
+*/
+LOCAL_C void TileScanLine(TPtr8& aScanLine,
+ TInt aLengthInPixels,
+ const TPoint& aSrcPt,
+ const CBitwiseBitmap* aMaskBitmap,
+ TLineScanningPosition& aScanLinePos,
+ TUint32* aMaskBase,
+ TDisplayMode aDisplayMode
+ )
+ {
+ TInt lengthInBytes = CFbsBitmap::ScanLineLength(aLengthInPixels, aDisplayMode);
+ BG_ASSERT_DEBUG(lengthInBytes <= aScanLine.MaxLength(), EBitgdiPanicInvalidArg);
+ TInt scanLineLength = aScanLine.Length();
+ if(scanLineLength < lengthInBytes && aSrcPt.iX > 0)
+ {
+ //If, for example, src bmp is 100 pixels width, mask bmp is 20 pixels width and src
+ //rect is (10, 0, 100, 1) -> We will read only pixels 10..19 from the first scan line
+ //of the mask bmp. We have to have 90 mask bmp pixels.
+ //So we have to make a second mask bmp read startig from pixel 0 - 10 pixels length.
+ TInt maxLen = Min(aScanLine.MaxLength() - scanLineLength, aSrcPt.iX);
+ TPtr8 maskDes2(const_cast <TUint8*> (aScanLine.Ptr()) + scanLineLength, maxLen, maxLen);
+ TPoint srcPt(0, aSrcPt.iY);
+ TPoint zeroPt(0, 0);
+ aMaskBitmap->GetScanLine(maskDes2, srcPt, maxLen, EFalse, zeroPt, aDisplayMode, aMaskBase, aScanLinePos);
+ aScanLine.SetLength(scanLineLength + maskDes2.Length());
+ scanLineLength = aScanLine.Length();
+ }
+ if(scanLineLength >= lengthInBytes || scanLineLength == 0)
+ {
+ return;
+ }
+ //If we still don't have enough mask bmp pixels - we have to tile the scan line
+ TInt repeatCnt = lengthInBytes / scanLineLength - 1;
+ TInt bytesLeft = lengthInBytes % scanLineLength;
+ const TUint8* src = aScanLine.Ptr();
+ TUint8* dest = const_cast <TUint8*> (src) + scanLineLength;
+ for(;repeatCnt>0;dest+=scanLineLength,repeatCnt--)
+ {
+ Mem::Copy(dest, src, scanLineLength);
+ }
+ if(bytesLeft)
+ {
+ Mem::Copy(dest, src, bytesLeft);
+ }
+ aScanLine.SetLength(lengthInBytes);
+ }
+
+/**
+The method draws a masked rectangular section of the source
+bitmap and does a compress/stretch to fit a given destination
+rectangle.
+@internalComponent
+*/
+void CFbsBitGc::DoDrawBitmapMasked(const TRect& aDestRect,
+ CBitwiseBitmap* aSourceBitmap,
+ TUint32* aSourceBase,
+ const TRect& aSourceRect,
+ CBitwiseBitmap* aMaskBitmap,
+ TUint32* aMaskBase,
+ TBool aInvertMask, const TPoint& aDitherOrigin)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+#ifdef _DEBUG
+ TRect deviceDestRect;
+ drawDevice->GetDrawRect(deviceDestRect);
+ BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
+#endif
+
+ // The clipped version of the destination rectangle
+ TRect clippedDestRect(aDestRect);
+ clippedDestRect.Intersection(iClipRect);
+
+ // If the source rectangle and the destination rectangle are same,
+ // no stretch/compress operation required, just do BitBltMasked
+ if (aDestRect.Size() == aSourceRect.Size())
+ {
+ if (!clippedDestRect.IsEmpty())
+ {
+ const TPoint destPoint(clippedDestRect.iTl);
+ clippedDestRect.Move(aSourceRect.iTl - aDestRect.iTl);
+ DoBitBltMasked(destPoint,
+ aSourceBitmap,
+ aSourceBase,
+ clippedDestRect,
+ aMaskBitmap,
+ aMaskBase,
+ aInvertMask,
+ aDitherOrigin,
+ CFbsDrawDevice::ENoShadow);
+ }
+ return;
+ }
+ MFastBlend* fastBlend=NULL;
+ if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
+ {
+ if (fastBlend->FastBlendBitmapMaskedScaled(iClipRect, aDestRect, aSourceRect, aSourceBase, aSourceBitmap->DataStride(),
+ aSourceBitmap->DisplayMode(),aSourceBitmap->SizeInPixels(),
+ aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aInvertMask,
+ iDrawMode, iShadowMode)==KErrNone)
+ {
+ return;
+ }
+ }
+
+ TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
+ const TInt scanLineBytes = drawDevice->ScanLineBytes();
+ TPtr8 scanLineDes(REINTERPRET_CAST(TUint8*,scanLineBuffer),scanLineBytes,scanLineBytes);
+
+ // This constant is associated to the value used in TestGdi::DoDrawBitmapMaskedL, case #24.
+ // If this value is changed, then that one must be updated as well otherwise the test will no longer be valid.
+ const TInt KScanLineLength = 256;
+ const TInt KRgbSize = 4;
+ TUint8 maskBuffer[KScanLineLength];
+
+ TUint8 sourceBuffer[KScanLineLength*KRgbSize];
+ TPtr8 sourceDes(sourceBuffer,KScanLineLength*KRgbSize,KScanLineLength*KRgbSize);
+
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
+ TDrawMode drawMode = aInvertMask ? EDrawModeAND : EDrawModeANDNOT;
+ // If the source bitmap and the mask bitmap are same, draw the source bitmap either
+ // with EDrawModeAND or EDrawModeOR based on aInvertMask parameter.
+ if (aSourceBitmap == aMaskBitmap)
+ {
+ drawMode = aInvertMask ? EDrawModeAND : EDrawModeOR;
+ }
+
+ TLinearDDA xLine;
+ TInt bitmapXStart = 0;
+ xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
+ TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
+ xLine.JumpToYCoord2(bitmapXStart,clippedDestRect.iTl.iX);
+
+ TLinearDDA yLine;
+ TPoint yCoord(aSourceRect.iTl.iY,aDestRect.iTl.iY);
+ yLine.Construct(yCoord,TPoint(aSourceRect.iBr.iY,aDestRect.iBr.iY),TLinearDDA::ELeft);
+ TInt dummy;
+ yLine.JumpToYCoord2(dummy,clippedDestRect.iTl.iY);
+ yCoord.SetXY(dummy,clippedDestRect.iTl.iY);
+
+ TPoint ditherOrigin(aDitherOrigin + clippedDestRect.iTl);
+ const TInt srceWidth = aSourceRect.Width();
+ const TInt destWidth = aDestRect.Width();
+ const TInt clipWidth = clippedDestRect.Width();
+ const TInt clipStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
+ const TInt sourceBmpWidth = aSourceBitmap->SizeInPixels().iWidth;
+ const TInt maskWidth = aMaskBitmap->SizeInPixels().iWidth;
+ const TInt maskHeight = aMaskBitmap->SizeInPixels().iHeight;
+
+ TLineScanningPosition lineScanPos(aSourceBase);
+ TLineScanningPosition lineScanPos2(aSourceBase);
+ TLineScanningPosition lineScanPosMask(aMaskBase);
+
+ HBufC8* alphaBuffer = NULL;
+ TPtr8 alphaBufferDes(NULL, 0);
+ const TDisplayMode maskDisplayMode = aMaskBitmap->DisplayMode();
+
+ // Mask inversion is not supported if the original source mask format is EGray256.
+ // Note that this is only used for pre-multiplied alpha targets.
+ TUint8 maskInverter = (aInvertMask && maskDisplayMode != EGray256) ? 0xFF : 0x00;
+
+ if (aSourceBitmap != aMaskBitmap)
+ {
+ // Get buffer to be used to convert non-EGray256 masks to EGray256 when display mode is EColor16MAP
+ // or to tile the mask when the mask width is smaller than the source bitmap width.
+ if (maskDisplayMode != EGray256 && (dispMode == EColor16MAP || maskWidth < sourceBmpWidth))
+ {
+ alphaBuffer = CFbsBitmap::GetExtraBuffer(CFbsBitmap::ScanLineLength(maskWidth, EGray256));
+ if (!alphaBuffer)
+ {
+ return; // Out of memory so do not draw anything
+ }
+ alphaBufferDes.Set(alphaBuffer->Des());
+ }
+
+ // Get buffer to be used for decompressing compressed masks when mask is EGray256
+ if (maskDisplayMode == EGray256 && aMaskBitmap->IsCompressed())
+ {
+ HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
+ if (!hBuf)
+ {
+ return; // Out of memory so do not draw anything
+ }
+ lineScanPosMask.iScanLineBuffer = hBuf;
+ }
+ }
+
+ while (yCoord.iY < clippedDestRect.iBr.iY)
+ {
+ // Draw only the source bitmap, if the source bitmap and the mask bitmap are same.
+ // else draw both the bitmaps
+ if (aSourceBitmap == aMaskBitmap)
+ {
+ aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
+ clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+ srceWidth,ditherOrigin,dispMode,aSourceBase,lineScanPos);
+ if (yCoord.iY==clippedDestRect.iTl.iY)
+ aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
+ drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
+ }
+ else if ((maskDisplayMode == EGray256) || (dispMode == EColor16MAP))
+ {
+ // Stretch the source bitmap and the mask bitmap for KScanLineLength as stretch length
+ // then do alpha blending for this length. If the length is more then KScanLineLength
+ // repeat it till you stretch complete destination length.
+ const TPoint startPt(bitmapXStart,yCoord.iX);
+ TInt clipWidthPart = clippedDestRect.Width();
+ TBool loopLast = ETrue;
+ if(clipWidthPart > KScanLineLength)
+ {
+ clipWidthPart = KScanLineLength;
+ loopLast = EFalse;
+ }
+ TInt clipIncStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
+ TInt startClip=clippedDestRect.iTl.iX;
+ TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
+ xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
+ TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
+ xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
+ TPoint srcPixel(bitmapXStart % maskWidth,yCoord.iX % maskHeight);
+ TInt spaceLeft = 0;
+ TRgb maskRgbValue;
+ TUint32* maskScanLinePtr32 = NULL;
+ TPoint currentYValue(0,srcPixel.iY);
+ aMaskBitmap->GetScanLinePtr(maskScanLinePtr32, currentYValue, maskWidth, aMaskBase, lineScanPosMask);
+ // To implement non EGray256 mask support with EColor16MAP display mode, we convert
+ // the mask to EGray256.
+ if (maskDisplayMode != EGray256) // Convert scan-line to EGray256 and set maskScanLinePtr32 to the conversion.
+ {
+ aMaskBitmap->GetScanLine(maskScanLinePtr32, alphaBufferDes, currentYValue, maskWidth, EFalse, TPoint(0, 0), EGray256);
+ maskScanLinePtr32 = (TUint32*)alphaBuffer->Ptr();
+ }
+ TUint8* maskScanLinePtr = reinterpret_cast<TUint8*>(maskScanLinePtr32);
+
+ // Outer loop over all KScanLineLengths
+ FOREVER
+ {
+ aSourceBitmap->StretchScanLine(sourceDes,startPt,clipIncStrch,clipWidthPart,destWidth,
+ aSourceRect.iTl.iX,srceWidth,ditherOrigin,EColor16MU,aSourceBase,lineScanPos);
+ // Inner loop to tile the mask if necessary
+ spaceLeft = clipWidthPart;
+
+ do {
+ srcPixel.iX = sourceDestXCoords.iX % maskWidth;
+
+ // Invert the mask using the inversion mask.
+ maskBuffer[(sourceDestXCoords.iY-clippedDestRect.iTl.iX)%KScanLineLength]=
+ maskInverter^maskScanLinePtr[srcPixel.iX];
+ xLine.NextStep(sourceDestXCoords);
+ } while (--spaceLeft>0);
+
+ if (yCoord.iY == clippedDestRect.iTl.iY && startClip == clippedDestRect.iTl.iX)
+ {
+ aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
+ aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
+ }
+ drawDevice->WriteRgbAlphaLine(startClip,yCoord.iY,clipWidthPart,sourceBuffer,maskBuffer,iDrawMode);
+ if (loopLast)
+ {
+ break;
+ }
+ startClip+=KScanLineLength;
+ if (clippedDestRect.iBr.iX - startClip <= KScanLineLength)
+ {
+ loopLast = ETrue;
+ clipWidthPart = clippedDestRect.iBr.iX - startClip;
+ }
+ clipIncStrch += KScanLineLength;
+ }
+ }
+ else
+ {
+ aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
+ clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+ srceWidth,ditherOrigin,dispMode,aSourceBase,lineScanPos2);
+ drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,EDrawModeXOR);
+
+ TInt maskXStart = bitmapXStart % maskWidth;
+ if(maskWidth < sourceBmpWidth)
+ {
+ TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
+ xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
+ TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
+ xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
+ TPoint srcPixel(maskXStart,yCoord.iX % maskHeight);
+ TInt spaceLeft = clipWidth;
+ TPoint prevSourceDestXCoords(-1,-1);
+ TRgb maskRgbValue;
+ aMaskBitmap->GetScanLine(alphaBufferDes, TPoint(0,srcPixel.iY), maskWidth, EFalse, TPoint(0, 0), EGray256, aMaskBase, lineScanPosMask);
+
+ // Loop to tile the mask
+ do {
+ if (sourceDestXCoords.iY != prevSourceDestXCoords.iY)
+ {
+ if (sourceDestXCoords.iX != prevSourceDestXCoords.iX)
+ {
+ srcPixel.iX = sourceDestXCoords.iX % maskWidth;
+ if (srcPixel.iX < 0)
+ srcPixel.iX += maskWidth;
+ maskRgbValue = TRgb::Gray256((*alphaBuffer)[srcPixel.iX]);
+ }
+ drawDevice->WriteRgb(sourceDestXCoords.iY,yCoord.iY,maskRgbValue,drawMode);
+ spaceLeft--;
+ }
+ prevSourceDestXCoords = sourceDestXCoords;
+ xLine.SingleStep(sourceDestXCoords);
+ } while (spaceLeft > 0);
+ }
+ else
+ {
+ // No need to tile the mask
+ aMaskBitmap->StretchScanLine(scanLineDes,TPoint(maskXStart,yCoord.iX % maskHeight),
+ clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+ srceWidth,ditherOrigin,dispMode,aMaskBase,lineScanPosMask);
+ drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
+ // Redo stretching of the aSourceBitmap scanline
+ aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
+ clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
+ srceWidth,ditherOrigin,dispMode,aSourceBase,lineScanPos2);
+ }
+
+ if (yCoord.iY==clippedDestRect.iTl.iY)
+ {
+ aSourceBitmap->SetCompressionBookmark(lineScanPos2,aSourceBase,NULL);
+ aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
+ }
+
+ drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,EDrawModeXOR);
+ }
+ yLine.NextStep(yCoord);
+ ditherOrigin.iY++;
+ }
+ }
+
+EXPORT_C TInt CFbsBitGc::AlphaBlendBitmaps(const TPoint& aDestPt,
+ const CWsBitmap* aSrcBmp,
+ const TRect& aSrcRect,
+ const CWsBitmap* aAlphaBmp,
+ const TPoint& aAlphaPt)
+ {
+ return AlphaBlendBitmaps(aDestPt, REINTERPRET_CAST(const CFbsBitmap*, aSrcBmp), aSrcRect, REINTERPRET_CAST(const CFbsBitmap*, aAlphaBmp), aAlphaPt);
+ }
+
+TInt CFbsBitGc::FastBlendInterface(const CBitwiseBitmap* aSource, const CBitwiseBitmap* aMask, MFastBlend*& aFastBlend) const
+ {
+#if defined(__ALLOW_FAST_BLEND_DISABLE__)
+ if (iFastBlendDisabled)
+ return(KErrNotSupported);
+#endif
+ if ((aSource && aSource->IsCompressed()) || (aMask && aMask->IsCompressed()))
+ return(KErrNotSupported);
+ TAny* interface=NULL;
+ TInt ret=iDevice->iDrawDevice->GetInterface(KFastBlendInterfaceID, interface);
+ aFastBlend=(MFastBlend*)interface;
+ return(ret);
+ }
+
+/*
+Returns the pixel-format to be used when extracting a scan-line through CBitwiseBitmap::GetScanLine(), CBitwiseBitmap::GetVerticalScanLine(), and CBitwiseBitmap::StretchScanLine() for consumption by CFbsDrawDevice::WriteLine() and associated methods.
+
+@see CBitwiseBitmap::GetScanLine()
+@see CBitwiseBitmap::GetVerticalScanLine()
+@see CBitwiseBitmap::StretchScanLine()
+@see CFbsDrawDevice::WriteLine()
+@internalComponent
+*/
+TDisplayMode CFbsBitGc::ScanLineBufferDisplayMode(CFbsDrawDevice* aDrawDevice)
+ {
+ return iDrawMode == EDrawModeWriteAlpha ? aDrawDevice->DisplayMode() : aDrawDevice->ScanLineDisplayMode();
+ }
+
+/** Prepares the rasterizer to retrieve scan lines from a bitmap if it is an
+extended bitmap. No region of interest is passed to the rasterizer.
+This function calls CFbsRasterizer::BeginBitmap() with the appropriate
+parameters. When finished retrieving scan lines from the extended bitmap,
+CFbsRasterizer::EndBitmap() must be called.
+@param aBitmap The bitmap to retrieve scan lines from.
+@return A pointer to the rasterizer owned by this thread's FBServ session.
+@return NULL if the rasterizer is not present or aBitmap is not an extended bitmap.
+@see CFbsRasterizer
+@internalComponent
+*/
+CFbsRasterizer* CFbsBitGc::PrepareRasterizerForExtendedBitmap(const CFbsBitmap& aBitmap)
+ {
+ CFbsRasterizer* rasterizer = NULL;
+ CFbsRasterizer::TBitmapDesc desc;
+ desc.iDataType = aBitmap.ExtendedBitmapType();
+ if (desc.iDataType != KNullUid)
+ {
+ rasterizer = CFbsBitmap::Rasterizer();
+ if (rasterizer)
+ {
+ desc.iSizeInPixels = aBitmap.SizeInPixels();
+ desc.iDispMode = aBitmap.DisplayMode();
+ desc.iData = aBitmap.DataAddress();
+ desc.iDataSize = aBitmap.DataSize();
+ rasterizer->BeginBitmap(aBitmap.SerialNumber(), desc, NULL);
+ }
+ }
+ return rasterizer;
+ }
+
+/** Prepares the rasterizer to retrieve scan lines from a bitmap if it is an
+extended bitmap. The region of interest passed to the rasterizer is the
+intersection of the clipping region and the specified rectangle.
+This function calls CFbsRasterizer::BeginBitmap() with the appropriate
+parameters. When finished retrieving scan lines from the extended bitmap,
+CFbsRasterizer::EndBitmap() must be called.
+@param aBitmap The bitmap to retrieve scan lines from.
+@param aDestRect A rectangle in coordinates relative to the graphics context that
+ bounds the area that aBitmap is to be blitted onto.
+@param aOffset An offset that converts aDestRect into coordinates relative to
+ the source bitmap.
+@return A pointer to the rasterizer owned by this thread's FBServ session.
+@return NULL if the rasterizer is not present or aBitmap is not an extended bitmap.
+@see CFbsRasterizer
+@internalComponent
+*/
+CFbsRasterizer* CFbsBitGc::PrepareRasterizerForExtendedBitmap(const CFbsBitmap& aBitmap, const TRect& aDestRect, const TPoint& aOffset)
+ {
+ CFbsRasterizer* rasterizer = NULL;
+ CFbsRasterizer::TBitmapDesc desc;
+ desc.iDataType = aBitmap.ExtendedBitmapType();
+ if (desc.iDataType != KNullUid)
+ {
+ rasterizer = CFbsBitmap::Rasterizer();
+ if (rasterizer)
+ {
+ desc.iSizeInPixels = aBitmap.SizeInPixels();
+ desc.iDispMode = aBitmap.DisplayMode();
+ desc.iData = aBitmap.DataAddress();
+ desc.iDataSize = aBitmap.DataSize();
+ RRegion rgn;
+ rgn.Copy(*iDefaultRegionPtr);
+ rgn.ClipRect(aDestRect);
+ rgn.Offset(aOffset);
+ BG_ASSERT_DEBUG(rgn.IsContainedBy(desc.iSizeInPixels), EBitgdiPanicOutOfBounds);
+ rasterizer->BeginBitmap(aBitmap.SerialNumber(), desc, &rgn);
+ rgn.Close();
+ }
+ }
+ return rasterizer;
+ }
+
+/** Prepares the rasterizer to retrieve scan lines from a bitmap if it is an
+extended bitmap. The region of interest passed to the rasterizer is the intersection
+of the clipping region, the clipping rectangle and the specified rectangle.
+This function calls CFbsRasterizer::BeginBitmap() with the appropriate
+parameters. When finished retrieving scan lines from the extended bitmap,
+CFbsRasterizer::EndBitmap() must be called.
+@param aBitmap The bitmap to retrieve scan lines from.
+@param aDestRect A rectangle in coordinates relative to the graphics context that
+ bounds the area that aBitmap is to be drawn onto.
+@param aSourceRect A rectangle in coordinates relative to the source bitmap that maps
+ to aDestRect after scaling and translation.
+@return A pointer to the rasterizer owned by this thread's FBServ session.
+@return NULL if the rasterizer is not present or aBitmap is not an extended bitmap.
+@see CFbsRasterizer
+@internalComponent
+*/
+CFbsRasterizer* CFbsBitGc::PrepareRasterizerForExtendedBitmap(const CFbsBitmap& aBitmap, const TRect& aDestRect, const TRect& aSourceRect)
+ {
+ CFbsRasterizer* rasterizer = NULL;
+ CFbsRasterizer::TBitmapDesc desc;
+ desc.iDataType = aBitmap.ExtendedBitmapType();
+ if (desc.iDataType != KNullUid)
+ {
+ rasterizer = CFbsBitmap::Rasterizer();
+ if (rasterizer)
+ {
+ desc.iSizeInPixels = aBitmap.SizeInPixels();
+ desc.iDispMode = aBitmap.DisplayMode();
+ desc.iData = aBitmap.DataAddress();
+ desc.iDataSize = aBitmap.DataSize();
+ RRegion rgn;
+ // Calculate the parameters for the linear DDA algorithm used to scale the region
+ // of interest before entering the rectangle loop, since they are invariant.
+ TLinearDDA xLine0, yLine0;
+ xLine0.Construct(TPoint(aSourceRect.iTl.iX, aDestRect.iTl.iX),
+ TPoint(aSourceRect.iBr.iX, aDestRect.iBr.iX),
+ TLinearDDA::ELeft);
+ yLine0.Construct(TPoint(aSourceRect.iTl.iY, aDestRect.iTl.iY),
+ TPoint(aSourceRect.iBr.iY, aDestRect.iBr.iY),
+ TLinearDDA::ELeft);
+ TInt n = iDefaultRegionPtr->Count();
+ for (TInt i = 0; i < n; ++i)
+ {
+ TRect rect = (*iDefaultRegionPtr)[i];
+ if (!rect.Intersects(iUserClipRect))
+ {
+ continue;
+ }
+ rect.Intersection(iUserClipRect);
+ if (!rect.Intersects(aDestRect))
+ {
+ continue;
+ }
+ rect.Intersection(aDestRect);
+ // Scale the region of interest from coordinates relative to the graphics
+ // context to coordinates relative to the bitmap, one rectangle at a time.
+ TLinearDDA xLine(xLine0), yLine(yLine0);
+ TInt ax, ay, bx, by;
+ xLine.JumpToYCoord(ax, rect.iTl.iX);
+ yLine.JumpToYCoord(ay, rect.iTl.iY);
+ xLine.JumpToYCoord(bx, rect.iBr.iX);
+ yLine.JumpToYCoord(by, rect.iBr.iY);
+ if (ax < bx && ay < by)
+ {
+ rgn.AddRect(TRect(ax, ay, bx, by));
+ }
+ }
+ BG_ASSERT_DEBUG(rgn.IsContainedBy(desc.iSizeInPixels), EBitgdiPanicOutOfBounds);
+ rasterizer->BeginBitmap(aBitmap.SerialNumber(), desc, &rgn);
+ rgn.Close();
+ }
+ }
+ return rasterizer;
+ }