os/graphics/graphicsdeviceinterface/bitgdi/sbit/BITBLT.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "BITPANIC.H"
    17 #include <fntstore.h>
    18 #include <bitmap.h>
    19 #include <bitstd.h>
    20 #include <bitdev.h>
    21 #include <bitdraw.h>
    22 #include <bitdrawscaling.h>
    23 #include <bitdrawinterfaceid.h>
    24 #include <bmalphablend.h>
    25 #include <graphics/fbsrasterizer.h>
    26 #include <graphics/bitmap.inl>
    27 #include <graphics/gdi/gdiinline.inl>
    28 
    29 GLREF_C void XorBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes);
    30 GLREF_C void AndBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes);
    31 GLREF_C void InvertBuffer(TUint32* aDestBuffer,TInt aNumBytes);
    32 GLREF_C void InvertBuffer(TUint8* aDestBuffer,TInt aNumBytes);
    33 LOCAL_C void TileScanLine(TPtr8& aScanLine,
    34 						  TInt aLengthInPixels,
    35 						  const TPoint& aSrcPt,
    36 						  const CBitwiseBitmap* aMaskBitmap,
    37 						  TLineScanningPosition& aScanLinePos,
    38 						  TUint32* aMaskBase,
    39 						  TDisplayMode aDisplayMode
    40 						  );
    41 
    42 /** Draws from another CFbsBitGc.
    43 
    44 @param aPoint The position to draw the top left corner of the piece of bitmap
    45 @param aGc The source bitmap graphics context */
    46 EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,const CFbsBitGc& aGc)
    47 	{
    48 	TRect deviceRect;
    49 	aGc.iDevice->iDrawDevice->GetDrawRect(deviceRect);
    50 	BitBlt(aDest,aGc,deviceRect);
    51 	}
    52 
    53 /** Draws a particular rectangle from another CFbsBitGc.
    54 
    55 @param aPoint The position to draw the top left corner of the piece of bitmap.
    56 @param aGc The source bitmap graphics context.
    57 @param aSrceRect A rectangle defining the piece of the source to be drawn. */
    58 EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,
    59 								const CFbsBitGc& aGc,
    60 								const TRect& aSrceRect)
    61 	{
    62 	if (CheckDevice(aSrceRect))
    63 		return;
    64 	aGc.CheckDevice();
    65 	CFbsDevice* srceDevice = aGc.iDevice;
    66 	if (!srceDevice)
    67 		return;
    68 
    69 	TRect srceRect(aSrceRect);
    70 	TRect deviceRect;
    71 	srceDevice->GetDrawRect(deviceRect);
    72 	if (!srceRect.Intersects(deviceRect))
    73 		return;
    74 	srceRect.Intersection(deviceRect);
    75 
    76 	const TPoint destPoint(aDest + iOrigin + srceRect.iTl - aSrceRect.iTl);
    77 	const TRect destRect(destPoint,srceRect.Size());
    78 	const TPoint offset(srceRect.iTl - destPoint);
    79 
    80 	TRect clippedDestRect(destRect);
    81 	AddRect(clippedDestRect);
    82 	if (UserClipRect(clippedDestRect))
    83 		return;
    84 
    85 	SetupDevice();
    86 	aGc.iDevice->DrawingBegin();
    87 	iDevice->DrawingBegin();
    88 
    89 	const TInt limit = iDefaultRegionPtr->Count();
    90 	TBool opaqueSource = (!IsAlphaChannel(srceDevice->DisplayMode())) && (iDrawMode == EDrawModePEN);
    91 	for(TInt count=0;count<limit;count++)
    92 		{
    93 		iClipRect=(*iDefaultRegionPtr)[count];
    94 		if(!iClipRect.Intersects(clippedDestRect))
    95 			continue;
    96 		iClipRect.Intersection(clippedDestRect);
    97 
    98 		TRect clippedSrceRect(iClipRect);
    99 		clippedSrceRect.Move(offset);
   100 
   101 		if (opaqueSource)
   102 			iDrawMode = EDrawModeWriteAlpha;// ie write rather then blend
   103 		DoBitBlt(iClipRect.iTl,srceDevice,clippedSrceRect);
   104 		if (opaqueSource)
   105 			iDrawMode = EDrawModePEN;// set it back how it was
   106 		iDevice->iDrawDevice->UpdateRegion(iClipRect);
   107 		}
   108 
   109 	aGc.iDevice->DrawingEnd();
   110 	iDevice->DrawingEnd();
   111 	}
   112 
   113 
   114 /** Draws the whole of a CFbsBitmap.
   115 
   116 @param aDest   The position to draw the top left corner of the bitmap.
   117 @param aBitmap The source bitmap. */
   118 EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,const CFbsBitmap* aBitmap)
   119     {
   120     if (aBitmap == NULL || !aBitmap->Handle())
   121     	return;
   122     
   123 	aBitmap->BeginDataAccess();
   124     BitBlt(aDest,aBitmap,TRect(aBitmap->SizeInPixels()));
   125 	aBitmap->EndDataAccess(ETrue);
   126 	}
   127 
   128 
   129 /** Draws a particular rectangle from a CFbsBitmap.
   130 
   131 @param aDest The position to draw the top left corner of the bitmap.
   132 @param aBitmap The source bitmap.
   133 @param aSrceRect A rectangle defining the piece of the source to be drawn. */
   134 EXPORT_C void CFbsBitGc::BitBlt(const TPoint& aDest,
   135 								const CFbsBitmap* aBitmap,
   136 								const TRect& aSrceRect)
   137     {
   138 	if (aBitmap == NULL || !aBitmap->Handle()|| CheckDevice(aSrceRect))
   139 		return;
   140 
   141 	aBitmap->BeginDataAccess();
   142 		
   143 	TRect srceRect(aSrceRect);
   144 	const TRect area(aBitmap->SizeInPixels());
   145 	if (!srceRect.Intersects(area))
   146 		{
   147 		aBitmap->EndDataAccess(ETrue);
   148 		return;
   149 		}
   150 	srceRect.Intersection(area);
   151 
   152 	const TPoint destPoint(aDest + iOrigin + srceRect.iTl - aSrceRect.iTl);
   153 	const TPoint offset(srceRect.iTl - destPoint);
   154 
   155 	TRect targetRect(destPoint,srceRect.Size());
   156 	AddRect(targetRect);
   157 	if (UserClipRect(targetRect))
   158 		{
   159 		aBitmap->EndDataAccess(ETrue);
   160 		return;
   161 		}
   162 
   163 	SetupDevice();
   164 	iDevice->DrawingBegin();
   165 
   166 	CBitwiseBitmap* srce = ((CFbsBitGcBitmap*)aBitmap)->Address();
   167 	BG_ASSERT_DEBUG(srce,EBitgdiPanicInvalidBitmap);
   168 
   169 	CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aBitmap, targetRect, offset);
   170 
   171 	TInt count;
   172 	const TInt limit = iDefaultRegionPtr->Count();
   173 	CGraphicsAccelerator* ga = GraphicsAccelerator();
   174 	TBool opaqueSource = (!IsAlphaChannel(aBitmap->DisplayMode())) && (iDrawMode == EDrawModePEN);
   175 
   176 	if(ga && (iShadowMode == CFbsDrawDevice::ENoShadow))
   177 		{
   178 	    TInt gaOperationResult = KErrUnknown;
   179 		TAcceleratedBitmapSpec bitmapSpec(const_cast<CFbsBitmap*>(aBitmap));
   180         iDevice->DrawingEnd();
   181 
   182 		for(count=0;count<limit;count++)
   183 			{
   184 
   185 			iClipRect=(*iDefaultRegionPtr)[count];
   186 			if(!iClipRect.Intersects(targetRect))
   187 				continue;
   188 			iClipRect.Intersection(targetRect);
   189 
   190 			TRect clippedSrceRect(iClipRect);
   191 			clippedSrceRect.Move(offset);
   192 
   193 			gaOperationResult = ga->Operation(TGopBitBlt(iClipRect.iTl,bitmapSpec,clippedSrceRect));
   194 			if(gaOperationResult != KErrNone)
   195 				break;
   196 			iDevice->iDrawDevice->UpdateRegion(iClipRect);
   197 			}
   198 		if(gaOperationResult == KErrNone)
   199 			goto finish;
   200 		iDevice->DrawingBegin();
   201 		}
   202 
   203 	for(count=0;count<limit;count++)
   204 		{
   205 		iClipRect=(*iDefaultRegionPtr)[count];
   206 		if(!iClipRect.Intersects(targetRect))
   207 			continue;
   208 		iClipRect.Intersection(targetRect);
   209 
   210 		TRect clippedSrceRect(iClipRect);
   211 		clippedSrceRect.Move(offset);
   212 
   213 		if (opaqueSource)
   214 			iDrawMode = EDrawModeWriteAlpha;// ie write rather then blend
   215 		DoBitBlt(iClipRect.iTl,srce,aBitmap->DataAddress(),aBitmap->DataStride(),clippedSrceRect);
   216 		if (opaqueSource)
   217 			iDrawMode = EDrawModePEN;// set it back how it was
   218 		iDevice->iDrawDevice->UpdateRegion(iClipRect);
   219 		}
   220 
   221 	iDevice->DrawingEnd();
   222 finish:
   223 	if (rasterizer)
   224 		{
   225 		rasterizer->EndBitmap(aBitmap->SerialNumber());
   226 		}
   227 	aBitmap->EndDataAccess(ETrue);
   228 	}
   229 
   230 
   231 /** Performs a masked bitmap block transfer.
   232 
   233 The function provides a concrete implementation of the pure virtual
   234 function CBitmapContext::BitBltMasked(). The function
   235 behaviour is the same as documented in that class.
   236 
   237 There are several points to note about this implementation of
   238 BitBltMasked():
   239 
   240 1.For best performance the aMaskBitmap and source aBitmap should
   241 have the same display mode as the destination device/bitmap.
   242 
   243 2.For performance reasons this implementation does not validate
   244 the contents of the aMaskBitmap. The caller must ensure the mask
   245 pixels are either black or white otherwise undefined blitting causing
   246 unpredictable discoloration will result. This is especially true
   247 for index (where pixel is palette entry) display modes (e.g. EColor16).
   248 It is up to the caller to decide if they wish to utilise
   249 CFbsBitmap::IsMonochrome().
   250 
   251 3.Alpha blending is used when the display mode of the mask bitmap aMaskBitmap
   252 is EGray256.
   253 
   254 @see CBitmapContext::BitBltMasked() */
   255 EXPORT_C void CFbsBitGc::BitBltMasked(const TPoint& aDest,
   256 									  const CFbsBitmap* aBitmap,
   257 									  const TRect& aSourceRect,
   258 									  const CFbsBitmap* aMaskBitmap,
   259 									  TBool aInvertMask)
   260     {
   261 	if (aBitmap == NULL || !aBitmap->Handle() ||
   262 		aMaskBitmap == NULL || !aMaskBitmap->Handle() ||
   263 		CheckDevice(aSourceRect))
   264 		return;
   265 
   266 	aBitmap->BeginDataAccess();
   267 	aMaskBitmap->BeginDataAccess();
   268 		
   269 	TRect srceRect(aSourceRect);
   270 	const TRect area(aBitmap->SizeInPixels());
   271 	if (!srceRect.Intersects(area))
   272 		{
   273 		aBitmap->EndDataAccess(ETrue);
   274 		aMaskBitmap->EndDataAccess(ETrue);
   275 		return;
   276 		}
   277 	srceRect.Intersection(area);
   278 
   279 	const TPoint destPoint(aDest + iOrigin + srceRect.iTl - aSourceRect.iTl);
   280 	const TRect destRect(destPoint,srceRect.Size());
   281 	const TPoint offset(srceRect.iTl - destPoint);
   282 	const TPoint ditherorigin(iDitherOrigin + aDest);
   283 
   284 	TRect clippedDestRect(destRect);
   285 	AddRect(clippedDestRect);
   286 	if (UserClipRect(clippedDestRect))
   287 		{
   288 		aBitmap->EndDataAccess(ETrue);
   289 		aMaskBitmap->EndDataAccess(ETrue);
   290 		return;
   291 		}
   292 
   293 	SetupDevice();
   294 	iDevice->DrawingBegin();
   295 
   296 
   297 	CBitwiseBitmap* srcebmp = ((CFbsBitGcBitmap*)aBitmap)->Address();
   298 	CBitwiseBitmap* maskbmp = ((CFbsBitGcBitmap*)aMaskBitmap)->Address();
   299 	BG_ASSERT_DEBUG(srcebmp,EBitgdiPanicInvalidBitmap);
   300 	BG_ASSERT_DEBUG(maskbmp,EBitgdiPanicInvalidBitmap);
   301 
   302 	const TDisplayMode maskMode = maskbmp->DisplayMode();
   303 
   304 	// Do the background fill the lazy way with flicker if any of the following are true:
   305 	// 1. There is no anti-flicker buffer
   306 	// 2. The source and mask bitmaps are the same
   307 	// 3. The brush style is patterned and the mask is an alpha mask
   308 	// 4. The brush style is not null or solid or patterned
   309 
   310 	if (!iDevice->iBitBltMaskedBuffer ||
   311 		srcebmp == maskbmp ||
   312 		(maskMode == EGray256 && iBrushStyle == EPatternedBrush) ||
   313 		iBrushStyle > EPatternedBrush)
   314 		{
   315 		iBrushBitmap.BeginDataAccess();
   316 		CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
   317 		RectFill(destRect);
   318 		if (brushRasterizer)
   319 			{
   320 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   321 			}
   322 		iBrushBitmap.EndDataAccess(ETrue);
   323 		}
   324 
   325 	const TInt8 shadowMode = iShadowMode;
   326 	iShadowMode = CFbsDrawDevice::ENoShadow;
   327 	SetupDevice();
   328 
   329 	CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aBitmap, clippedDestRect, offset);
   330 	CFbsRasterizer* maskRasterizer = NULL;
   331 	if (srcebmp != maskbmp)
   332 		{
   333 		if (aMaskBitmap->SizeInPixels().iWidth >= aBitmap->SizeInPixels().iWidth
   334 			&& aMaskBitmap->SizeInPixels().iHeight >= aBitmap->SizeInPixels().iHeight)
   335 			{
   336 			// Mask is not tiled. Pass same region of interest as source bitmap to rasterizer.
   337 			maskRasterizer = PrepareRasterizerForExtendedBitmap(*aMaskBitmap, clippedDestRect, offset);
   338 			}
   339 		else
   340 			{
   341 			// Mask is tiled. Do not pass any region of interest to rasterizer.
   342 			maskRasterizer = PrepareRasterizerForExtendedBitmap(*aMaskBitmap);
   343 			}
   344 		}
   345 
   346     TInt count;
   347 	const TInt limit = iDefaultRegionPtr->Count();
   348 	CGraphicsAccelerator* ga = GraphicsAccelerator();
   349 	TBool opaqueSource = (!IsAlphaChannel(aBitmap->DisplayMode())) && (iDrawMode == EDrawModePEN);
   350 
   351 	if(ga)
   352 		{
   353 		if((iBrushStyle == ENullBrush) && aInvertMask &&
   354 		   (shadowMode == CFbsDrawDevice::ENoShadow))
   355 			{
   356 			TInt gaOperationResult = KErrUnknown;
   357 			TAcceleratedBitmapSpec bitmapSpec(const_cast<CFbsBitmap*>(aBitmap));
   358 			TAcceleratedBitmapSpec bitmapMaskSpec(const_cast<CFbsBitmap*>(aMaskBitmap));
   359 			iDevice->DrawingEnd();
   360 
   361 			for(count=0;count<limit;count++)
   362 				{
   363 				iClipRect=(*iDefaultRegionPtr)[count];
   364 				if(!iClipRect.Intersects(clippedDestRect))
   365 					continue;
   366 				iClipRect.Intersection(clippedDestRect);
   367 				TRect clippedSrceRect(iClipRect);
   368 				clippedSrceRect.Move(offset);
   369 
   370 				if(maskbmp->DisplayMode() == EGray256)
   371 					gaOperationResult = ga->Operation(TGopBitBltAlphaBitmap(iClipRect.iTl,
   372 																			bitmapSpec,
   373 																			clippedSrceRect,
   374 																			bitmapMaskSpec));
   375 				else
   376 					gaOperationResult = ga->Operation(TGopBitBltMasked(iClipRect.iTl,
   377 																	   bitmapSpec,
   378 																	   clippedSrceRect,
   379 																	   bitmapMaskSpec));
   380 
   381 				if(gaOperationResult != KErrNone)
   382 					break;
   383 				iDevice->iDrawDevice->UpdateRegion(iClipRect);
   384 				}
   385 			if(gaOperationResult == KErrNone)
   386 				goto finish;
   387 			iDevice->DrawingBegin();
   388 			}
   389 		}
   390 
   391 	for(count=0;count<limit;count++)
   392 		{
   393 		iClipRect=(*iDefaultRegionPtr)[count];
   394 		if (!iClipRect.Intersects(clippedDestRect))
   395 			continue;
   396 		iClipRect.Intersection(clippedDestRect);
   397 
   398 		TRect clippedSrceRect(iClipRect);
   399 		clippedSrceRect.Move(offset);
   400 
   401 		if (opaqueSource)
   402 			iDrawMode = EDrawModeWriteAlpha;// ie write rather then blend
   403 		DoBitBltMasked(iClipRect.iTl,
   404 					   srcebmp,
   405 					   aBitmap->DataAddress(),
   406 					   clippedSrceRect,
   407 					   maskbmp,
   408 					   aMaskBitmap->DataAddress(),
   409 					   aInvertMask,
   410 					   ditherorigin,
   411 					   shadowMode);
   412 		if (opaqueSource)
   413 			iDrawMode = EDrawModePEN;// set it back how it was
   414 		iDevice->iDrawDevice->UpdateRegion(iClipRect);
   415 		}
   416 
   417 	iDevice->DrawingEnd();
   418 finish:
   419 	if (rasterizer)
   420 		{
   421 		rasterizer->EndBitmap(aBitmap->SerialNumber());
   422 		}
   423 	if (maskRasterizer)
   424 		{
   425 		maskRasterizer->EndBitmap(aMaskBitmap->SerialNumber());
   426 		}
   427 	aBitmap->EndDataAccess(ETrue);
   428 	aMaskBitmap->EndDataAccess(ETrue);
   429 	iShadowMode = shadowMode;
   430 	}
   431 /**
   432 Does BitBlt operation of source and bitmap per scanline.
   433 
   434 */
   435 void CFbsBitGc::DoBitBlt(const TPoint& aDest,CFbsDevice* aSrce,const TRect& aSrceRect)
   436 	{
   437 	const TInt width = aSrceRect.Width();
   438 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   439 #ifdef _DEBUG
   440 	TRect deviceSrcRect;
   441 	aSrce->iDrawDevice->GetDrawRect(deviceSrcRect);
   442 	TRect deviceDestRect;
   443 	drawDevice->GetDrawRect(deviceDestRect);
   444 #endif
   445 	BG_ASSERT_DEBUG(aSrceRect.iTl.iX >= deviceSrcRect.iTl.iX, EBitgdiPanicOutOfBounds);
   446 	BG_ASSERT_DEBUG(aSrceRect.iTl.iY >= deviceSrcRect.iTl.iY, EBitgdiPanicOutOfBounds);
   447 	BG_ASSERT_DEBUG(aSrceRect.iBr.iX <= deviceSrcRect.iBr.iX, EBitgdiPanicOutOfBounds);
   448 	BG_ASSERT_DEBUG(aSrceRect.iBr.iY <= deviceSrcRect.iBr.iY, EBitgdiPanicOutOfBounds);
   449 	BG_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
   450 	BG_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
   451 	BG_ASSERT_DEBUG((aDest.iX + aSrceRect.Width())  <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
   452 	BG_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
   453 
   454 	CFbsDrawDevice* srcDrawDevice = aSrce->iDrawDevice;
   455 	TAny* interface=NULL;
   456 	if (iDrawMode==EDrawModeWriteAlpha &&
   457 		iShadowMode == CFbsDrawDevice::ENoShadow &&
   458 		(aSrceRect.iTl.iX >= 0) &&  (aSrceRect.iTl.iY >= 0) &&
   459 		(aDest.iX >= 0) && (aDest.iY >= 0) &&
   460 	    srcDrawDevice->DisplayMode() == drawDevice->DisplayMode() &&
   461 		drawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone)
   462 		{
   463 		// Conditions in CFbsBitGc allow for optimised blitting.
   464 		// The draw device supports the optimised blitting function.
   465 		// Operation may fail regardless due to unacceptable conditions in the draw device.
   466 		BG_ASSERT_DEBUG(interface!=NULL, EBitgdiPanicNullPointer);
   467 		MFastBlit2* fastBlit = reinterpret_cast<MFastBlit2*>(interface);
   468 		if (fastBlit->WriteBitmapBlock(aDest, srcDrawDevice, aSrceRect) == KErrNone)
   469 			{
   470 			return;
   471 			}
   472 		}
   473 	MFastBlend* fastBlend=NULL;
   474 	if (FastBlendInterface(NULL,NULL,fastBlend)==KErrNone)
   475 		{
   476 		if (fastBlend->FastBlendBitmap(aDest, srcDrawDevice, aSrceRect, iDrawMode, iShadowMode)==KErrNone)
   477 			{
   478 			return;
   479 			}
   480 		}
   481 	//scanLineBuffer is destination scanline buffer.
   482 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
   483 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
   484 	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
   485 	//dispMode is destination display mode.
   486 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
   487 	TInt destY = aDest.iY;
   488 	//Gets the scanline from the source, into the buffer scanLineDes.
   489 	//The DoGetScanLine operation is also responsible for converting
   490 	// the buffer pixel format to destination display format.
   491 
   492 	for (TInt row = aSrceRect.iTl.iY; row < aSrceRect.iBr.iY; row++,destY++)
   493 		{
   494 		aSrce->DoGetScanLine(scanLineDes,TPoint(aSrceRect.iTl.iX,row),width,dispMode);
   495 		drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,iDrawMode);
   496 		}
   497 	}
   498 
   499 /**
   500 Calculates the position into the scanline for the given x coordinate
   501 */
   502 TUint CFbsBitGc::MemoryOffsetForPixelPitch(TUint aX, TDisplayMode aDisplayMode)
   503 	{
   504 	switch (aDisplayMode)
   505 		{
   506 		case EColor16MU:
   507 		case EColor16MA:
   508 		case EColor16MAP:
   509 			return aX << 2;
   510 
   511 		case EColor16M:
   512 			return aX * 3;
   513 
   514 		case EColor4K:
   515 		case EColor64K:
   516 			return aX << 1;
   517 
   518 		case EGray256:
   519 		case EColor256:
   520 			return aX;
   521 
   522 		default:
   523 			BG_PANIC_DEBUG(EBitgdiPanicInvalidDisplayMode);
   524 		break;
   525 		}
   526 	return 0;
   527 	}
   528 
   529 /**
   530 Gets the scanline pointer with the offset
   531 */
   532 TUint32* CFbsBitGc::GetScanLineOffsetPtr(CBitwiseBitmap* aSrce, TUint32*& aSlptr, TInt aLength, TPoint aPixel,TUint32* aBase, TLineScanningPosition& aLineScanningPosition, TUint aXOffset)
   533 	{
   534 	aSrce->GetScanLinePtr(aSlptr, aLength, aPixel, aBase, aLineScanningPosition);
   535 	return (TUint32*)((TUint8*)aSlptr + aXOffset);
   536 	}
   537 
   538 void CFbsBitGc::DoBitBlt(const TPoint& aDest,
   539 						 CBitwiseBitmap* aSrce,
   540 						 TUint32* aBase,
   541 						 TInt aStride,
   542 						 const TRect& aSrceRect)
   543 	{
   544 	// Does multiple bitmap widths for painting rects only
   545 	const TInt width = aSrceRect.Width();
   546 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   547 #ifdef _DEBUG
   548 	TRect deviceDestRect;
   549 	drawDevice->GetDrawRect(deviceDestRect);
   550 #endif
   551 	BG_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
   552 	BG_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
   553 	BG_ASSERT_DEBUG((aDest.iX + aSrceRect.Width())  <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
   554 	BG_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
   555 
   556 	TSize srcSize = aSrce->SizeInPixels();
   557 	if (srcSize.iWidth == 0 || srcSize.iHeight == 0)
   558 		return; //no point doing anything if asked to draw zero size bitmap
   559 
   560 	TAny* interface=NULL;
   561 	if (iDrawMode==EDrawModeWriteAlpha &&
   562 		iShadowMode == CFbsDrawDevice::ENoShadow &&
   563 		aSrceRect.iTl.iX >= 0 &&
   564 		aSrceRect.iTl.iY >= 0 &&
   565 		aSrceRect.iBr.iX <= srcSize.iWidth &&
   566 		aSrceRect.iBr.iY <= srcSize.iHeight &&
   567 		(aDest.iX >= 0) && (aDest.iY >= 0) &&
   568 		!aSrce->IsCompressed() &&
   569 		aSrce->DisplayMode() == drawDevice->DisplayMode() &&
   570 		drawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone)
   571 		{
   572 		// Conditions in CFbsBitGc allow for optimised blitting.
   573 		// The draw device supports the optimised blitting function.
   574 		// Operation may fail regardless due to unacceptable conditions in the draw device.
   575 		BG_ASSERT_DEBUG(interface!=NULL, EBitgdiPanicNullPointer);
   576 		MFastBlit2* fastBlit = reinterpret_cast<MFastBlit2*>(interface);
   577 		if (fastBlit && (fastBlit->WriteBitmapBlock(aDest, aBase, aStride, srcSize, aSrceRect) == KErrNone))
   578 			{
   579 			return;
   580 			}
   581 		}
   582 	MFastBlend* fastBlend=NULL;
   583 	if (FastBlendInterface(aSrce,NULL,fastBlend)==KErrNone)
   584 		{
   585 		if (fastBlend->FastBlendBitmap(aDest, aBase, aStride, srcSize, aSrceRect, aSrce->DisplayMode(), iDrawMode, iShadowMode)== KErrNone)
   586 			{
   587 			return;
   588 			}
   589 		}
   590 
   591 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
   592 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
   593 	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
   594 
   595 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
   596 
   597 	const TBool useScanLinePtr = (!iShadowMode) && (dispMode == aSrce->DisplayMode()) && (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8);
   598 	TUint32* slptr=NULL;
   599 	TUint offset = 0;
   600 	TUint32* lastScanLine = NULL;
   601 	if (useScanLinePtr)
   602 		lastScanLine = aSrce->ScanLineAddress(aBase,aSrceRect.iBr.iY-1);
   603 
   604 	TInt srceWidth = srcSize.iWidth;
   605 	TInt partlinestart = 0;
   606 	partlinestart = aSrceRect.iTl.iX % srceWidth;
   607 	if (partlinestart < 0)
   608 		partlinestart += srceWidth;
   609 	const TInt partlinelength = Min(srceWidth - partlinestart,width);
   610 	TInt destX = aDest.iX;
   611 	const TInt destXlimit=destX+width;
   612 
   613 	// first part line
   614 	if (partlinestart > 0 && partlinelength > 0)
   615 		{
   616 		TPoint srcecoord1(partlinestart,aSrceRect.iTl.iY);
   617 		TInt desty = aDest.iY;
   618 		TPoint ditherorigin(iDitherOrigin);
   619 		ditherorigin.iX += aDest.iX;
   620 		ditherorigin.iY += desty;
   621 
   622 		TLineScanningPosition lineScanPos(aBase);
   623 
   624 		if (useScanLinePtr)
   625 			{
   626 			offset = MemoryOffsetForPixelPitch(partlinestart, dispMode);
   627 			if (aSrce->IsCompressed())
   628 				{
   629 				while (srcecoord1.iY < aSrceRect.iBr.iY)
   630 					{
   631 					scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, partlinelength, srcecoord1, aBase, lineScanPos, offset);
   632 					if (srcecoord1.iY==aSrceRect.iTl.iY)
   633 						{
   634 						aSrce->SetCompressionBookmark(lineScanPos,aBase,NULL);
   635 						}
   636 					drawDevice->WriteLine(aDest.iX,desty,partlinelength, scanLineBuffer,iDrawMode);
   637 					srcecoord1.iY++,desty++,ditherorigin.iY++;
   638 					}
   639 				}
   640 			else
   641 				{
   642 				while (srcecoord1.iY < aSrceRect.iBr.iY)
   643 					{
   644 					scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, partlinelength, srcecoord1, aBase, lineScanPos, offset);
   645 					do
   646 						{
   647 						drawDevice->WriteLine(aDest.iX,desty,partlinelength, scanLineBuffer,iDrawMode);
   648 						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
   649 						srcecoord1.iY++,desty++,ditherorigin.iY++;
   650 						}
   651 					while ((srcecoord1.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
   652 					}
   653 				}
   654 			}
   655 		else
   656 			{
   657 			for (; srcecoord1.iY < aSrceRect.iBr.iY; srcecoord1.iY++,desty++,ditherorigin.iY++)
   658 				{
   659 				aSrce->GetScanLine(scanLineDes,srcecoord1,partlinelength,ETrue,
   660 						   ditherorigin,dispMode,aBase, lineScanPos);
   661 				if (srcecoord1.iY==aSrceRect.iTl.iY)
   662 					{
   663 					aSrce->SetCompressionBookmark(lineScanPos,aBase,NULL);
   664 					}
   665 				drawDevice->WriteLine(aDest.iX,desty,partlinelength, scanLineBuffer,iDrawMode);
   666 				}
   667 			}
   668 
   669 		destX+=partlinelength;
   670 		}
   671 
   672 	// multiple complete lines - columns
   673 	TInt numcolumns = 0;
   674 	numcolumns = (destXlimit - destX) / srceWidth;
   675 	if (numcolumns > 0)
   676 		{
   677 		TPoint srcecoord2(0,aSrceRect.iTl.iY);
   678 		TInt desty = aDest.iY;
   679 		TPoint ditherorigin(iDitherOrigin);
   680 		ditherorigin.iX += destX;
   681 		ditherorigin.iY += desty;
   682 
   683 		TLineScanningPosition lineScanPos(aBase);
   684 
   685 		if (useScanLinePtr)
   686 			{
   687 			if (aSrce->IsCompressed())
   688 				{
   689 				while (srcecoord2.iY < aSrceRect.iBr.iY)
   690 					{
   691 					TPoint coord(srcecoord2);
   692 					aSrce->GetScanLinePtr(slptr, srceWidth, coord,aBase, lineScanPos);
   693 					if (srcecoord2.iY==aSrceRect.iTl.iY)
   694 						{
   695 						aSrce->SetCompressionBookmark(lineScanPos, aBase,NULL);
   696 						}
   697 					TInt tempdestX = destX;
   698 					for (TInt count = 0; count < numcolumns; count++,tempdestX+=srceWidth)
   699 						{
   700 						drawDevice->WriteLine(tempdestX,desty,srceWidth, slptr,iDrawMode);
   701 						ditherorigin.iX += srceWidth;
   702 						}
   703 					srcecoord2.iY++,desty++,ditherorigin.iY++;
   704 					}
   705 				}
   706 			else
   707 				{
   708 				while (srcecoord2.iY < aSrceRect.iBr.iY)
   709 					{
   710 					TPoint coord(srcecoord2);
   711 					aSrce->GetScanLinePtr(slptr, srceWidth, coord,aBase, lineScanPos);
   712 					do
   713 						{
   714 						TInt tempdestX = destX;
   715 						for (TInt count = 0; count < numcolumns; count++,tempdestX+=srceWidth)
   716 							{
   717 							drawDevice->WriteLine(tempdestX,desty,srceWidth, slptr,iDrawMode);
   718 							ditherorigin.iX += srceWidth;
   719 							}
   720 						slptr = (TUint32*)((TUint8*)slptr + aStride);
   721 						srcecoord2.iY++,desty++,ditherorigin.iY++;
   722 						}
   723 					while ((srcecoord2.iY < aSrceRect.iBr.iY) && (slptr < lastScanLine));
   724 					}
   725 				}
   726 			}
   727 		else
   728 			{
   729 			for (; srcecoord2.iY < aSrceRect.iBr.iY; srcecoord2.iY++,desty++,ditherorigin.iY++)
   730 				{
   731 				TInt tempdestX = destX;
   732 				TPoint coord(srcecoord2);
   733 				aSrce->GetScanLinePtr(slptr, srceWidth, coord,aBase, lineScanPos);
   734 				if (srcecoord2.iY==aSrceRect.iTl.iY)
   735 					{
   736 					aSrce->SetCompressionBookmark(lineScanPos, aBase,NULL);
   737 					}
   738 				for (TInt count = 0; count < numcolumns; count++,tempdestX+=srceWidth)
   739 					{
   740 					aSrce->GetScanLine(slptr, scanLineDes,coord,srceWidth,ETrue,
   741 						   ditherorigin,dispMode);
   742 					drawDevice->WriteLine(tempdestX,desty,srceWidth, scanLineBuffer,iDrawMode);
   743 					ditherorigin.iX += srceWidth;
   744 					}
   745 				}
   746 			}
   747 
   748 		destX += numcolumns * srceWidth;
   749 		}
   750 
   751 	// final part line
   752 	if (destX < destXlimit)
   753 		{
   754 		const TInt restofline = destXlimit - destX;
   755 		TPoint srcecoord3(0,aSrceRect.iTl.iY);
   756 		TInt desty = aDest.iY;
   757 		TPoint ditherorigin(iDitherOrigin);
   758 		ditherorigin.iX += destX;
   759 		ditherorigin.iY += desty;
   760 
   761 		TLineScanningPosition lineScanPos(aBase);
   762 
   763 		if (useScanLinePtr)
   764 			{
   765 			offset = 0;
   766 			if (aSrce->IsCompressed())
   767 				{
   768 				while (srcecoord3.iY < aSrceRect.iBr.iY)
   769 					{
   770 					scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, srceWidth, srcecoord3, aBase, lineScanPos, offset);
   771 					if (srcecoord3.iY==aSrceRect.iTl.iY)
   772 						{
   773 						aSrce->SetCompressionBookmark(lineScanPos,aBase,NULL);
   774 						}
   775 					drawDevice->WriteLine(destX,desty,restofline,scanLineBuffer,iDrawMode);
   776 					srcecoord3.iY++,desty++,ditherorigin.iY++;
   777 					}
   778 				}
   779 			else
   780 				{
   781 				while (srcecoord3.iY < aSrceRect.iBr.iY)
   782 					{
   783 					scanLineBuffer = GetScanLineOffsetPtr(aSrce, slptr, srceWidth, srcecoord3, aBase, lineScanPos, offset);
   784 					do
   785 						{
   786 						drawDevice->WriteLine(destX,desty,restofline,scanLineBuffer,iDrawMode);
   787 						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
   788 						srcecoord3.iY++,desty++,ditherorigin.iY++;
   789 						}
   790 					while ((srcecoord3.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
   791 					}
   792 				}
   793 			}
   794 		else
   795 			{
   796 			for (; srcecoord3.iY < aSrceRect.iBr.iY; srcecoord3.iY++,desty++,ditherorigin.iY++)
   797 				{
   798 				aSrce->GetScanLine(scanLineDes,srcecoord3,srceWidth,ETrue,
   799 								   ditherorigin,dispMode,aBase,lineScanPos);
   800 				if (srcecoord3.iY==aSrceRect.iTl.iY)
   801 					{
   802 					aSrce->SetCompressionBookmark(lineScanPos, aBase,NULL);
   803 					}
   804 				drawDevice->WriteLine(destX,desty,restofline,scanLineBuffer,iDrawMode);
   805 				}
   806 			}
   807 		}
   808 	}
   809 
   810 void CFbsBitGc::DoBitBltMasked(const TPoint& aDest,
   811 							   CBitwiseBitmap* aSourceBitmap,
   812 							   TUint32* aSourceBase,
   813 							   const TRect& aSourceRect,
   814 							   CBitwiseBitmap* aMaskBitmap,
   815 							   TUint32* aMaskBase,
   816 							   TBool aInvertMask,
   817 							   const TPoint& aDitherOrigin,
   818 							   TInt aShadowMode)
   819 	{
   820 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   821 #ifdef _DEBUG
   822 	TRect deviceDestRect;
   823 	drawDevice->GetDrawRect(deviceDestRect);
   824 #endif
   825 	BG_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
   826 	BG_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
   827 	BG_ASSERT_DEBUG((aDest.iX + aSourceRect.Width()) <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
   828 	BG_ASSERT_DEBUG((aDest.iY + aSourceRect.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
   829 
   830 	MFastBlend* fastBlend=NULL;
   831 	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
   832 		{
   833 		if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
   834 							aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aSourceRect.iTl, aInvertMask,
   835 							iDrawMode, aShadowMode)==KErrNone)
   836 			{
   837 			return;
   838 			}
   839 		}
   840 
   841 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
   842 	if (aMaskBitmap->DisplayMode() == EGray256)
   843 		{
   844 		DoBitBltAlpha(aDest,aSourceBitmap,aSourceBase,aSourceRect,
   845 					  aMaskBitmap,aMaskBase,aSourceRect.iTl,aShadowMode, EFalse);
   846 		}
   847 	// if screen driver is 16MAP we avoid logical operator pen modes by using DoBitBltAlpha() for blitting
   848 	else if (dispMode == EColor16MAP)
   849 		{
   850 		DoBitBltAlpha(aDest,aSourceBitmap,aSourceBase,aSourceRect,
   851 					  aMaskBitmap,aMaskBase,aSourceRect.iTl,aShadowMode, aInvertMask);
   852 		}
   853 
   854 	else if (aSourceBitmap == aMaskBitmap)
   855 		{
   856 		const TInt width = aSourceRect.Width();
   857 		TPoint ditherOrigin(aDitherOrigin + aDest);
   858 		const TDrawMode drawMode = aInvertMask ? EDrawModeAND : EDrawModeOR;
   859 		TPoint srcePoint(aSourceRect.iTl);
   860 		TInt destY = aDest.iY;
   861 
   862 		TLineScanningPosition lineScanPos(aSourceBase);
   863 
   864 		const TBool useScanLinePtr = (!aShadowMode) && (dispMode == aSourceBitmap->DisplayMode() && (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8));
   865 		if (useScanLinePtr)
   866 			{
   867 			TUint32* scanLineBuffer = NULL;
   868 			TUint32* slptr=NULL;
   869 			TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode);
   870 
   871 			if (aSourceBitmap->IsCompressed())
   872 				{
   873 				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
   874 					{
   875 					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
   876 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
   877 					}
   878 				}
   879 			else
   880 				{
   881 				TUint stride = aSourceBitmap->DataStride();
   882 				TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
   883 
   884 				while (srcePoint.iY < aSourceRect.iBr.iY)
   885 					{
   886 					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
   887 					do
   888 						{
   889 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
   890 						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + stride);
   891 						destY++,srcePoint.iY++,ditherOrigin.iY++;
   892 						}
   893 					while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
   894 					}
   895 				}
   896 			}
   897 		else
   898 			{
   899 			const TInt scanLineBytes = drawDevice->ScanLineBytes();
   900 			TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
   901 			TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
   902 			for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
   903 				{
   904 				aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,
   905 								   ETrue,ditherOrigin,dispMode,aSourceBase,lineScanPos);
   906 
   907 				if (aShadowMode)
   908 					{
   909 					drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
   910 					drawDevice->ShadowBuffer(width,scanLineBuffer);
   911 					drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
   912 					}
   913 
   914 				drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
   915 				}
   916 			}
   917 		}
   918 	else
   919 		{
   920 		if (iDevice->iBitBltMaskedBuffer)
   921 			{
   922 			if (iBrushStyle == ESolidBrush)
   923 				DoBitBltMaskedNonFlickerSolid(aDest,aSourceBitmap,aSourceBase,aSourceRect,
   924 											  aMaskBitmap,aMaskBase,aInvertMask,aDitherOrigin,
   925 											  aShadowMode);
   926 			else if (iBrushStyle == EPatternedBrush)
   927 				DoBitBltMaskedNonFlickerPatterned(aDest,aSourceBitmap,aSourceBase,aSourceRect,
   928 												  aMaskBitmap,aMaskBase,aInvertMask,
   929 												  aDitherOrigin,aShadowMode);
   930 			else
   931 				DoBitBltMaskedNonFlicker(aDest,aSourceBitmap,aSourceBase,aSourceRect,
   932 										 aMaskBitmap,aMaskBase,aInvertMask,aDitherOrigin,
   933 										 aShadowMode);
   934 			}
   935 		else
   936 			DoBitBltMaskedFlicker(aDest,aSourceBitmap,aSourceBase,aSourceRect,aMaskBitmap,
   937 								  aMaskBase,aInvertMask,aDitherOrigin,aShadowMode);
   938 		}
   939 	}
   940 
   941 void CFbsBitGc::DoBitBltMaskedFlicker(const TPoint& aDest,
   942 									  CBitwiseBitmap* aSourceBitmap,
   943 									  TUint32* aSourceBase,
   944 									  const TRect& aSourceRect,
   945 									  CBitwiseBitmap* aMaskBitmap,
   946 									  TUint32* aMaskBase,
   947 									  TBool aInvertMask,
   948 									  const TPoint& aDitherOrigin,
   949 									  TInt aShadowMode)
   950 	{
   951 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   952 
   953 	const TInt width = aSourceRect.Width();
   954 	TInt destY = aDest.iY;
   955 	TPoint srcePoint(aSourceRect.iTl);
   956 
   957 	TLineScanningPosition lineScanPos(aSourceBase);
   958 	TLineScanningPosition lineScanPosMask(aMaskBase);
   959 
   960 	const TDisplayMode srcFormat = aSourceBitmap->DisplayMode();
   961 	const TDisplayMode maskFormat = aMaskBitmap->DisplayMode();
   962 	
   963 	if (aMaskBitmap->IsCompressed()) 
   964        { 
   965        HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4); 
   966        if (!hBuf) 
   967           return; // Out of memory so do not draw anything 
   968        lineScanPosMask.iScanLineBuffer = hBuf; 
   969        } 
   970 
   971 	TAny* interface=NULL;
   972 	if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) &&
   973 		maskFormat == EGray2 &&
   974 		!aShadowMode &&
   975 		aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
   976 		aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
   977 		drawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
   978 		{
   979 		// Parameters allow optimised code path
   980 		TInt length = width;
   981 		TUint32* srcPtr=NULL;
   982 		TUint32* maskPtr=NULL;
   983 		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
   984 
   985 		while (srcePoint.iY < aSourceRect.iBr.iY)
   986 			{
   987 			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos);
   988 			aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask);
   989 
   990 			fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask);
   991 
   992 			destY++;
   993 			++srcePoint.iY;
   994 			}
   995 		return;
   996 		}
   997 
   998 	TPoint ditherOrigin(aDitherOrigin + aDest);
   999 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
  1000 	const TDrawMode drawMode = aInvertMask ? EDrawModeAND : EDrawModeANDNOT;
  1001 
  1002 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
  1003 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
  1004 	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
  1005 
  1006 	TLineScanningPosition lineScanPos2(aSourceBase);
  1007 
  1008 	//scanline modifications required if using shadows, different modes, bits per pixel less than 8
  1009 	if ((!aShadowMode) && (dispMode == aSourceBitmap->DisplayMode()) && (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8))
  1010 		{
  1011 		TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode);
  1012 		TUint32* slptr=NULL;
  1013 		//mask scanline modifications required for EInvertPen, different screen modes
  1014 		if ((drawMode != EDrawModeANDNOT) && (dispMode == aMaskBitmap->DisplayMode()))
  1015 			{
  1016 			TUint32* scanLineBufferMask = NULL;
  1017 			//stride jumping not possible with compressed bitmaps
  1018 			if (aSourceBitmap->IsCompressed() || aMaskBitmap->IsCompressed())
  1019 				{
  1020 				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
  1021 					{
  1022 		 			scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
  1023 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
  1024 		 			scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
  1025 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
  1026 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
  1027 					}
  1028 				}
  1029 			else
  1030 				{
  1031 				TUint strideSrc = aSourceBitmap->DataStride();
  1032 				TUint strideMask = aMaskBitmap->DataStride();
  1033 				TUint32* lastScanLineSrc = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
  1034 				TUint32* lastScanLineMask = aMaskBitmap->ScanLineAddress(aMaskBase,aSourceRect.iBr.iY-1);
  1035 
  1036 				while (srcePoint.iY < aSourceRect.iBr.iY)
  1037 					{
  1038 		 			scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
  1039 		 			scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
  1040 
  1041 		 			do
  1042 		 				{
  1043 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
  1044 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
  1045 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
  1046 						destY++,srcePoint.iY++,ditherOrigin.iY++;
  1047 		 				}
  1048 		 			while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLineSrc) && (scanLineBufferMask < lastScanLineMask)
  1049 		 				&& ((scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + strideSrc))>(TUint32*)0)
  1050 		 				&& ((scanLineBufferMask = (TUint32*)((TUint8*)scanLineBufferMask + strideMask))>(TUint32*)0)
  1051 		 				);
  1052 					}
  1053 				}
  1054 			}
  1055 		else
  1056 			{
  1057 			TUint32* scanLineBufferPtr = NULL;
  1058 			//stride jumping not possible with compressed bitmaps
  1059 			if (aSourceBitmap->IsCompressed())
  1060 				{
  1061 				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
  1062 					{
  1063 		 			scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
  1064 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
  1065 					aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode, aMaskBase, lineScanPosMask);
  1066 					::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
  1067 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
  1068 					drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
  1069 					}
  1070 				}
  1071 			else
  1072 				{
  1073 				TUint stride = aSourceBitmap->DataStride();
  1074 				TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
  1075 				while (srcePoint.iY < aSourceRect.iBr.iY)
  1076 					{
  1077 		 			scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
  1078 		 			do
  1079 		 				{
  1080 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
  1081 						aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,aMaskBase, lineScanPosMask);
  1082 						::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
  1083 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
  1084 						drawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,EDrawModeXOR);
  1085 						destY++,srcePoint.iY++,ditherOrigin.iY++;
  1086 		 				}
  1087 					while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBufferPtr < lastScanLine)
  1088 						&& ((scanLineBufferPtr = (TUint32*)((TUint8*)scanLineBufferPtr + stride))>(TUint32*)0));
  1089 					}
  1090 				}
  1091 			}
  1092 		}
  1093 	else
  1094 		{
  1095 		for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
  1096 			{
  1097 			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,
  1098 								dispMode,aSourceBase,lineScanPos);
  1099 
  1100 			if (aShadowMode)
  1101 				{
  1102 				drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1103 				drawDevice->ShadowBuffer(width,scanLineBuffer);
  1104 				drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
  1105 				}
  1106 
  1107 			drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
  1108 
  1109 			aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,
  1110 									 aMaskBase, lineScanPosMask);
  1111 			::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask,
  1112 						   aMaskBase, dispMode);
  1113 			drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
  1114 
  1115 			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,dispMode,
  1116 							   aSourceBase,lineScanPos2);
  1117 
  1118 			if(aShadowMode)
  1119 				{
  1120 				drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1121 				drawDevice->ShadowBuffer(width,scanLineBuffer);
  1122 				drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
  1123 				}
  1124 
  1125 			drawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,EDrawModeXOR);
  1126 			}
  1127 		}
  1128 	}
  1129 
  1130 void CFbsBitGc::DoBitBltMaskedNonFlicker(const TPoint& aDest,
  1131 										 CBitwiseBitmap* aSourceBitmap,
  1132 										 TUint32* aSourceBase,
  1133 										 const TRect& aSourceRect,
  1134 										 CBitwiseBitmap* aMaskBitmap,
  1135 										 TUint32* aMaskBase,
  1136 										 TBool aInvertMask,
  1137 										 const TPoint& aDitherOrigin,
  1138 										 TInt aShadowMode)
  1139 	{
  1140 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
  1141 
  1142 	const TInt width = aSourceRect.Width();
  1143 	TInt destY = aDest.iY;
  1144 	TPoint srcePoint(aSourceRect.iTl);
  1145 
  1146 	TLineScanningPosition lineScanPos(aSourceBase);
  1147 	TLineScanningPosition lineScanPosMask(aMaskBase);
  1148 
  1149 	const TDisplayMode srcFormat = aSourceBitmap->DisplayMode();
  1150 	const TDisplayMode maskFormat = aMaskBitmap->DisplayMode();
  1151 	
  1152 	if (aMaskBitmap->IsCompressed()) 
  1153        { 
  1154        HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4); 
  1155        if (!hBuf) 
  1156           return; // Out of memory so do not draw anything 
  1157        lineScanPosMask.iScanLineBuffer = hBuf; 
  1158        } 
  1159 
  1160 	TAny* interface=NULL;
  1161 	if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) &&
  1162 		maskFormat == EGray2 &&
  1163 		!aShadowMode &&
  1164 		aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
  1165 		aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
  1166 		drawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
  1167 		{
  1168 		// Parameters allow optimised code path
  1169 		TInt length = width;
  1170 		TUint32* srcPtr=NULL;
  1171 		TUint32* maskPtr=NULL;
  1172 		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
  1173 
  1174 		while (srcePoint.iY < aSourceRect.iBr.iY)
  1175 			{
  1176 			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos);
  1177 			aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask);
  1178 
  1179 			fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask);
  1180 
  1181 			destY++;
  1182 			++srcePoint.iY;
  1183 			}
  1184 
  1185 		return;
  1186 		}
  1187 
  1188 	TPoint ditherOrigin(aDitherOrigin + aDest);
  1189 
  1190 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
  1191 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
  1192 	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
  1193 
  1194 	TUint32* bitBltBuffer = (TUint32*)iDevice->iBitBltMaskedBuffer;
  1195 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
  1196 	const TInt bufferBytes = CFbsBitmap::ScanLineLength(width, dispMode);
  1197 	TUint32* scanLineCopy = (TUint32*) new TUint8[bufferBytes];
  1198 
  1199 	TLineScanningPosition lineScanPos2(aSourceBase);
  1200 	for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
  1201 		{
  1202 		drawDevice->ReadLine(aDest.iX,destY,width,bitBltBuffer,dispMode);
  1203 		aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,dispMode,
  1204 								   aSourceBase,lineScanPos);
  1205 
  1206 		if (scanLineCopy)
  1207 			{
  1208 			Mem::Copy(scanLineCopy,scanLineBuffer,bufferBytes);
  1209 			}
  1210 
  1211 		if (aShadowMode)
  1212 			{
  1213 			drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1214 			drawDevice->ShadowBuffer(width,scanLineBuffer);
  1215 			drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
  1216 			}
  1217 
  1218 		XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1219 
  1220 		aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,
  1221 								 aMaskBase,lineScanPosMask);
  1222 		::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask,
  1223 					   aMaskBase, dispMode);
  1224 
  1225 		if (!aInvertMask)
  1226 			InvertBuffer(scanLineBuffer,bufferBytes);
  1227 		AndBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1228 
  1229 		// Slow call when memory low?
  1230 		TUint32* scanLine;
  1231 		if (!scanLineCopy)
  1232 			{
  1233 			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,
  1234 									   dispMode,aSourceBase,lineScanPos2);
  1235 			scanLine = scanLineBuffer;
  1236 			}
  1237 		else
  1238 			scanLine = scanLineCopy;
  1239 
  1240 		if(aShadowMode)
  1241 			{
  1242 			drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1243 			drawDevice->ShadowBuffer(width,scanLine);
  1244 			drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
  1245 			}
  1246 
  1247 		XorBuffers(bitBltBuffer,scanLine,bufferBytes);
  1248 
  1249 		drawDevice->WriteLine(aDest.iX,destY,width,bitBltBuffer,iDrawMode);
  1250 		}
  1251 	if (scanLineCopy)
  1252 		{
  1253 		delete[] scanLineCopy;
  1254 		}
  1255 	}
  1256 
  1257 void CFbsBitGc::DoBitBltMaskedNonFlickerSolid(const TPoint& aDest,
  1258 											  CBitwiseBitmap* aSourceBitmap,
  1259 											  TUint32* aSourceBase,
  1260 											  const TRect& aSourceRect,
  1261 											  CBitwiseBitmap* aMaskBitmap,
  1262 											  TUint32* aMaskBase,
  1263 											  TBool aInvertMask,
  1264 											  const TPoint& aDitherOrigin,
  1265 											  TInt aShadowMode)
  1266 	{
  1267 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
  1268 	const TInt width = aSourceRect.Width();
  1269 	TPoint ditherOrigin(aDitherOrigin + aDest);
  1270 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
  1271 	TInt destY = aDest.iY;
  1272 	TPoint srcePoint(aSourceRect.iTl);
  1273 
  1274 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
  1275 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
  1276 	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
  1277 
  1278 	TUint32* bitBltBuffer = (TUint32*)iDevice->iBitBltMaskedBuffer;
  1279 	TUint32* backgroundBuffer = (TUint32*)(iDevice->iBitBltMaskedBuffer + scanLineBytes);
  1280 	const TInt bufferBytes = CFbsBitmap::ScanLineLength(width, dispMode);
  1281 
  1282 	drawDevice->WriteRgbMulti(aDest.iX,aDest.iY,width,1,iBrushColor,iDrawMode);
  1283 	drawDevice->ReadLine(aDest.iX,destY,width,backgroundBuffer,dispMode);
  1284 
  1285 	TLineScanningPosition lineScanPos(aSourceBase);
  1286 	TLineScanningPosition lineScanPos2(aSourceBase);
  1287 	TLineScanningPosition lineScanPosMask(aMaskBase);
  1288 
  1289 	for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++,ditherOrigin.iY++)
  1290 		{
  1291 		Mem::Copy(bitBltBuffer,backgroundBuffer,bufferBytes);
  1292 
  1293 		aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,dispMode,
  1294 								   aSourceBase,lineScanPos);
  1295 		XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1296 
  1297 		aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse,ditherOrigin,dispMode,
  1298 								 aMaskBase,lineScanPosMask);
  1299 		::TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask,
  1300 					   aMaskBase, dispMode);
  1301 
  1302 		if (!aInvertMask)
  1303 			InvertBuffer(scanLineBuffer,bufferBytes);
  1304 		AndBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1305 		aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,ETrue,ditherOrigin,
  1306 								   dispMode,aSourceBase,lineScanPos2);
  1307 
  1308 		XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1309 
  1310 		if(aShadowMode)
  1311 			drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1312 
  1313 		drawDevice->WriteLine(aDest.iX,destY,width,bitBltBuffer,iDrawMode);
  1314 
  1315 		if(aShadowMode)
  1316 			drawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
  1317 		}
  1318 	}
  1319 
  1320 void CFbsBitGc::DoBitBltMaskedNonFlickerPatterned(const TPoint& aDest,
  1321 												  CBitwiseBitmap* aSourceBitmap,
  1322 												  TUint32* aSourceBase,
  1323 												  const TRect& aSourceRect,
  1324 												  CBitwiseBitmap* aMaskBitmap,
  1325 												  TUint32* aMaskBase,
  1326 												  TBool aInvertMask,
  1327 												  const TPoint& aDitherOrigin,
  1328 												  TInt aShadowMode)
  1329 	{
  1330 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
  1331 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
  1332 
  1333 	drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1334 
  1335 	iBrushBitmap.BeginDataAccess();
  1336 	CBitwiseBitmap* brushBitmap = iBrushBitmap.Address();
  1337 	BG_ASSERT_ALWAYS(iBrushUsed, EBitgdiPanicInvalidBitmap);
  1338 	BG_ASSERT_ALWAYS(brushBitmap != NULL, EBitgdiPanicInvalidBitmap);
  1339 
  1340 	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
  1341 	TUint32* brushData = iBrushBitmap.DataAddress();
  1342 	TPoint brushSourcePoint(aDest - iBrushOrigin - iOrigin);
  1343 	const TSize brushSize(iBrushBitmap.SizeInPixels());
  1344 	if (brushSourcePoint.iX < 0 || brushSourcePoint.iX >= brushSize.iWidth)
  1345 		brushSourcePoint.iX %= brushSize.iWidth;
  1346 	if (brushSourcePoint.iX < 0)
  1347 		brushSourcePoint.iX += brushSize.iWidth;
  1348 
  1349 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
  1350 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
  1351 	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
  1352 
  1353 	TUint32* bitBltBuffer = (TUint32*)iDevice->iBitBltMaskedBuffer;
  1354 	TPtr8 bitBltDes(iDevice->iBitBltMaskedBuffer, scanLineBytes, scanLineBytes);
  1355 
  1356 	TInt widthRemaining = aSourceRect.Width();
  1357 	TPoint sourcePoint(aSourceRect.iTl);
  1358 	TInt destX = aDest.iX;
  1359 
  1360 	TInt width = Min(widthRemaining,brushSize.iWidth);
  1361 
  1362 	if (brushSourcePoint.iX + widthRemaining > brushSize.iWidth)
  1363 		width = brushSize.iWidth - brushSourcePoint.iX;
  1364 
  1365 	while (widthRemaining > 0)
  1366 		{
  1367 		TInt destY = aDest.iY;
  1368 		sourcePoint.iY = aSourceRect.iTl.iY;
  1369 		brushSourcePoint.iY = aDest.iY - iBrushOrigin.iY - iOrigin.iY;
  1370 		TPoint ditherOrigin(aDitherOrigin + TPoint(destX,aDest.iY));
  1371 		const TInt bufferBytes = CFbsBitmap::ScanLineLength(width, dispMode);
  1372 
  1373 		TLineScanningPosition lineScanPosBrush(brushData);
  1374 		TLineScanningPosition lineScanPosMask(aMaskBase);
  1375 		TLineScanningPosition lineScanPosSrc(aSourceBase);
  1376 		TLineScanningPosition lineScanPosSrc2(aSourceBase);
  1377 
  1378 		for ( ;sourcePoint.iY < aSourceRect.iBr.iY;
  1379 			   destY++,sourcePoint.iY++,ditherOrigin.iY++,brushSourcePoint.iY++)
  1380 			{
  1381 			brushBitmap->GetScanLine(bitBltDes,brushSourcePoint,width,ETrue,ditherOrigin,
  1382 									 dispMode,brushData,lineScanPosBrush);
  1383 			aSourceBitmap->GetScanLine(scanLineDes,sourcePoint,width,ETrue,ditherOrigin,
  1384 									   dispMode,aSourceBase,lineScanPosSrc);
  1385 			XorBuffers(bitBltBuffer,scanLineBuffer,scanLineBytes);
  1386 
  1387 			aMaskBitmap->GetScanLine(scanLineDes,sourcePoint,width,EFalse,ditherOrigin,
  1388 									 dispMode,aMaskBase,lineScanPosMask);
  1389 			::TileScanLine(scanLineDes, width, sourcePoint, aMaskBitmap, lineScanPosMask,
  1390 						   aMaskBase, dispMode);
  1391 
  1392 			if (!aInvertMask)
  1393 				InvertBuffer(scanLineBuffer,bufferBytes);
  1394 			AndBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1395 
  1396 			aSourceBitmap->GetScanLine(scanLineDes,sourcePoint,width,ETrue,ditherOrigin,
  1397 									   dispMode,aSourceBase,lineScanPosSrc2);
  1398 			XorBuffers(bitBltBuffer,scanLineBuffer,bufferBytes);
  1399 
  1400 			drawDevice->WriteLine(destX,destY,width,bitBltBuffer,iDrawMode);
  1401 			}
  1402 
  1403 		widthRemaining -= width;
  1404 		sourcePoint.iX += width;
  1405 		brushSourcePoint.iX += width;
  1406 		destX += width;
  1407 
  1408 		width = Min(widthRemaining,brushSize.iWidth);
  1409 		}
  1410 	if (brushRasterizer)
  1411 		{
  1412 		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
  1413 		}
  1414 	iBrushBitmap.EndDataAccess(ETrue);
  1415 	}
  1416 
  1417 void CFbsBitGc::DoBitBltAlpha(const TPoint& aDest,CBitwiseBitmap* aSourceBitmap,
  1418 							  TUint32* aSourceBase,const TRect& aSourceRect,
  1419 							  CBitwiseBitmap* aMaskBitmap,TUint32* aMaskBase,
  1420 							  const TPoint& aAlphaPoint,TInt aShadowMode, TBool aInvertMask)
  1421 	{
  1422 	MFastBlend* fastBlend=NULL;
  1423 	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
  1424 		{
  1425 		if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
  1426 							aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aAlphaPoint, aInvertMask,
  1427 							iDrawMode, aShadowMode)==KErrNone)
  1428 			{
  1429 			return;
  1430 			}
  1431 		}
  1432 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
  1433 
  1434 	const TPoint KZeroPoint(0,0);
  1435 	const TInt KScanLineLength = 256;
  1436 	const TInt KRgbSize = 4;
  1437 
  1438 	TUint8 srceRgbBuffer[KScanLineLength * KRgbSize];
  1439 	TUint8 maskBuffer[KScanLineLength];
  1440 	TUint8* srceRgbBufferPtr(srceRgbBuffer);
  1441 
  1442 	TPtr8 srceRgbDes(srceRgbBuffer,KScanLineLength * KRgbSize,KScanLineLength * KRgbSize);
  1443 	TPtr8 maskDes(maskBuffer,KScanLineLength,KScanLineLength);
  1444 
  1445 	drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1446 
  1447 	const TSize sourceSize = aSourceBitmap->SizeInPixels();
  1448 	// Convert negative or large offsets into sensible positive ones.
  1449 	TPoint alphaOffset(aAlphaPoint.iX % sourceSize.iWidth, aAlphaPoint.iY % sourceSize.iHeight);
  1450 	if ( alphaOffset.iX < 0 ) 
  1451 		alphaOffset.iX += sourceSize.iWidth;
  1452 	if ( alphaOffset.iY < 0 ) 
  1453 		alphaOffset.iY += sourceSize.iHeight;
  1454 	
  1455 	TInt srceY = aSourceRect.iTl.iY;
  1456 	TInt destY = aDest.iY;
  1457 	TInt alphaY = alphaOffset.iY;
  1458 	
  1459 	TLineScanningPosition lineScanPosSrc(aSourceBase);
  1460 	TLineScanningPosition lineScanPosMask(aMaskBase);
  1461 
  1462 	TDisplayMode sourceMode = aSourceBitmap->DisplayMode();
  1463 
  1464 	if (aMaskBitmap->IsCompressed())
  1465 		{
  1466 		HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
  1467 		if (!hBuf)
  1468 			{
  1469 			return;  // Out of memory so do not draw anything
  1470 			}
  1471 		lineScanPosMask.iScanLineBuffer = hBuf;
  1472 		}
  1473 
  1474 	TAny* interface=NULL;
  1475 	if ( (sourceMode == EColor16MU || sourceMode == EColor64K) &&
  1476 			aMaskBitmap->DisplayMode() == EGray256 && // ensure a monochrome mask isn't passed in as an alpha channel
  1477 			aSourceBitmap->SizeInPixels().iWidth  <= aMaskBitmap->SizeInPixels().iWidth &&
  1478 			aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
  1479 			drawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
  1480 		{
  1481 		TInt length = aSourceRect.Width();
  1482 		const TInt srceX = aSourceRect.iTl.iX;				
  1483 		const TInt alphaX = alphaOffset.iX;
  1484 		const TInt destX = aDest.iX;
  1485 		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
  1486 
  1487 		while (srceY < aSourceRect.iBr.iY)
  1488 			{
  1489 			TUint32* srcPtr;
  1490 			TUint32* maskPtr;
  1491 			TPoint srcPoint(srceX, srceY);
  1492 			TPoint maskPoint(alphaX, alphaY);
  1493 
  1494 			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcPoint, aSourceBase, lineScanPosSrc);
  1495 			aMaskBitmap->GetScanLinePtr(maskPtr, length, maskPoint, aMaskBase, lineScanPosMask);
  1496 
  1497 			fastBlit->WriteAlphaLineEx(destX,destY,length,srceX,srcPtr,sourceMode,alphaX,maskPtr,MAlphaBlend::EShdwBefore);
  1498 
  1499 			srceY++;
  1500 			destY++;
  1501 			alphaY++;
  1502 			}
  1503 		return;
  1504 		}
  1505 
  1506 	const TBool useScanLinePtr = ((!aShadowMode) && (EColor16MA == aSourceBitmap->DisplayMode()));
  1507 	TUint32* slptr=NULL;
  1508 	TUint offset = 0;
  1509 	TDisplayMode srcMode = ERgb;
  1510 	
  1511 	while (srceY < aSourceRect.iBr.iY)
  1512 		{
  1513 		TInt srceX = aSourceRect.iTl.iX;
  1514 		TInt destX = aDest.iX;
  1515 		TInt alphaX = alphaOffset.iX;
  1516 		
  1517 		while (srceX < aSourceRect.iBr.iX)
  1518 			{
  1519 			TPoint srcePoint(srceX,srceY);
  1520 			TPoint alphaPoint(alphaX,alphaY);
  1521 			const TInt width = Min(KScanLineLength,aSourceRect.iBr.iX - srceX);
  1522 
  1523 			if (useScanLinePtr)
  1524 				{
  1525 				offset = MemoryOffsetForPixelPitch(srceX, EColor16MU);
  1526 				srceRgbBufferPtr = (TUint8*)GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPosSrc, offset);
  1527 				}
  1528 			else
  1529 				{
  1530 				aSourceBitmap->GetScanLine(srceRgbDes,srcePoint,width,EFalse,KZeroPoint,
  1531 								   srcMode,aSourceBase,lineScanPosSrc);
  1532 				}
  1533 
  1534 			aMaskBitmap->GetScanLine(maskDes,alphaPoint,width,EFalse,KZeroPoint,
  1535 									 EGray256,aMaskBase,lineScanPosMask);
  1536 			::TileScanLine(maskDes, width, alphaPoint, aMaskBitmap, lineScanPosMask,
  1537 						   aMaskBase, EGray256);
  1538 			// aInvertMask is not used for alpha channels (EGray256 mask)
  1539 			if (aInvertMask && aMaskBitmap->DisplayMode() != EGray256)
  1540 				{
  1541 				for (TInt i = 0; i < width; ++i)
  1542 					maskBuffer[i] = ~maskBuffer[i];
  1543 				}
  1544 			drawDevice->WriteRgbAlphaLine(destX,destY,width,srceRgbBufferPtr,maskBuffer,iDrawMode);
  1545 
  1546 			srceX += KScanLineLength;
  1547 			destX += KScanLineLength;
  1548 			alphaX += KScanLineLength;
  1549 			}
  1550 
  1551 		srceY++;
  1552 		destY++;
  1553 		alphaY++;
  1554 		}
  1555 	}
  1556 
  1557 /**
  1558 The method performs an alpha blending of the source data - aSrcBmp1 and aSrcBmp2, using
  1559 the data from aAlphaBmp as an alpha blending factor.
  1560 @internalComponent
  1561 @see CFbsBitGc::AlphaBlendBitmaps.
  1562 */
  1563 void CFbsBitGc::DoBitBltAlpha(const TPoint& aDestPt,
  1564 							  const CBitwiseBitmap* aSrcBmp1,
  1565 							  TUint32* aSrcBmpDataAddr1,
  1566 							  const CBitwiseBitmap* aSrcBmp2,
  1567 							  TUint32* aSrcBmpDataAddr2,
  1568 							  const CBitwiseBitmap* aAlphaBmp,
  1569 							  TUint32* aAlphaBmpDataAddr,
  1570 							  const TRect& aSrcRect1,
  1571 							  const TPoint& aSrcPt2,
  1572 							  const TPoint& aAlphaPt,
  1573 							  TInt aShadowMode)
  1574 	{
  1575 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
  1576 #ifdef _DEBUG
  1577 	TRect deviceDestRect;
  1578 	drawDevice->GetDrawRect(deviceDestRect);
  1579 #endif
  1580 	//Check the destination point.
  1581 	BG_ASSERT_DEBUG(aDestPt.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
  1582 	BG_ASSERT_DEBUG(aDestPt.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
  1583 	BG_ASSERT_DEBUG((aDestPt.iX + aSrcRect1.Width()) <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
  1584 	BG_ASSERT_DEBUG((aDestPt.iY + aSrcRect1.Height()) <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
  1585 
  1586 	const TPoint KZeroPoint(0,0);
  1587 	const TInt KScanLineLength = 256;//128 is not enough to fill buffer for 16MA and 16MU display modes
  1588 	const TInt KRgbSize = 4;
  1589 
  1590 	TUint8 srceRgbBuffer1[KScanLineLength * KRgbSize];
  1591 	TUint8 srceBuffer2[KScanLineLength * KRgbSize];
  1592 	TUint8 alphaBuffer[KScanLineLength];
  1593 
  1594 	TPtr8 srceRgbDes1(srceRgbBuffer1,KScanLineLength * KRgbSize,KScanLineLength * KRgbSize);
  1595 	TPtr8 srceDes2(srceBuffer2,KScanLineLength * KRgbSize,KScanLineLength * KRgbSize);
  1596 	TPtr8 alphaDes(alphaBuffer,KScanLineLength,KScanLineLength);
  1597 
  1598 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
  1599 	drawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(aShadowMode));
  1600 
  1601 	TInt srceY1 = aSrcRect1.iTl.iY;
  1602 	TInt srceY2 = aSrcPt2.iY;
  1603 	TInt alphaY = aAlphaPt.iY;
  1604 	TInt destY = aDestPt.iY;
  1605 
  1606 	TLineScanningPosition lineScanPosSrc1(aSrcBmpDataAddr1);
  1607 	TLineScanningPosition lineScanPosSrc2(aSrcBmpDataAddr2);
  1608 	TLineScanningPosition lineScanPosAlpha(aAlphaBmpDataAddr);
  1609 
  1610 	while (srceY1 < aSrcRect1.iBr.iY)
  1611 		{
  1612 		TInt srceX1 = aSrcRect1.iTl.iX;
  1613 		TInt srceX2 = aSrcPt2.iX;
  1614 		TInt alphaX = aAlphaPt.iX;
  1615 		TInt destX = aDestPt.iX;
  1616 
  1617 		while (srceX1 < aSrcRect1.iBr.iX)
  1618 			{
  1619 			TPoint srcePoint1(srceX1,srceY1);
  1620 			TPoint srcePoint2(srceX2,srceY2);
  1621 			TPoint alphaPoint(alphaX,alphaY);
  1622 			const TInt width = Min(KScanLineLength,aSrcRect1.iBr.iX - srceX1);
  1623 
  1624 			aSrcBmp1->GetScanLine(srceRgbDes1,srcePoint1,width,EFalse,KZeroPoint,EColor16MU,
  1625 								  aSrcBmpDataAddr1,lineScanPosSrc1);
  1626 			aSrcBmp2->GetScanLine(srceDes2,srcePoint2,width,EFalse,KZeroPoint,dispMode,
  1627 								  aSrcBmpDataAddr2,lineScanPosSrc2);
  1628 			aAlphaBmp->GetScanLine(alphaDes,alphaPoint,width,EFalse,KZeroPoint,EGray256,
  1629 								   aAlphaBmpDataAddr,lineScanPosAlpha);
  1630 			::TileScanLine(alphaDes, width, alphaPoint, aAlphaBmp, lineScanPosAlpha, aAlphaBmpDataAddr, EGray256);
  1631 
  1632 			drawDevice->WriteRgbAlphaLine(destX,
  1633 										  destY,
  1634 										  width,
  1635 										  srceRgbBuffer1,
  1636 										  srceBuffer2,
  1637 										  alphaBuffer,
  1638 										  iDrawMode);
  1639 
  1640 			srceX1 += KScanLineLength;
  1641 			srceX2 += KScanLineLength;
  1642 			alphaX += KScanLineLength;
  1643 			destX += KScanLineLength;
  1644 			}
  1645 
  1646 		srceY1++;
  1647 		srceY2++;
  1648 		alphaY++;
  1649 		destY++;
  1650 		}
  1651 	}
  1652 
  1653 /**
  1654 The method performs an alpha blending of the source data - aSrcBmp1 and aSrcBmp2, using
  1655 the data from aAlphaBmp as an alpha blending factor.
  1656 The formula used for that, is:
  1657 (C1 * A + C2 * (255 - A)) / 255, where:
  1658 - C1 - a pixel from aSrcBmp1;
  1659 - C2 - a pixel from aSrcBmp2;
  1660 - A  - a pixel from aAlphaBmp;
  1661 The content of source and alpha bitmap is preserved.
  1662 The calculated alpha blended pixels are written to the destination - the screen or a bitmap.
  1663 @publishedAll
  1664 @released
  1665 @param aDestPt Position in the target the result should be drawn to.
  1666 @param aSrcBmp1 A pointer to the source bitmap 1.
  1667 @param aSrcBmp2 A pointer to the source bitmap 2.
  1668 @param aAlphaBmp A pointer to the bitmap used as an alpha blending factor.
  1669 @param aSrcRect1 A part of bitmap 1 that should be used as a source for the alpha blending.
  1670 @param aSrcPt2 Position of the first pixel in bitmap 2 that should be used as a source
  1671                for the alpha blending. The size of the area is the same as the
  1672 			   bitmap 1 area - aSrcRect1 parameter.
  1673 @param aAlphaPt Position of the first pixel in the alpha bitmap that should be used as a source
  1674                 for the alpha blending. The size of the area is the same as the
  1675                 bitmap 1 area - aSrcRect1 parameter.
  1676 @pre !aSrcRect1.IsEmpty()
  1677 @pre aSrcBmp1 != NULL
  1678 @pre aSrcBmp1->Handle() != NULL
  1679 @pre aSrcBmp2 != NULL
  1680 @pre aSrcBmp2->Handle() != NULL
  1681 @pre aAlphaBmp != NULL
  1682 @pre aAlphaBmp->Handle() != NULL
  1683 @pre aAlphaBmp->DisplayMode() <= EGray256
  1684 @return KErrNone If the call is successful, KErrArgument otherwise.
  1685 */
  1686 EXPORT_C  TInt CFbsBitGc::AlphaBlendBitmaps(const TPoint& aDestPt,
  1687 											const CFbsBitmap* aSrcBmp1,
  1688 											const CFbsBitmap* aSrcBmp2,
  1689 											const TRect& aSrcRect1,
  1690 											const TPoint& aSrcPt2,
  1691 											const CFbsBitmap* aAlphaBmp,
  1692 											const TPoint& aAlphaPt)
  1693 	{
  1694 	//Check the bitmap pointers and handles. Check the CFbsDevice instance -
  1695 	//it shouldn't be NULL - that means - CFbsBitGc instance (this pointer)
  1696 	//should be created either using CFbsDevice::CreateContext() or CFbsBitGc::Activate() -
  1697 	//before the method was called.
  1698 	if(!aSrcBmp1 || !aSrcBmp1->Handle() || !aSrcBmp2 || !aSrcBmp2->Handle() ||
  1699 	   !aAlphaBmp || !aAlphaBmp->Handle() || CheckDevice(aSrcRect1))
  1700 		{
  1701 		return KErrArgument;
  1702 		}
  1703 		
  1704 	aSrcBmp1->BeginDataAccess();
  1705 	aSrcBmp2->BeginDataAccess();
  1706 	aAlphaBmp->BeginDataAccess();
  1707 		
  1708 	//Check display mode of the alpha bitmap. Bitmaps which display mode is greater than
  1709 	//EGray256 can't be used as alpha bitmaps.
  1710 	if(aAlphaBmp->DisplayMode() > EGray256)
  1711 		{
  1712 		aSrcBmp1->EndDataAccess(ETrue);
  1713 		aSrcBmp2->EndDataAccess(ETrue);
  1714 		aAlphaBmp->EndDataAccess(ETrue);
  1715 		return KErrArgument;
  1716 		}
  1717 	//Check source rect 1. Bitmap 1 must contain the whole source rect 1.
  1718 	TRect srcRect1(aSrcRect1);
  1719 	TRect area1(aSrcBmp1->SizeInPixels());
  1720 	srcRect1.Intersection(area1);
  1721 	if(srcRect1 != aSrcRect1)
  1722 		{
  1723 		aSrcBmp1->EndDataAccess(ETrue);
  1724 		aSrcBmp2->EndDataAccess(ETrue);
  1725 		aAlphaBmp->EndDataAccess(ETrue);
  1726 		return KErrArgument;
  1727 		}
  1728 	//Create and check source rect 2. Bitmap 2 must contain the whole source rect 2.
  1729 	TRect srcRect2(TSize(aSrcRect1.Width(), aSrcRect1.Height()));
  1730 	srcRect2.Move(aSrcPt2);
  1731 	TRect srcRect2t(srcRect2);
  1732 	TRect area2(aSrcBmp2->SizeInPixels());
  1733 	srcRect2.Intersection(area2);
  1734 	if(srcRect2 != srcRect2t)
  1735 		{
  1736 		aSrcBmp1->EndDataAccess(ETrue);
  1737 		aSrcBmp2->EndDataAccess(ETrue);
  1738 		aAlphaBmp->EndDataAccess(ETrue);
  1739 		return KErrArgument;
  1740 		}
  1741 	//Calculate the destination rect
  1742 	TPoint destPt(aDestPt + iOrigin);
  1743 	TRect destRect(destPt, srcRect1.Size());
  1744 	TPoint offset(srcRect1.iTl - destPt);
  1745 	TPoint offset2(srcRect2.iTl - destPt);
  1746 	TRect clippedDestRect(destRect);
  1747 	AddRect(clippedDestRect);
  1748 	if(UserClipRect(clippedDestRect))
  1749 		{
  1750 		aSrcBmp1->EndDataAccess(ETrue);
  1751 		aSrcBmp2->EndDataAccess(ETrue);
  1752 		aAlphaBmp->EndDataAccess(ETrue);
  1753 		return KErrArgument;
  1754 		}
  1755 	//Save current shadow mode
  1756 	TInt8 shadowMode = iShadowMode;
  1757 	iShadowMode = CFbsDrawDevice::ENoShadow;
  1758 	//Setup the device and prevent the bitmaps from being cleaned away by client code.
  1759 	//Drawing begins.
  1760 	SetupDevice();
  1761 	iDevice->DrawingBegin();
  1762 	CBitwiseBitmap* srcBmp1 = ((CFbsBitGcBitmap*)aSrcBmp1)->Address();
  1763 	CBitwiseBitmap* srcBmp2 = ((CFbsBitGcBitmap*)aSrcBmp2)->Address();
  1764 	CBitwiseBitmap* alphaBmp = ((CFbsBitGcBitmap*)aAlphaBmp)->Address();
  1765 	BG_ASSERT_DEBUG(srcBmp1, EBitgdiPanicInvalidBitmap);
  1766 	BG_ASSERT_DEBUG(srcBmp2, EBitgdiPanicInvalidBitmap);
  1767 	BG_ASSERT_DEBUG(alphaBmp, EBitgdiPanicInvalidBitmap);
  1768 
  1769 	TUint32* srcDataAddr1 = aSrcBmp1->DataAddress();
  1770 	TUint32* srcDataAddr2 = aSrcBmp2->DataAddress();
  1771 	TUint32* alphaDataAddr = aAlphaBmp->DataAddress();
  1772 
  1773 	CFbsRasterizer* rasterizer1 = PrepareRasterizerForExtendedBitmap(*aSrcBmp1, clippedDestRect, offset);
  1774 	CFbsRasterizer* rasterizer2 = PrepareRasterizerForExtendedBitmap(*aSrcBmp2, clippedDestRect, offset2);
  1775 	CFbsRasterizer* alphaRasterizer;
  1776 	if (aAlphaPt.iX >= 0 && aAlphaPt.iY >= 0
  1777 		&& aAlphaPt.iX + aSrcRect1.Width() <= aAlphaBmp->SizeInPixels().iWidth
  1778 		&& aAlphaPt.iY + aSrcRect1.Height() <= aAlphaBmp->SizeInPixels().iHeight)
  1779 		{
  1780 		// Alpha blending bitmap is not tiled. Pass same region of interest as source bitmaps to rasterizer.
  1781 		alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp, clippedDestRect, aAlphaPt - destPt);
  1782 		}
  1783 	else
  1784 		{
  1785 		// Alpha blending bitmap is tiled. Do not pass any region of interest to rasterizer.
  1786 		alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp);
  1787 		}
  1788 
  1789 	//For each region - find the clipping rect and draw
  1790 	TInt limit = iDefaultRegionPtr->Count();
  1791 	CGraphicsAccelerator* ga = GraphicsAccelerator();
  1792 	// Code for Graphics Accelerated Drawing
  1793 	if(ga && (shadowMode == CFbsDrawDevice::ENoShadow))
  1794 		{
  1795 		TInt gaOperationResult = KErrUnknown;
  1796 		TAcceleratedBitmapSpec srcBmp1Spec(const_cast<CFbsBitmap*>(aSrcBmp1));
  1797 		TAcceleratedBitmapSpec srcBmp2Spec(const_cast<CFbsBitmap*>(aSrcBmp2));
  1798 		TAcceleratedBitmapSpec alphaBmpSpec(const_cast<CFbsBitmap*>(aAlphaBmp));
  1799 		iDevice->DrawingEnd();
  1800 
  1801 		for(TInt count=0;count<limit;count++)
  1802 			{
  1803 			iClipRect=(*iDefaultRegionPtr)[count];
  1804 			if(!iClipRect.Intersects(clippedDestRect))
  1805 				{
  1806 				continue;
  1807 				}
  1808 			//clippedDestRect was constructed from destRect. destRect was constructed from srcRect1.
  1809 			iClipRect.Intersection(clippedDestRect);
  1810 			TRect clippedSrcRect(iClipRect);
  1811 			clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect1 now.
  1812 			TPoint shift(clippedSrcRect.iTl - srcRect1.iTl);
  1813 			BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
  1814 			BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
  1815 
  1816 			gaOperationResult = ga->Operation(TGopAlphaBlendTwoBitmaps(iClipRect.iTl,srcBmp1Spec,srcBmp2Spec,clippedSrcRect,aSrcPt2 + shift,alphaBmpSpec,aAlphaPt + shift));
  1817 			if(gaOperationResult != KErrNone)
  1818 				break;
  1819 			iDevice->iDrawDevice->UpdateRegion(iClipRect);
  1820 			}
  1821 		if(gaOperationResult == KErrNone)
  1822 			goto finish;
  1823 		iDevice->DrawingBegin();
  1824 		}
  1825 
  1826 	// Code for non- Graphics Accelerated Drawing
  1827 	for(TInt count=0;count<limit;count++)
  1828 		{
  1829 		iClipRect=(*iDefaultRegionPtr)[count];
  1830 		if(!iClipRect.Intersects(clippedDestRect))
  1831 			{
  1832 			continue;
  1833 			}
  1834 		//clippedDestRect was constructed from destRect. destRect was constructed from srcRect1.
  1835 		iClipRect.Intersection(clippedDestRect);
  1836 		TRect clippedSrcRect(iClipRect);
  1837 		clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect1 now.
  1838 		TPoint shift(clippedSrcRect.iTl - srcRect1.iTl);
  1839 		BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
  1840 		BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
  1841 
  1842 		TDrawMode drawMode = iDrawMode;
  1843 		iDrawMode = EDrawModeWriteAlpha; // this is the only mode currently supported
  1844 		DoBitBltAlpha(iClipRect.iTl,
  1845 					  srcBmp1,
  1846 					  srcDataAddr1,
  1847 					  srcBmp2,
  1848 					  srcDataAddr2,
  1849 					  alphaBmp,
  1850 					  alphaDataAddr,
  1851 					  clippedSrcRect,
  1852 					  aSrcPt2 + shift,
  1853 					  aAlphaPt + shift,
  1854 					  shadowMode);
  1855 		iDrawMode = drawMode; // restore the previous draw mode
  1856 
  1857 		iDevice->iDrawDevice->UpdateRegion(iClipRect);
  1858 		}
  1859 
  1860 	//Drawig ends. Restore the previous shadow mode
  1861 	iDevice->DrawingEnd();
  1862 finish:
  1863 	if (rasterizer1)
  1864 		{
  1865 		rasterizer1->EndBitmap(aSrcBmp1->SerialNumber());
  1866 		}
  1867 	if (rasterizer2)
  1868 		{
  1869 		rasterizer2->EndBitmap(aSrcBmp2->SerialNumber());
  1870 		}
  1871 	if (alphaRasterizer)
  1872 		{
  1873 		alphaRasterizer->EndBitmap(aAlphaBmp->SerialNumber());
  1874 		}
  1875 	aSrcBmp1->EndDataAccess(ETrue);
  1876 	aSrcBmp2->EndDataAccess(ETrue);
  1877 	aAlphaBmp->EndDataAccess(ETrue);
  1878 	iShadowMode = shadowMode;
  1879 
  1880 	return KErrNone;
  1881 	}
  1882 
  1883 /**
  1884 The method performs an alpha blending of the source data - aSrcBmp - with the existing image, using
  1885 the data from aAlphaBmp as an alpha blending factor.
  1886 The formula used for that, is:
  1887 (C * A + D * (255 - A)) / 255, where:
  1888 - C - a pixel from aSrcBmp;
  1889 - D - a pixel from the destination;
  1890 - A  - a pixel from aAlphaBmp;
  1891 The content of source and alpha bitmap is preserved.
  1892 The calculated alpha blended pixels are written to the destination - the screen or a bitmap.
  1893 @publishedAll
  1894 @released
  1895 @param aDestPt Position in the target the result should be drawn to.
  1896 @param aSrcBmp A pointer to the source bitmap.
  1897 @param aAlphaBmp A pointer to the bitmap used as an alpha blending factor.
  1898 @param aSrcRect A part of aSrcBmp that should be used as a source for the alpha blending.
  1899 				DISCLAIMER: if aSrcRect is bigger (width and/or height) the behaviour is undefined
  1900 @param aAlphaPt Position of the first pixel in the alpha bitmap that should be used as a source
  1901                 for the alpha blending. The size of the area is
  1902                 the same as the aSrcRect parameter (read DISCLAIMER above).
  1903 @pre !aSrcRect.IsEmpty()
  1904 @pre aSrcBmp != NULL
  1905 @pre aSrcBmp->Handle() != NULL
  1906 @pre aAlphaBmp != NULL
  1907 @pre aAlphaBmp->Handle() != NULL
  1908 @pre aAlphaBmp->DisplayMode() <= EGray256
  1909 @return KErrNone If the call is successfull, KErrArgument otherwise.
  1910 */
  1911 EXPORT_C  TInt CFbsBitGc::AlphaBlendBitmaps(const TPoint& aDestPt,
  1912 											const CFbsBitmap* aSrcBmp,
  1913 											const TRect& aSrcRect,
  1914 											const CFbsBitmap* aAlphaBmp,
  1915 											const TPoint& aAlphaPt)
  1916 	{
  1917 	//Check the bitmap pointers and handles. Check the CFbsDevice instance -
  1918 	//it shouldn't be NULL - that means - CFbsBitGc instance (this pointer)
  1919 	//should be created either using CFbsDevice::CreateContext() or CFbsBitGc::Activate() -
  1920 	//before the method was called.
  1921 	if(!aSrcBmp || !aSrcBmp->Handle() ||
  1922 	   !aAlphaBmp || !aAlphaBmp->Handle() || CheckDevice(aSrcRect))
  1923 		{
  1924 		return KErrArgument;
  1925 		}
  1926 		
  1927 	aSrcBmp->BeginDataAccess();
  1928 	aAlphaBmp->BeginDataAccess();
  1929 		
  1930 	//Check display mode of the alpha bitmap. Bitmaps which display mode is greater than
  1931 	//EGray256 can't be used as alpha bitmaps.
  1932 	if(aAlphaBmp->DisplayMode() > EGray256)
  1933 		{
  1934 		aSrcBmp->EndDataAccess(ETrue);
  1935 		aAlphaBmp->EndDataAccess(ETrue);
  1936 		return KErrArgument;
  1937 		}
  1938 	//Taking the actual part of the source rect contained in the Bitmap.
  1939 	TRect srcRect(aSrcRect);
  1940 	TRect area(aSrcBmp->SizeInPixels());
  1941 	if(!srcRect.Intersects(area))
  1942 		{
  1943 		aSrcBmp->EndDataAccess(ETrue);
  1944 		aAlphaBmp->EndDataAccess(ETrue);
  1945 		return KErrArgument;
  1946 		}
  1947 	srcRect.Intersection(area);
  1948 	//Calculate the destination rect
  1949 	TPoint destPt(aDestPt + iOrigin);
  1950 	TRect destRect(destPt, srcRect.Size());
  1951 	TPoint offset(srcRect.iTl - destPt);
  1952 	TRect clippedDestRect(destRect);
  1953 	AddRect(clippedDestRect);
  1954 	if(UserClipRect(clippedDestRect))
  1955 		{
  1956 		aSrcBmp->EndDataAccess(ETrue);
  1957 		aAlphaBmp->EndDataAccess(ETrue);
  1958 		return KErrArgument;
  1959 		}
  1960 	//Save current shadow mode
  1961 	TInt8 shadowMode = iShadowMode;
  1962 	iShadowMode = CFbsDrawDevice::ENoShadow;
  1963 	//Setup the device and prevent the bitmaps from being cleaned away by client code.
  1964 	//Drawing begins.
  1965 	SetupDevice();
  1966 	iDevice->DrawingBegin();
  1967 	
  1968 	CBitwiseBitmap* srcBmp = ((CFbsBitGcBitmap*)aSrcBmp)->Address();
  1969 	CBitwiseBitmap* alphaBmp = ((CFbsBitGcBitmap*)aAlphaBmp)->Address();
  1970 	BG_ASSERT_DEBUG(srcBmp, EBitgdiPanicInvalidBitmap);
  1971 	BG_ASSERT_DEBUG(alphaBmp, EBitgdiPanicInvalidBitmap);
  1972 	TUint32* srcDataAddr = aSrcBmp->DataAddress();
  1973 	TUint32* alphaDataAddr = aAlphaBmp->DataAddress();
  1974 
  1975 	CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aSrcBmp, clippedDestRect, offset);
  1976 	CFbsRasterizer* alphaRasterizer;
  1977 	if (aAlphaPt.iX >= 0 && aAlphaPt.iY >= 0
  1978 		&& aAlphaPt.iX + srcRect.Width() <= aAlphaBmp->SizeInPixels().iWidth
  1979 		&& aAlphaPt.iY + srcRect.Height() <= aAlphaBmp->SizeInPixels().iHeight)
  1980 		{
  1981 		// Alpha blending bitmap is not tiled. Pass same region of interest as source bitmap to rasterizer.
  1982 		alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp, clippedDestRect, aAlphaPt - destPt);
  1983 		}
  1984 	else
  1985 		{
  1986 		// Alpha blending bitmap is tiled. Do not pass any region of interest to rasterizer.
  1987 		alphaRasterizer = PrepareRasterizerForExtendedBitmap(*aAlphaBmp);
  1988 		}
  1989 
  1990 	//For each region - find the clipping rect and draw
  1991 	TInt limit = iDefaultRegionPtr->Count();
  1992 	CGraphicsAccelerator* ga = GraphicsAccelerator();
  1993 	// Code for Graphics Accelerated Drawing
  1994 	if(ga && (shadowMode == CFbsDrawDevice::ENoShadow))
  1995 		{
  1996 		TInt gaOperationResult = KErrUnknown;
  1997 		TAcceleratedBitmapSpec srcBmpSpec(const_cast<CFbsBitmap*>(aSrcBmp));
  1998 		TAcceleratedBitmapSpec alphaBmpSpec(const_cast<CFbsBitmap*>(aAlphaBmp));
  1999 		iDevice->DrawingEnd();
  2000 
  2001 		for(TInt count=0;count<limit;count++)
  2002 			{
  2003 			iClipRect=(*iDefaultRegionPtr)[count];
  2004 			if(!iClipRect.Intersects(clippedDestRect))
  2005 				{
  2006 				continue;
  2007 				}
  2008 			//clippedDestRect was constructed from destRect. destRect was constructed from srcRect.
  2009 			iClipRect.Intersection(clippedDestRect);
  2010 			TRect clippedSrcRect(iClipRect);
  2011 			clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect now.
  2012 			TPoint shift(clippedSrcRect.iTl - srcRect.iTl);
  2013 			BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
  2014 			BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
  2015 
  2016 			gaOperationResult = ga->Operation(TGopAlphaBlendOneBitmap(iClipRect.iTl,srcBmpSpec,clippedSrcRect,alphaBmpSpec,aAlphaPt + shift));
  2017 			if(gaOperationResult != KErrNone)
  2018 				break;
  2019 			iDevice->iDrawDevice->UpdateRegion(iClipRect);
  2020 			}
  2021 		if(gaOperationResult == KErrNone)
  2022 			goto finish;
  2023 		iDevice->DrawingBegin();
  2024 		}
  2025 
  2026 	// Code for non- Graphics Accelerated Drawing
  2027 	for(TInt count=0;count<limit;count++)
  2028 		{
  2029 		iClipRect=(*iDefaultRegionPtr)[count];
  2030 		if(!iClipRect.Intersects(clippedDestRect))
  2031 			{
  2032 			continue;
  2033 			}
  2034 		//clippedDestRect was constructed from destRect. destRect was constructed from srcRect.
  2035 		iClipRect.Intersection(clippedDestRect);
  2036 		TRect clippedSrcRect(iClipRect);
  2037 		clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect now.
  2038 		TPoint shift(clippedSrcRect.iTl - srcRect.iTl);
  2039 		BG_ASSERT_DEBUG(shift.iX >= 0, EBitgdiPanicNegativeShift);
  2040 		BG_ASSERT_DEBUG(shift.iY >= 0, EBitgdiPanicNegativeShift);
  2041 		DoBitBltAlpha(iClipRect.iTl,
  2042 					  srcBmp,
  2043 					  srcDataAddr,
  2044 					  clippedSrcRect,
  2045 					  alphaBmp,
  2046 					  alphaDataAddr,
  2047 					  aAlphaPt + shift,
  2048 					  shadowMode,
  2049 					  EFalse);
  2050 		iDevice->iDrawDevice->UpdateRegion(iClipRect);
  2051 		}
  2052 
  2053 	// Drawing ends. Restore the previous shadow mode.
  2054 	iDevice->DrawingEnd();
  2055 finish:
  2056 	if (rasterizer)
  2057 		{
  2058 		rasterizer->EndBitmap(aSrcBmp->SerialNumber());
  2059 		}
  2060 	if (alphaRasterizer)
  2061 		{
  2062 		alphaRasterizer->EndBitmap(aAlphaBmp->SerialNumber());
  2063 		}
  2064 	aSrcBmp->EndDataAccess(ETrue);
  2065 	aAlphaBmp->EndDataAccess(ETrue);
  2066 	iShadowMode = shadowMode;
  2067 
  2068 	return KErrNone;
  2069 	}
  2070 
  2071 GLDEF_C void XorBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes)
  2072 	{
  2073 	// Round up to nearest word boundary
  2074 	const TUint32* const destBufferLimit = aDestBuffer + ((aNumBytes + sizeof(TUint32) - 1) / sizeof(TUint32));
  2075 
  2076 	while (aDestBuffer < destBufferLimit)
  2077 		*aDestBuffer++ ^= *aSrceBuffer++;
  2078 	}
  2079 
  2080 GLDEF_C void AndBuffers(TUint32* aDestBuffer,const TUint32* aSrceBuffer,TInt aNumBytes)
  2081 	{
  2082 	// Round up to nearest word boundary
  2083 	const TUint32* const destBufferLimit = aDestBuffer + ((aNumBytes + sizeof(TUint32) - 1) / sizeof(TUint32));
  2084 
  2085 	while (aDestBuffer < destBufferLimit)
  2086 		*aDestBuffer++ &= *aSrceBuffer++;
  2087 	}
  2088 
  2089 GLDEF_C void InvertBuffer(TUint32* aDestBuffer,TInt aNumBytes)
  2090 	{
  2091 	// Round up to nearest word boundary
  2092 	const TUint32* const destBufferLimit = aDestBuffer + ((aNumBytes + sizeof(TUint32) - 1) / sizeof(TUint32));
  2093 
  2094 	while (aDestBuffer < destBufferLimit)
  2095 		{
  2096 		*aDestBuffer = *aDestBuffer ^ KMaxTUint32;
  2097 		++aDestBuffer;
  2098 		}
  2099 	}
  2100 
  2101 GLDEF_C void InvertBuffer(TUint8* aDestBuffer,TInt aNumBytes)
  2102 	{
  2103 	const TUint8* const destBufferLimit = aDestBuffer + aNumBytes;
  2104 
  2105 	while (aDestBuffer < destBufferLimit)
  2106 		{
  2107 		*aDestBuffer = static_cast<TUint8>(*aDestBuffer ^ KMaxTUint8);
  2108 		++aDestBuffer;
  2109 		}
  2110 	}
  2111 
  2112 /**
  2113 The method tiles the scan line if its length in pixels is less than
  2114 aLengthInPixels argument.
  2115 @internalComponent
  2116 @param aScanLine A pointer to the scan line buffer.
  2117 @param aLengthInPixels The scan line buffer should have that count of pixels after the method call.
  2118 @param aSrcPt Position of the first pixel in aMaskBitmap that should be used as a source
  2119               for the pixels in scan line buffer.
  2120 @param aMaskBitmap Any additional pixels for the scan line buffer will be taken from here.
  2121 @param aScanLinePos This argument is used for some internal optimizations. It should not be
  2122                     modified by the caller.
  2123 @param aMaskBase The base address of aMaskBitmap data.
  2124 @param aDisplayMode Any additional pixels should be taken from aMaskBitmap using aDisplayMode
  2125                     as an argument for GetScanLine() call.
  2126 */
  2127 LOCAL_C void TileScanLine(TPtr8& aScanLine,
  2128 						  TInt aLengthInPixels,
  2129 						  const TPoint& aSrcPt,
  2130 						  const CBitwiseBitmap* aMaskBitmap,
  2131 						  TLineScanningPosition& aScanLinePos,
  2132 						  TUint32* aMaskBase,
  2133 						  TDisplayMode aDisplayMode
  2134 						  )
  2135 	{
  2136 	TInt lengthInBytes = CFbsBitmap::ScanLineLength(aLengthInPixels, aDisplayMode);
  2137 	BG_ASSERT_DEBUG(lengthInBytes <= aScanLine.MaxLength(), EBitgdiPanicInvalidArg);
  2138 	TInt scanLineLength = aScanLine.Length();
  2139 	if(scanLineLength < lengthInBytes && aSrcPt.iX > 0)
  2140 		{
  2141 		//If, for example, src bmp is 100 pixels width, mask bmp is 20 pixels width and src
  2142 		//rect is (10, 0, 100, 1) -> We will read only pixels 10..19 from the first scan line
  2143 		//of the mask bmp. We have to have 90 mask bmp pixels.
  2144 		//So we have to make a second mask bmp read startig from pixel 0 - 10 pixels length.
  2145 		TInt maxLen = Min(aScanLine.MaxLength() - scanLineLength, aSrcPt.iX);
  2146 		TPtr8 maskDes2(const_cast <TUint8*> (aScanLine.Ptr()) + scanLineLength, maxLen, maxLen);
  2147 		TPoint srcPt(0, aSrcPt.iY);
  2148 		TPoint zeroPt(0, 0);
  2149 		aMaskBitmap->GetScanLine(maskDes2, srcPt, maxLen, EFalse, zeroPt, aDisplayMode, aMaskBase, aScanLinePos);
  2150 		aScanLine.SetLength(scanLineLength + maskDes2.Length());
  2151 		scanLineLength = aScanLine.Length();
  2152 		}
  2153 	if(scanLineLength >= lengthInBytes || scanLineLength == 0)
  2154 		{
  2155 		return;
  2156 		}
  2157 	//If we still don't have enough mask bmp pixels - we have to tile the scan line
  2158 	TInt repeatCnt = lengthInBytes / scanLineLength - 1;
  2159 	TInt bytesLeft = lengthInBytes % scanLineLength;
  2160 	const TUint8* src = aScanLine.Ptr();
  2161 	TUint8* dest = const_cast <TUint8*> (src) + scanLineLength;
  2162 	for(;repeatCnt>0;dest+=scanLineLength,repeatCnt--)
  2163 		{
  2164 		Mem::Copy(dest, src, scanLineLength);
  2165 		}
  2166 	if(bytesLeft)
  2167 		{
  2168 		Mem::Copy(dest, src, bytesLeft);
  2169 		}
  2170 	aScanLine.SetLength(lengthInBytes);
  2171 	}
  2172 
  2173 /**
  2174 The method draws a masked rectangular section of the source
  2175 bitmap and does a compress/stretch to fit a given destination
  2176 rectangle.
  2177 @internalComponent
  2178 */
  2179 void CFbsBitGc::DoDrawBitmapMasked(const TRect& aDestRect,
  2180 							   CBitwiseBitmap* aSourceBitmap,
  2181 							   TUint32* aSourceBase,
  2182 							   const TRect& aSourceRect,
  2183 							   CBitwiseBitmap* aMaskBitmap,
  2184 							   TUint32* aMaskBase,
  2185 							   TBool aInvertMask, const TPoint& aDitherOrigin)
  2186 	{
  2187 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
  2188 #ifdef _DEBUG
  2189 	TRect deviceDestRect;
  2190 	drawDevice->GetDrawRect(deviceDestRect);
  2191 	BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
  2192 	BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
  2193 	BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
  2194 	BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
  2195 #endif
  2196 
  2197 	// The clipped version of the destination rectangle
  2198 	TRect clippedDestRect(aDestRect);
  2199 	clippedDestRect.Intersection(iClipRect);
  2200 
  2201 	// If the source rectangle and the destination rectangle are same,
  2202 	// no stretch/compress operation required, just do BitBltMasked
  2203 	if (aDestRect.Size() == aSourceRect.Size())
  2204 		{
  2205 		if (!clippedDestRect.IsEmpty())
  2206 			{
  2207 			const TPoint destPoint(clippedDestRect.iTl);
  2208 			clippedDestRect.Move(aSourceRect.iTl - aDestRect.iTl);
  2209 			DoBitBltMasked(destPoint,
  2210 						   aSourceBitmap,
  2211 						   aSourceBase,
  2212 						   clippedDestRect,
  2213 						   aMaskBitmap,
  2214 						   aMaskBase,
  2215 						   aInvertMask,
  2216 						   aDitherOrigin,
  2217 						   CFbsDrawDevice::ENoShadow);
  2218 			}
  2219 		return;
  2220 		}
  2221 	MFastBlend* fastBlend=NULL;
  2222 	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
  2223 		{
  2224 		if (fastBlend->FastBlendBitmapMaskedScaled(iClipRect, aDestRect, aSourceRect, aSourceBase, aSourceBitmap->DataStride(),
  2225 				aSourceBitmap->DisplayMode(),aSourceBitmap->SizeInPixels(), 
  2226 				aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aInvertMask, 
  2227 				iDrawMode, iShadowMode)==KErrNone)
  2228 			{
  2229 			return;
  2230 			}
  2231 		}
  2232 
  2233 	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
  2234 	const TInt scanLineBytes = drawDevice->ScanLineBytes();
  2235 	TPtr8 scanLineDes(REINTERPRET_CAST(TUint8*,scanLineBuffer),scanLineBytes,scanLineBytes);
  2236 
  2237 	// This constant is associated to the value used in TestGdi::DoDrawBitmapMaskedL, case #24.
  2238 	// If this value is changed, then that one must be updated as well otherwise the test will no longer be valid.	
  2239 	const TInt KScanLineLength = 256;
  2240 	const TInt KRgbSize = 4;
  2241 	TUint8 maskBuffer[KScanLineLength];
  2242 
  2243 	TUint8 sourceBuffer[KScanLineLength*KRgbSize];
  2244 	TPtr8 sourceDes(sourceBuffer,KScanLineLength*KRgbSize,KScanLineLength*KRgbSize);
  2245 
  2246 	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
  2247 	TDrawMode drawMode = aInvertMask ? EDrawModeAND : EDrawModeANDNOT;
  2248 	// If the source bitmap and the mask bitmap are same, draw the source bitmap either
  2249 	// with EDrawModeAND or EDrawModeOR based on aInvertMask parameter.
  2250 	if (aSourceBitmap == aMaskBitmap)
  2251 		{
  2252 		drawMode = aInvertMask ? EDrawModeAND : EDrawModeOR;
  2253 		}
  2254 
  2255 	TLinearDDA xLine;
  2256 	TInt bitmapXStart = 0;
  2257 	xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
  2258 					TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
  2259 	xLine.JumpToYCoord2(bitmapXStart,clippedDestRect.iTl.iX);
  2260 
  2261 	TLinearDDA yLine;
  2262 	TPoint yCoord(aSourceRect.iTl.iY,aDestRect.iTl.iY);
  2263 	yLine.Construct(yCoord,TPoint(aSourceRect.iBr.iY,aDestRect.iBr.iY),TLinearDDA::ELeft);
  2264 	TInt dummy;
  2265 	yLine.JumpToYCoord2(dummy,clippedDestRect.iTl.iY);
  2266 	yCoord.SetXY(dummy,clippedDestRect.iTl.iY);
  2267 
  2268 	TPoint ditherOrigin(aDitherOrigin + clippedDestRect.iTl);
  2269 	const TInt srceWidth = aSourceRect.Width();
  2270 	const TInt destWidth = aDestRect.Width();
  2271 	const TInt clipWidth = clippedDestRect.Width();
  2272 	const TInt clipStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
  2273 	const TInt sourceBmpWidth = aSourceBitmap->SizeInPixels().iWidth;
  2274 	const TInt maskWidth = aMaskBitmap->SizeInPixels().iWidth;
  2275 	const TInt maskHeight = aMaskBitmap->SizeInPixels().iHeight;
  2276 
  2277 	TLineScanningPosition lineScanPos(aSourceBase);
  2278 	TLineScanningPosition lineScanPos2(aSourceBase);
  2279 	TLineScanningPosition lineScanPosMask(aMaskBase);
  2280 
  2281 	HBufC8* alphaBuffer = NULL;
  2282 	TPtr8 alphaBufferDes(NULL, 0);
  2283 	const TDisplayMode maskDisplayMode = aMaskBitmap->DisplayMode();
  2284 
  2285 	// Mask inversion is not supported if the original source mask format is EGray256.
  2286 	// Note that this is only used for pre-multiplied alpha targets.
  2287 	TUint8 maskInverter = (aInvertMask && maskDisplayMode != EGray256) ? 0xFF : 0x00;
  2288 
  2289 	if (aSourceBitmap != aMaskBitmap)
  2290 		{
  2291 		// Get buffer to be used to convert non-EGray256 masks to EGray256 when display mode is EColor16MAP
  2292 		// or to tile the mask when the mask width is smaller than the source bitmap width.
  2293 		if (maskDisplayMode != EGray256 && (dispMode == EColor16MAP || maskWidth < sourceBmpWidth))
  2294 			{
  2295 			alphaBuffer = CFbsBitmap::GetExtraBuffer(CFbsBitmap::ScanLineLength(maskWidth, EGray256));
  2296 			if (!alphaBuffer)
  2297 				{
  2298 				return;  // Out of memory so do not draw anything 
  2299 				}
  2300 			alphaBufferDes.Set(alphaBuffer->Des());
  2301 			}
  2302 
  2303 		// Get buffer to be used for decompressing compressed masks when mask is EGray256
  2304 		if (maskDisplayMode == EGray256 && aMaskBitmap->IsCompressed())
  2305 			{
  2306 			HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
  2307 			if (!hBuf)
  2308 				{
  2309 				return;  // Out of memory so do not draw anything
  2310 				}
  2311 			lineScanPosMask.iScanLineBuffer = hBuf;
  2312 			}
  2313 		}
  2314 
  2315 	while (yCoord.iY < clippedDestRect.iBr.iY)
  2316 		{
  2317 		// Draw only the source bitmap, if the source bitmap and the mask bitmap are same.
  2318 		// else draw both the bitmaps
  2319 		if (aSourceBitmap == aMaskBitmap)
  2320 			{
  2321 			aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
  2322 								 clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
  2323 								 srceWidth,ditherOrigin,dispMode,aSourceBase,lineScanPos);
  2324 			if (yCoord.iY==clippedDestRect.iTl.iY)
  2325 				aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
  2326 			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
  2327 			}
  2328 		else if ((maskDisplayMode == EGray256) || (dispMode == EColor16MAP))
  2329 			{
  2330 			// Stretch the source bitmap and the mask bitmap for KScanLineLength as stretch length
  2331 			// then do alpha blending for this length. If the length is more then KScanLineLength
  2332 			// repeat it till you stretch complete destination length.
  2333 			const TPoint startPt(bitmapXStart,yCoord.iX);
  2334 			TInt clipWidthPart = clippedDestRect.Width();
  2335 			TBool loopLast = ETrue;
  2336 			if(clipWidthPart > KScanLineLength)
  2337 				{
  2338 				clipWidthPart = KScanLineLength;
  2339 				loopLast = EFalse;
  2340 				}
  2341 			TInt clipIncStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
  2342 			TInt startClip=clippedDestRect.iTl.iX;
  2343 			TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
  2344 			xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
  2345 							TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
  2346 			xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
  2347 			TPoint srcPixel(bitmapXStart % maskWidth,yCoord.iX % maskHeight);
  2348 			TInt spaceLeft = 0;
  2349 			TRgb maskRgbValue;
  2350 			TUint32* maskScanLinePtr32 = NULL;
  2351 			TPoint currentYValue(0,srcPixel.iY);
  2352 			aMaskBitmap->GetScanLinePtr(maskScanLinePtr32, currentYValue, maskWidth, aMaskBase, lineScanPosMask);
  2353 			// To implement non EGray256 mask support with EColor16MAP display mode, we convert
  2354 			// the mask to EGray256.
  2355 			if (maskDisplayMode != EGray256) // Convert scan-line to EGray256 and set maskScanLinePtr32 to the conversion.
  2356 				{
  2357 				aMaskBitmap->GetScanLine(maskScanLinePtr32, alphaBufferDes, currentYValue, maskWidth, EFalse, TPoint(0, 0), EGray256);
  2358 				maskScanLinePtr32 = (TUint32*)alphaBuffer->Ptr();
  2359 				}
  2360 			TUint8* maskScanLinePtr = reinterpret_cast<TUint8*>(maskScanLinePtr32);
  2361 
  2362 			// Outer loop over all KScanLineLengths
  2363 			FOREVER
  2364 				{
  2365 				aSourceBitmap->StretchScanLine(sourceDes,startPt,clipIncStrch,clipWidthPart,destWidth,
  2366 								aSourceRect.iTl.iX,srceWidth,ditherOrigin,EColor16MU,aSourceBase,lineScanPos);
  2367 				// Inner loop to tile the mask if necessary
  2368 				spaceLeft = clipWidthPart;
  2369 	
  2370 				do	{
  2371 					srcPixel.iX = sourceDestXCoords.iX % maskWidth;
  2372 			
  2373 					// Invert the mask using the inversion mask.
  2374 					maskBuffer[(sourceDestXCoords.iY-clippedDestRect.iTl.iX)%KScanLineLength]=
  2375 						maskInverter^maskScanLinePtr[srcPixel.iX];
  2376 					xLine.NextStep(sourceDestXCoords);
  2377 					} while (--spaceLeft>0);
  2378 				
  2379 				if (yCoord.iY == clippedDestRect.iTl.iY && startClip == clippedDestRect.iTl.iX)
  2380 					{
  2381 					aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
  2382 					aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
  2383 					}
  2384 				drawDevice->WriteRgbAlphaLine(startClip,yCoord.iY,clipWidthPart,sourceBuffer,maskBuffer,iDrawMode);
  2385 				if (loopLast)
  2386 					{
  2387 					break;
  2388 					}
  2389 				startClip+=KScanLineLength;
  2390 				if (clippedDestRect.iBr.iX - startClip <= KScanLineLength)
  2391  					{
  2392 					loopLast = ETrue;
  2393 					clipWidthPart = clippedDestRect.iBr.iX - startClip;
  2394 					}
  2395 				clipIncStrch += KScanLineLength;
  2396 				}
  2397 			}
  2398 		else
  2399 			{
  2400 			aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
  2401 									 clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
  2402 									 srceWidth,ditherOrigin,dispMode,aSourceBase,lineScanPos2);
  2403 			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,EDrawModeXOR);
  2404 
  2405 			TInt maskXStart = bitmapXStart % maskWidth;
  2406 			if(maskWidth < sourceBmpWidth)
  2407 				{
  2408 				TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
  2409 				xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
  2410 								TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
  2411 				xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
  2412 				TPoint srcPixel(maskXStart,yCoord.iX % maskHeight);
  2413 				TInt spaceLeft = clipWidth;
  2414 				TPoint prevSourceDestXCoords(-1,-1);
  2415 				TRgb maskRgbValue;
  2416 				aMaskBitmap->GetScanLine(alphaBufferDes, TPoint(0,srcPixel.iY), maskWidth, EFalse, TPoint(0, 0), EGray256, aMaskBase, lineScanPosMask);
  2417 
  2418 				// Loop to tile the mask
  2419 				do	{
  2420 					if (sourceDestXCoords.iY != prevSourceDestXCoords.iY)
  2421 						{
  2422 						if (sourceDestXCoords.iX != prevSourceDestXCoords.iX)
  2423 							{
  2424 							srcPixel.iX = sourceDestXCoords.iX % maskWidth;
  2425 							if (srcPixel.iX < 0)
  2426 								srcPixel.iX += maskWidth;
  2427 							maskRgbValue = TRgb::Gray256((*alphaBuffer)[srcPixel.iX]);
  2428 							}
  2429 						drawDevice->WriteRgb(sourceDestXCoords.iY,yCoord.iY,maskRgbValue,drawMode);
  2430 						spaceLeft--;
  2431 						}
  2432 					prevSourceDestXCoords = sourceDestXCoords;
  2433 					xLine.SingleStep(sourceDestXCoords);
  2434 					} while (spaceLeft > 0);
  2435 				}
  2436 			else
  2437 				{
  2438 				// No need to tile the mask
  2439 				aMaskBitmap->StretchScanLine(scanLineDes,TPoint(maskXStart,yCoord.iX % maskHeight),
  2440 										clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
  2441 										srceWidth,ditherOrigin,dispMode,aMaskBase,lineScanPosMask);
  2442 				drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
  2443 				// Redo stretching of the aSourceBitmap scanline
  2444 				aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
  2445 									 	clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
  2446 									 	srceWidth,ditherOrigin,dispMode,aSourceBase,lineScanPos2);
  2447 				}
  2448 
  2449 			if (yCoord.iY==clippedDestRect.iTl.iY)
  2450 				{
  2451 				aSourceBitmap->SetCompressionBookmark(lineScanPos2,aSourceBase,NULL);
  2452 				aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
  2453 				}
  2454 
  2455 			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,EDrawModeXOR);
  2456 			}
  2457 		yLine.NextStep(yCoord);
  2458 		ditherOrigin.iY++;
  2459 		}
  2460 	}
  2461 
  2462 EXPORT_C TInt CFbsBitGc::AlphaBlendBitmaps(const TPoint& aDestPt,
  2463 											const CWsBitmap* aSrcBmp,
  2464 											const TRect& aSrcRect,
  2465 											const CWsBitmap* aAlphaBmp,
  2466 											const TPoint& aAlphaPt)
  2467 	{
  2468 	return AlphaBlendBitmaps(aDestPt, REINTERPRET_CAST(const CFbsBitmap*, aSrcBmp), aSrcRect, REINTERPRET_CAST(const CFbsBitmap*, aAlphaBmp), aAlphaPt);
  2469 	}
  2470 
  2471 TInt CFbsBitGc::FastBlendInterface(const CBitwiseBitmap* aSource, const CBitwiseBitmap* aMask, MFastBlend*& aFastBlend) const
  2472 	{
  2473 #if defined(__ALLOW_FAST_BLEND_DISABLE__)
  2474 	if (iFastBlendDisabled)
  2475 		return(KErrNotSupported);
  2476 #endif
  2477 	if ((aSource && aSource->IsCompressed()) || (aMask && aMask->IsCompressed()))
  2478 		return(KErrNotSupported);
  2479 	TAny* interface=NULL;
  2480 	TInt ret=iDevice->iDrawDevice->GetInterface(KFastBlendInterfaceID, interface);
  2481 	aFastBlend=(MFastBlend*)interface;
  2482 	return(ret);
  2483 	}
  2484 
  2485 /*
  2486 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.
  2487 
  2488 @see CBitwiseBitmap::GetScanLine()
  2489 @see CBitwiseBitmap::GetVerticalScanLine()
  2490 @see CBitwiseBitmap::StretchScanLine()
  2491 @see CFbsDrawDevice::WriteLine()
  2492 @internalComponent
  2493 */
  2494 TDisplayMode CFbsBitGc::ScanLineBufferDisplayMode(CFbsDrawDevice* aDrawDevice)
  2495 	{
  2496 	return iDrawMode == EDrawModeWriteAlpha ? aDrawDevice->DisplayMode() : aDrawDevice->ScanLineDisplayMode();
  2497 	}
  2498 
  2499 /** Prepares the rasterizer to retrieve scan lines from a bitmap if it is an
  2500 extended bitmap. No region of interest is passed to the rasterizer.
  2501 This function calls CFbsRasterizer::BeginBitmap() with the appropriate
  2502 parameters. When finished retrieving scan lines from the extended bitmap,
  2503 CFbsRasterizer::EndBitmap() must be called.
  2504 @param aBitmap The bitmap to retrieve scan lines from.
  2505 @return A pointer to the rasterizer owned by this thread's FBServ session.
  2506 @return NULL if the rasterizer is not present or aBitmap is not an extended bitmap.
  2507 @see CFbsRasterizer
  2508 @internalComponent
  2509 */
  2510 CFbsRasterizer* CFbsBitGc::PrepareRasterizerForExtendedBitmap(const CFbsBitmap& aBitmap)
  2511 	{
  2512 	CFbsRasterizer* rasterizer = NULL;
  2513 	CFbsRasterizer::TBitmapDesc desc;
  2514 	desc.iDataType = aBitmap.ExtendedBitmapType();
  2515 	if (desc.iDataType != KNullUid)
  2516 		{
  2517 		rasterizer = CFbsBitmap::Rasterizer();
  2518 		if (rasterizer)
  2519 			{
  2520 			desc.iSizeInPixels = aBitmap.SizeInPixels();
  2521 			desc.iDispMode = aBitmap.DisplayMode();
  2522 			desc.iData = aBitmap.DataAddress();
  2523 			desc.iDataSize = aBitmap.DataSize();
  2524 			rasterizer->BeginBitmap(aBitmap.SerialNumber(), desc, NULL);
  2525 			}
  2526 		}
  2527 	return rasterizer;
  2528 	}
  2529 
  2530 /** Prepares the rasterizer to retrieve scan lines from a bitmap if it is an
  2531 extended bitmap. The region of interest passed to the rasterizer is the
  2532 intersection of the clipping region and the specified rectangle.
  2533 This function calls CFbsRasterizer::BeginBitmap() with the appropriate
  2534 parameters. When finished retrieving scan lines from the extended bitmap,
  2535 CFbsRasterizer::EndBitmap() must be called.
  2536 @param aBitmap The bitmap to retrieve scan lines from.
  2537 @param aDestRect A rectangle in coordinates relative to the graphics context that
  2538                  bounds the area that aBitmap is to be blitted onto.
  2539 @param aOffset An offset that converts aDestRect into coordinates relative to
  2540                the source bitmap.
  2541 @return A pointer to the rasterizer owned by this thread's FBServ session.
  2542 @return NULL if the rasterizer is not present or aBitmap is not an extended bitmap.
  2543 @see CFbsRasterizer
  2544 @internalComponent
  2545 */
  2546 CFbsRasterizer* CFbsBitGc::PrepareRasterizerForExtendedBitmap(const CFbsBitmap& aBitmap, const TRect& aDestRect, const TPoint& aOffset)
  2547 	{
  2548 	CFbsRasterizer* rasterizer = NULL;
  2549 	CFbsRasterizer::TBitmapDesc desc;
  2550 	desc.iDataType = aBitmap.ExtendedBitmapType();
  2551 	if (desc.iDataType != KNullUid)
  2552 		{
  2553 		rasterizer = CFbsBitmap::Rasterizer();
  2554 		if (rasterizer)
  2555 			{
  2556 			desc.iSizeInPixels = aBitmap.SizeInPixels();
  2557 			desc.iDispMode = aBitmap.DisplayMode();
  2558 			desc.iData = aBitmap.DataAddress();
  2559 			desc.iDataSize = aBitmap.DataSize();
  2560 			RRegion rgn;
  2561 			rgn.Copy(*iDefaultRegionPtr);
  2562 			rgn.ClipRect(aDestRect);
  2563 			rgn.Offset(aOffset);
  2564 			BG_ASSERT_DEBUG(rgn.IsContainedBy(desc.iSizeInPixels), EBitgdiPanicOutOfBounds);
  2565 			rasterizer->BeginBitmap(aBitmap.SerialNumber(), desc, &rgn);
  2566 			rgn.Close();
  2567 			}
  2568 		}
  2569 	return rasterizer;
  2570 	}
  2571 
  2572 /** Prepares the rasterizer to retrieve scan lines from a bitmap if it is an
  2573 extended bitmap. The region of interest passed to the rasterizer is the intersection
  2574 of the clipping region, the clipping rectangle and the specified rectangle.
  2575 This function calls CFbsRasterizer::BeginBitmap() with the appropriate
  2576 parameters. When finished retrieving scan lines from the extended bitmap,
  2577 CFbsRasterizer::EndBitmap() must be called.
  2578 @param aBitmap The bitmap to retrieve scan lines from.
  2579 @param aDestRect A rectangle in coordinates relative to the graphics context that
  2580                  bounds the area that aBitmap is to be drawn onto.
  2581 @param aSourceRect A rectangle in coordinates relative to the source bitmap that maps
  2582                    to aDestRect after scaling and translation.
  2583 @return A pointer to the rasterizer owned by this thread's FBServ session.
  2584 @return NULL if the rasterizer is not present or aBitmap is not an extended bitmap.
  2585 @see CFbsRasterizer
  2586 @internalComponent
  2587 */
  2588 CFbsRasterizer* CFbsBitGc::PrepareRasterizerForExtendedBitmap(const CFbsBitmap& aBitmap, const TRect& aDestRect, const TRect& aSourceRect)
  2589 	{
  2590 	CFbsRasterizer* rasterizer = NULL;
  2591 	CFbsRasterizer::TBitmapDesc desc;
  2592 	desc.iDataType = aBitmap.ExtendedBitmapType();
  2593 	if (desc.iDataType != KNullUid)
  2594 		{
  2595 		rasterizer = CFbsBitmap::Rasterizer();
  2596 		if (rasterizer)
  2597 			{
  2598 			desc.iSizeInPixels = aBitmap.SizeInPixels();
  2599 			desc.iDispMode = aBitmap.DisplayMode();
  2600 			desc.iData = aBitmap.DataAddress();
  2601 			desc.iDataSize = aBitmap.DataSize();
  2602 			RRegion rgn;
  2603 			// Calculate the parameters for the linear DDA algorithm used to scale the region
  2604 			// of interest before entering the rectangle loop, since they are invariant.
  2605 			TLinearDDA xLine0, yLine0;
  2606 			xLine0.Construct(TPoint(aSourceRect.iTl.iX, aDestRect.iTl.iX),
  2607 			                 TPoint(aSourceRect.iBr.iX, aDestRect.iBr.iX),
  2608 			                 TLinearDDA::ELeft);
  2609 			yLine0.Construct(TPoint(aSourceRect.iTl.iY, aDestRect.iTl.iY),
  2610 			                 TPoint(aSourceRect.iBr.iY, aDestRect.iBr.iY),
  2611 			                 TLinearDDA::ELeft);
  2612 			TInt n = iDefaultRegionPtr->Count();
  2613 			for (TInt i = 0; i < n; ++i)
  2614 				{
  2615 				TRect rect = (*iDefaultRegionPtr)[i];
  2616 				if (!rect.Intersects(iUserClipRect))
  2617 					{
  2618 					continue;
  2619 					}
  2620 				rect.Intersection(iUserClipRect);
  2621 				if (!rect.Intersects(aDestRect))
  2622 					{
  2623 					continue;
  2624 					}
  2625 				rect.Intersection(aDestRect);
  2626 				// Scale the region of interest from coordinates relative to the graphics
  2627 				// context to coordinates relative to the bitmap, one rectangle at a time.
  2628 				TLinearDDA xLine(xLine0), yLine(yLine0);
  2629 				TInt ax, ay, bx, by;
  2630 				xLine.JumpToYCoord(ax, rect.iTl.iX);
  2631 				yLine.JumpToYCoord(ay, rect.iTl.iY);
  2632 				xLine.JumpToYCoord(bx, rect.iBr.iX);
  2633 				yLine.JumpToYCoord(by, rect.iBr.iY);
  2634 				if (ax < bx && ay < by)
  2635 					{
  2636 					rgn.AddRect(TRect(ax, ay, bx, by));
  2637 					}
  2638 				}
  2639 			BG_ASSERT_DEBUG(rgn.IsContainedBy(desc.iSizeInPixels), EBitgdiPanicOutOfBounds);
  2640 			rasterizer->BeginBitmap(aBitmap.SerialNumber(), desc, &rgn);
  2641 			rgn.Close();
  2642 			}
  2643 		}
  2644 	return rasterizer;
  2645 	}