os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdibitblt.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "swdirectgdiengine.h"
sl@0
    17
#include "swdirectgdidriverimpl.h"
sl@0
    18
#include "directgdiadapter.h"
sl@0
    19
#include <bitdrawinterfaceid.h>
sl@0
    20
#include <bmalphablend.h>
sl@0
    21
#include <graphics/bitmap.inl>
sl@0
    22
#include <graphics/gdi/gdiinline.inl>
sl@0
    23
sl@0
    24
/** 
sl@0
    25
@see MDirectGdiEngine::BitBlt()
sl@0
    26
@panic DGDIAdapter 7, aBitmap is invalid (debug only). 
sl@0
    27
*/
sl@0
    28
void CSwDirectGdiEngine::BitBlt(const TPoint& aDestPos, 
sl@0
    29
								const CFbsBitmap& aBitmap,	
sl@0
    30
								const TRect& aSrceRect)
sl@0
    31
	{
sl@0
    32
	if (aBitmap.ExtendedBitmapType() != KNullUid)
sl@0
    33
		{
sl@0
    34
		iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
    35
		return;
sl@0
    36
		}
sl@0
    37
	
sl@0
    38
	TRect srceRect(aSrceRect);
sl@0
    39
	const TPoint destPoint(aDestPos + iOrigin + srceRect.iTl - aSrceRect.iTl);
sl@0
    40
	const TPoint offset(srceRect.iTl - destPoint);
sl@0
    41
sl@0
    42
	TRect targetRect(destPoint,srceRect.Size());
sl@0
    43
	aBitmap.BeginDataAccess();
sl@0
    44
sl@0
    45
	CBitwiseBitmap* srce = static_cast<const CSwDirectGdiBitmap&>(aBitmap).Address();
sl@0
    46
	GRAPHICS_ASSERT_DEBUG(srce,EDirectGdiPanicInvalidBitmap);
sl@0
    47
	
sl@0
    48
	const TInt limit = iDefaultRegionPtr->Count();		
sl@0
    49
			
sl@0
    50
	TBool opaqueSource = (!IsAlphaChannel(aBitmap.DisplayMode())) && (iDrawMode == DirectGdi::EDrawModePEN);	
sl@0
    51
sl@0
    52
	TRect clipRect;
sl@0
    53
	for (TInt count = 0; count < limit; count++)
sl@0
    54
		{
sl@0
    55
		clipRect = (*iDefaultRegionPtr)[count];
sl@0
    56
		if(!clipRect.Intersects(targetRect))
sl@0
    57
			{
sl@0
    58
			continue;
sl@0
    59
			}
sl@0
    60
		
sl@0
    61
		clipRect.Intersection(targetRect);
sl@0
    62
		
sl@0
    63
		TRect clippedSrceRect(clipRect);
sl@0
    64
		clippedSrceRect.Move(offset);
sl@0
    65
sl@0
    66
		if (opaqueSource)
sl@0
    67
			{
sl@0
    68
			iDrawMode = DirectGdi::EDrawModeWriteAlpha; // write rather than blend.
sl@0
    69
			}		
sl@0
    70
		
sl@0
    71
		DoBitBlt(clipRect.iTl, srce, aBitmap.DataAddress(), aBitmap.DataStride(), clippedSrceRect);
sl@0
    72
		
sl@0
    73
		if (opaqueSource)
sl@0
    74
			{
sl@0
    75
			iDrawMode = DirectGdi::EDrawModePEN; // set it back to how it was.
sl@0
    76
			}
sl@0
    77
		
sl@0
    78
		iDrawDevice->UpdateRegion(clipRect);
sl@0
    79
		}
sl@0
    80
	
sl@0
    81
	aBitmap.EndDataAccess(ETrue);	
sl@0
    82
	}
sl@0
    83
sl@0
    84
/**
sl@0
    85
@see MDirectGdiEngine::BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, TBool)
sl@0
    86
@panic DGDIAdapter 7, if either aMaskBitmap or aBitmap are invalid (debug only).
sl@0
    87
*/
sl@0
    88
void CSwDirectGdiEngine::BitBltMasked(const TPoint& aDestPos,
sl@0
    89
			  const CFbsBitmap& aBitmap,
sl@0
    90
			  const TRect& aSrcRect,
sl@0
    91
			  const CFbsBitmap& aMaskBitmap,
sl@0
    92
			  TBool aInvertMask)
sl@0
    93
	{
sl@0
    94
	if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid))
sl@0
    95
		{
sl@0
    96
		iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
    97
		return;
sl@0
    98
		}
sl@0
    99
	
sl@0
   100
	TRect localSrcRect(aSrcRect);
sl@0
   101
	const TPoint destPoint(aDestPos + iOrigin + localSrcRect.iTl - aSrcRect.iTl);
sl@0
   102
	const TRect destRect(destPoint, localSrcRect.Size());
sl@0
   103
	const TPoint offset(localSrcRect.iTl - destPoint);
sl@0
   104
	
sl@0
   105
	TRect targetRect(destRect);
sl@0
   106
	aBitmap.BeginDataAccess();
sl@0
   107
	aMaskBitmap.BeginDataAccess();
sl@0
   108
	
sl@0
   109
	CBitwiseBitmap* srcebmp = static_cast<const CSwDirectGdiBitmap&>(aBitmap).Address();
sl@0
   110
	CBitwiseBitmap* maskbmp = static_cast<const CSwDirectGdiBitmap&>(aMaskBitmap).Address();		
sl@0
   111
	
sl@0
   112
	GRAPHICS_ASSERT_DEBUG(srcebmp,EDirectGdiPanicInvalidBitmap);
sl@0
   113
	GRAPHICS_ASSERT_DEBUG(maskbmp,EDirectGdiPanicInvalidBitmap);
sl@0
   114
	
sl@0
   115
	const TDisplayMode maskMode = maskbmp->DisplayMode();
sl@0
   116
	const TInt limit = iDefaultRegionPtr->Count();
sl@0
   117
	TBool opaqueSource = (!IsAlphaChannel(aBitmap.DisplayMode())) && (iDrawMode == DirectGdi::EDrawModePEN);
sl@0
   118
	TRect clipRect;
sl@0
   119
	for (TInt count = 0; count < limit; count++)
sl@0
   120
		{
sl@0
   121
		clipRect = (*iDefaultRegionPtr)[count];
sl@0
   122
		if (!clipRect.Intersects(targetRect))
sl@0
   123
			{
sl@0
   124
			continue;
sl@0
   125
			}
sl@0
   126
		
sl@0
   127
		clipRect.Intersection(targetRect);
sl@0
   128
		TRect clippedSrceRect(clipRect);
sl@0
   129
		clippedSrceRect.Move(offset);
sl@0
   130
		
sl@0
   131
		if (opaqueSource)
sl@0
   132
			{
sl@0
   133
			iDrawMode = DirectGdi::EDrawModeWriteAlpha; // ie write rather than blend
sl@0
   134
			}
sl@0
   135
		
sl@0
   136
		DoBitBltMasked(clipRect.iTl, srcebmp, aBitmap.DataAddress(), clippedSrceRect, maskbmp, 
sl@0
   137
				aMaskBitmap.DataAddress(), aInvertMask);
sl@0
   138
		
sl@0
   139
		if (opaqueSource)
sl@0
   140
			{
sl@0
   141
			iDrawMode = DirectGdi::EDrawModePEN; // set to default
sl@0
   142
			}
sl@0
   143
		iDrawDevice->UpdateRegion(clipRect);
sl@0
   144
		}
sl@0
   145
	
sl@0
   146
	aBitmap.EndDataAccess(ETrue);
sl@0
   147
	aMaskBitmap.EndDataAccess(ETrue);	
sl@0
   148
	}
sl@0
   149
sl@0
   150
sl@0
   151
/**
sl@0
   152
@see MDirectGdiEngine::BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, const TPoint&)
sl@0
   153
@panic DGDIAdapter 7, if either aBitmap or aMaskBitmap are invalid.
sl@0
   154
@panic DGDIAdapter 1022, if the top-left corner of aSrcRect is out of bounds (debug only).
sl@0
   155
*/
sl@0
   156
void CSwDirectGdiEngine::BitBltMasked(const TPoint& aDestPt,
sl@0
   157
		const CFbsBitmap& aBitmap, const TRect& aSrcRect,
sl@0
   158
		const CFbsBitmap& aMaskBitmap, const TPoint& aAlphaPt)
sl@0
   159
	{
sl@0
   160
	if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid))
sl@0
   161
		{
sl@0
   162
		iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps
sl@0
   163
		return;
sl@0
   164
		}
sl@0
   165
	
sl@0
   166
	TRect srcRect(aSrcRect);
sl@0
   167
	//Calculate the destination rect
sl@0
   168
	TPoint destPt(aDestPt + iOrigin);
sl@0
   169
	TRect destRect(destPt, srcRect.Size());
sl@0
   170
	TPoint offset(srcRect.iTl - destPt);
sl@0
   171
	TRect targetRect(destRect);
sl@0
   172
sl@0
   173
	aBitmap.BeginDataAccess();
sl@0
   174
	aMaskBitmap.BeginDataAccess();
sl@0
   175
	CBitwiseBitmap* srcBmp = static_cast<const CSwDirectGdiBitmap&>(aBitmap).Address();
sl@0
   176
	CBitwiseBitmap* alphaBmp = static_cast<const CSwDirectGdiBitmap&>(aMaskBitmap).Address();
sl@0
   177
	GRAPHICS_ASSERT_DEBUG(srcBmp, EDirectGdiPanicInvalidBitmap);
sl@0
   178
	GRAPHICS_ASSERT_DEBUG(alphaBmp, EDirectGdiPanicInvalidBitmap);
sl@0
   179
	TUint32* srcDataAddr = aBitmap.DataAddress();
sl@0
   180
	TUint32* alphaDataAddr = aMaskBitmap.DataAddress();
sl@0
   181
sl@0
   182
	//For each region - find the clipping rect and draw
sl@0
   183
	TInt limit = iDefaultRegionPtr->Count ();
sl@0
   184
	TRect clipRect;
sl@0
   185
	for (TInt count=0; count<limit;count++)
sl@0
   186
		{
sl@0
   187
		clipRect=(*iDefaultRegionPtr)[count];
sl@0
   188
		if ( !clipRect.Intersects(targetRect))
sl@0
   189
			{
sl@0
   190
			continue;
sl@0
   191
			}
sl@0
   192
		//targetRect was constructed from destRect. destRect was constructed from srcRect.
sl@0
   193
		clipRect.Intersection (targetRect);
sl@0
   194
		TRect clippedSrcRect(clipRect);
sl@0
   195
		clippedSrcRect.Move(offset);//clippedSrcRect - maps to a part of srcRect now.
sl@0
   196
		TPoint shift(clippedSrcRect.iTl - srcRect.iTl);
sl@0
   197
		GRAPHICS_ASSERT_DEBUG(shift.iX >= 0, EDirectGdiPanicNegativeShift);
sl@0
   198
		GRAPHICS_ASSERT_DEBUG(shift.iY >= 0, EDirectGdiPanicNegativeShift);
sl@0
   199
		DoBitBltAlpha (clipRect.iTl, srcBmp, srcDataAddr, clippedSrcRect,
sl@0
   200
				alphaBmp, alphaDataAddr, aAlphaPt + shift, EFalse);
sl@0
   201
		iDrawDevice->UpdateRegion (clipRect);
sl@0
   202
		}
sl@0
   203
sl@0
   204
	aBitmap.EndDataAccess(ETrue);
sl@0
   205
	aMaskBitmap.EndDataAccess(ETrue);
sl@0
   206
	return;
sl@0
   207
	}			
sl@0
   208
sl@0
   209
/** 
sl@0
   210
Calculates the position into the scanline for the given x coordinate.
sl@0
   211
sl@0
   212
@param aX The given x-coordinate.
sl@0
   213
@param aDisplayMode The applied display mode.
sl@0
   214
@return The memory offset, or 0 if the mode is not supported.
sl@0
   215
@panic DGDIAdapter 1009, if aDisplayMode is not supported (debug only).
sl@0
   216
*/
sl@0
   217
TUint CSwDirectGdiEngine::MemoryOffsetForPixelPitch(TUint aX, TDisplayMode aDisplayMode) const
sl@0
   218
	{	
sl@0
   219
	switch (aDisplayMode)
sl@0
   220
		{
sl@0
   221
		case EColor16MU:
sl@0
   222
		case EColor16MAP:
sl@0
   223
			return aX << 2;
sl@0
   224
		case EColor64K:
sl@0
   225
			return aX << 1;
sl@0
   226
		default:
sl@0
   227
			GRAPHICS_PANIC_DEBUG(EDirectGdiPanicInvalidDisplayMode);
sl@0
   228
		}
sl@0
   229
	return 0;
sl@0
   230
	}
sl@0
   231
sl@0
   232
TUint32* CSwDirectGdiEngine::GetScanLineOffsetPtr(CBitwiseBitmap* aSrce, TUint32*& aSlptr, 
sl@0
   233
		TInt aLength, TPoint aPixel, TUint32* aBase, 
sl@0
   234
		TLineScanningPosition& aLineScanningPosition, TUint aXOffset)
sl@0
   235
	{
sl@0
   236
	aSrce->GetScanLinePtr(aSlptr, aLength, aPixel, aBase, aLineScanningPosition);
sl@0
   237
	return (TUint32*)((TUint8*)aSlptr + aXOffset);
sl@0
   238
	}
sl@0
   239
sl@0
   240
/**
sl@0
   241
Performs the actual bitblt to the device.
sl@0
   242
This function may also be called by DrawBitmap(), and DrawRect() when using a patterned brush, 
sl@0
   243
so any changes to this function may impact on them also.
sl@0
   244
sl@0
   245
@pre aSrce A bitmap with non-zero dimensions. aSrceRect has been clipped against the target.
sl@0
   246
sl@0
   247
@param aDest The target position on the device which will contain the top left 
sl@0
   248
             corner of the source bitmap.
sl@0
   249
@param aSrce The bitmap object that contains the pixels to draw.
sl@0
   250
@param aBase The address of the bitmap pixels.
sl@0
   251
@param aStride The length in bytes between scanlines in memory.
sl@0
   252
@param aSrceRect The area of the bitmap to draw from.
sl@0
   253
@panic DGDIAdapter 1013, if aDest is fully outside of the bounds of the target, or aSrceRect.iTl is not
sl@0
   254
       within the drawing area (debug only).
sl@0
   255
*/
sl@0
   256
void CSwDirectGdiEngine::DoBitBlt(const TPoint& aDest,
sl@0
   257
		 CBitwiseBitmap* aSrce,
sl@0
   258
		 TUint32* aBase,
sl@0
   259
		 TInt aStride,
sl@0
   260
		 const TRect& aSrceRect)
sl@0
   261
	{
sl@0
   262
	// Does multiple bitmap widths for painting rects only
sl@0
   263
	const TInt width = aSrceRect.Width ();
sl@0
   264
sl@0
   265
#ifdef _DEBUG
sl@0
   266
	TRect deviceDestRect;
sl@0
   267
	iDrawDevice->GetDrawRect(deviceDestRect);
sl@0
   268
	GRAPHICS_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
sl@0
   269
	GRAPHICS_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
sl@0
   270
	GRAPHICS_ASSERT_DEBUG((aDest.iX + aSrceRect.Width()) <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
sl@0
   271
	GRAPHICS_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);
sl@0
   272
	GRAPHICS_ASSERT_DEBUG(aDest.iX >= 0 && aDest.iY >= 0, EDirectGdiPanicOutOfBounds);
sl@0
   273
	GRAPHICS_ASSERT_DEBUG(aSrceRect.iTl.iX >= 0 && aSrceRect.iTl.iY >= 0, EDirectGdiPanicOutOfBounds);
sl@0
   274
#endif
sl@0
   275
sl@0
   276
	TSize srcSize = aSrce->SizeInPixels ();
sl@0
   277
	
sl@0
   278
	const TPoint KZeroPoint(0,0);
sl@0
   279
	TAny* interface = NULL;
sl@0
   280
	if (iDrawMode == DirectGdi::EDrawModeWriteAlpha &&
sl@0
   281
			aSrceRect.iBr.iX <= srcSize.iWidth && 
sl@0
   282
			aSrceRect.iBr.iY <= srcSize.iHeight &&
sl@0
   283
			!aSrce->IsCompressed() && 
sl@0
   284
			aSrce->DisplayMode() == iDrawDevice->DisplayMode() && 
sl@0
   285
			iDrawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone)
sl@0
   286
		{
sl@0
   287
		// Conditions in CFbsBitGc allow for optimised blitting.
sl@0
   288
		// The draw device supports the optimised blitting function.
sl@0
   289
		// Operation may fail regardless due to unacceptable conditions in the draw device.
sl@0
   290
		MFastBlit2* fastBlit = reinterpret_cast<MFastBlit2*>(interface);
sl@0
   291
		if (fastBlit && (fastBlit->WriteBitmapBlock(aDest, aBase, aStride, srcSize, aSrceRect) == KErrNone))			
sl@0
   292
			{
sl@0
   293
			return;
sl@0
   294
			}			
sl@0
   295
		}
sl@0
   296
sl@0
   297
	MFastBlend* fastBlend=NULL;
sl@0
   298
	if (FastBlendInterface(aSrce,NULL,fastBlend)==KErrNone)
sl@0
   299
		{
sl@0
   300
		if (fastBlend->FastBlendBitmap(aDest, aBase, aStride, srcSize, aSrceRect, aSrce->DisplayMode(), GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)== KErrNone)
sl@0
   301
			{
sl@0
   302
			return;
sl@0
   303
			}
sl@0
   304
		}
sl@0
   305
	
sl@0
   306
	const TInt scanLineBytes = iDrawDevice->ScanLineBytes();
sl@0
   307
	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
sl@0
   308
	TPtr8 scanLineDes((TUint8*)scanLineBuffer, scanLineBytes, scanLineBytes);
sl@0
   309
sl@0
   310
	const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
sl@0
   311
	
sl@0
   312
	const TBool useScanLinePtr = (dispMode == aSrce->DisplayMode()) && 
sl@0
   313
		(TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode) >= 8);
sl@0
   314
sl@0
   315
	TUint32* slptr = NULL;
sl@0
   316
	TUint offset = 0;
sl@0
   317
	TUint32* lastScanLine = NULL;
sl@0
   318
	if (useScanLinePtr)
sl@0
   319
		{
sl@0
   320
		lastScanLine = aSrce->ScanLineAddress(aBase, aSrceRect.iBr.iY-1);
sl@0
   321
		}
sl@0
   322
sl@0
   323
	TInt srceWidth = srcSize.iWidth;
sl@0
   324
	TInt partlinestart = aSrceRect.iTl.iX % srceWidth;
sl@0
   325
	
sl@0
   326
	if (partlinestart < 0)
sl@0
   327
		{
sl@0
   328
		partlinestart += srceWidth;
sl@0
   329
		}
sl@0
   330
	
sl@0
   331
	const TInt partlinelength = Min(srceWidth - partlinestart, width);
sl@0
   332
	TInt destX = aDest.iX;
sl@0
   333
	const TInt destXlimit = destX+width;
sl@0
   334
	const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
sl@0
   335
sl@0
   336
	// first part line
sl@0
   337
	if (partlinestart > 0 && partlinelength > 0)
sl@0
   338
		{
sl@0
   339
		TPoint srcecoord1(partlinestart, aSrceRect.iTl.iY);
sl@0
   340
		TInt desty = aDest.iY;
sl@0
   341
sl@0
   342
		TLineScanningPosition lineScanPos(aBase);
sl@0
   343
sl@0
   344
		if (useScanLinePtr)
sl@0
   345
			{
sl@0
   346
			offset = MemoryOffsetForPixelPitch(partlinestart, dispMode);
sl@0
   347
			if (aSrce->IsCompressed ())
sl@0
   348
				{
sl@0
   349
				
sl@0
   350
				while (srcecoord1.iY < aSrceRect.iBr.iY)
sl@0
   351
					{
sl@0
   352
					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
sl@0
   353
							partlinelength, srcecoord1, aBase, lineScanPos, offset);
sl@0
   354
					if (srcecoord1.iY == aSrceRect.iTl.iY)
sl@0
   355
						{
sl@0
   356
						aSrce->SetCompressionBookmark(lineScanPos, aBase, NULL);
sl@0
   357
						}
sl@0
   358
					iDrawDevice->WriteLine(aDest.iX, desty, partlinelength,
sl@0
   359
							scanLineBuffer, drawMode);
sl@0
   360
					srcecoord1.iY++;
sl@0
   361
					desty++;				
sl@0
   362
					}
sl@0
   363
				}
sl@0
   364
			else
sl@0
   365
				{
sl@0
   366
				while (srcecoord1.iY < aSrceRect.iBr.iY)
sl@0
   367
					{
sl@0
   368
					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
sl@0
   369
							partlinelength, srcecoord1, aBase, lineScanPos,
sl@0
   370
							offset);
sl@0
   371
					do
sl@0
   372
						{
sl@0
   373
						iDrawDevice->WriteLine (aDest.iX, desty,
sl@0
   374
								partlinelength, scanLineBuffer, drawMode);
sl@0
   375
						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
sl@0
   376
						srcecoord1.iY++;
sl@0
   377
						desty++;
sl@0
   378
						}
sl@0
   379
					while ((srcecoord1.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine)) ;
sl@0
   380
					}
sl@0
   381
				}
sl@0
   382
			}
sl@0
   383
		else
sl@0
   384
			{
sl@0
   385
			for ( ; srcecoord1.iY < aSrceRect.iBr.iY; srcecoord1.iY++, desty++)
sl@0
   386
				{
sl@0
   387
				aSrce->GetScanLine (scanLineDes, srcecoord1, partlinelength,
sl@0
   388
						EFalse, KZeroPoint, dispMode, aBase, lineScanPos);
sl@0
   389
				if ( srcecoord1.iY==aSrceRect.iTl.iY)
sl@0
   390
					{
sl@0
   391
					aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
sl@0
   392
					}
sl@0
   393
				iDrawDevice->WriteLine (aDest.iX, desty, partlinelength,
sl@0
   394
						scanLineBuffer, drawMode);
sl@0
   395
				}
sl@0
   396
			}
sl@0
   397
sl@0
   398
		destX += partlinelength;
sl@0
   399
		}
sl@0
   400
sl@0
   401
	// multiple complete lines - columns
sl@0
   402
	TInt numcolumns = (destXlimit - destX) / srceWidth;
sl@0
   403
	
sl@0
   404
	if (numcolumns > 0)
sl@0
   405
		{
sl@0
   406
		TPoint srcecoord2(0, aSrceRect.iTl.iY);
sl@0
   407
		TInt desty = aDest.iY;
sl@0
   408
sl@0
   409
		TLineScanningPosition lineScanPos(aBase);
sl@0
   410
sl@0
   411
		if (useScanLinePtr)
sl@0
   412
			{
sl@0
   413
			if (aSrce->IsCompressed())
sl@0
   414
				{
sl@0
   415
				while (srcecoord2.iY < aSrceRect.iBr.iY)
sl@0
   416
					{
sl@0
   417
					TPoint coord(srcecoord2);
sl@0
   418
					aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos);
sl@0
   419
					if (srcecoord2.iY == aSrceRect.iTl.iY)
sl@0
   420
						{
sl@0
   421
						aSrce->SetCompressionBookmark(lineScanPos, aBase, NULL);
sl@0
   422
						}
sl@0
   423
					TInt tempdestX = destX;
sl@0
   424
					for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth)
sl@0
   425
						{
sl@0
   426
						iDrawDevice->WriteLine(tempdestX, desty, srceWidth, slptr, drawMode);
sl@0
   427
						}
sl@0
   428
					srcecoord2.iY++;
sl@0
   429
					desty++;
sl@0
   430
					}
sl@0
   431
				}
sl@0
   432
			else
sl@0
   433
				{
sl@0
   434
				while (srcecoord2.iY < aSrceRect.iBr.iY)
sl@0
   435
					{
sl@0
   436
					TPoint coord(srcecoord2);
sl@0
   437
					aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos);
sl@0
   438
					do
sl@0
   439
						{
sl@0
   440
						TInt tempdestX = destX;
sl@0
   441
						for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth)
sl@0
   442
							{
sl@0
   443
							iDrawDevice->WriteLine (tempdestX, desty, srceWidth, slptr, drawMode);
sl@0
   444
							}
sl@0
   445
						slptr = (TUint32*)((TUint8*)slptr + aStride);
sl@0
   446
						srcecoord2.iY++;
sl@0
   447
						desty++;
sl@0
   448
						}
sl@0
   449
					while ((srcecoord2.iY < aSrceRect.iBr.iY) && (slptr < lastScanLine));
sl@0
   450
					}
sl@0
   451
				}
sl@0
   452
			}
sl@0
   453
		else
sl@0
   454
			{
sl@0
   455
			for (; srcecoord2.iY < aSrceRect.iBr.iY; srcecoord2.iY++, desty++)
sl@0
   456
				{
sl@0
   457
				TInt tempdestX = destX;
sl@0
   458
				TPoint coord(srcecoord2);
sl@0
   459
				aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos);
sl@0
   460
				if (srcecoord2.iY == aSrceRect.iTl.iY)
sl@0
   461
					{
sl@0
   462
					aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
sl@0
   463
					}
sl@0
   464
				for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth)
sl@0
   465
					{
sl@0
   466
					aSrce->GetScanLine(slptr, scanLineDes, coord, srceWidth,
sl@0
   467
							EFalse, KZeroPoint, dispMode);
sl@0
   468
					iDrawDevice->WriteLine(tempdestX, desty, srceWidth, scanLineBuffer, drawMode);
sl@0
   469
					}
sl@0
   470
				}
sl@0
   471
			}
sl@0
   472
sl@0
   473
		destX += numcolumns * srceWidth;
sl@0
   474
		}
sl@0
   475
sl@0
   476
	// final part line
sl@0
   477
	if (destX < destXlimit)
sl@0
   478
		{
sl@0
   479
		const TInt restofline = destXlimit - destX;
sl@0
   480
		TPoint srcecoord3(0, aSrceRect.iTl.iY);
sl@0
   481
		TInt desty = aDest.iY;
sl@0
   482
sl@0
   483
		TLineScanningPosition lineScanPos(aBase);
sl@0
   484
sl@0
   485
		if (useScanLinePtr)
sl@0
   486
			{
sl@0
   487
			offset = 0;
sl@0
   488
			if (aSrce->IsCompressed())
sl@0
   489
				{
sl@0
   490
				while (srcecoord3.iY < aSrceRect.iBr.iY)
sl@0
   491
					{
sl@0
   492
					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
sl@0
   493
							srceWidth, srcecoord3, aBase, lineScanPos, offset);
sl@0
   494
					if (srcecoord3.iY == aSrceRect.iTl.iY)
sl@0
   495
						{
sl@0
   496
						aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
sl@0
   497
						}
sl@0
   498
					iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode);
sl@0
   499
					srcecoord3.iY++;
sl@0
   500
					desty++;
sl@0
   501
					}
sl@0
   502
				}
sl@0
   503
			else
sl@0
   504
				{
sl@0
   505
				while (srcecoord3.iY < aSrceRect.iBr.iY)
sl@0
   506
					{
sl@0
   507
					scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr,
sl@0
   508
							srceWidth, srcecoord3, aBase, lineScanPos, offset);
sl@0
   509
					do
sl@0
   510
						{
sl@0
   511
						iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode);
sl@0
   512
						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride);
sl@0
   513
						srcecoord3.iY++;
sl@0
   514
						desty++;
sl@0
   515
						}
sl@0
   516
					while ((srcecoord3.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
sl@0
   517
					}
sl@0
   518
				}
sl@0
   519
			}
sl@0
   520
		else
sl@0
   521
			{
sl@0
   522
			for (; srcecoord3.iY < aSrceRect.iBr.iY; srcecoord3.iY++, desty++)
sl@0
   523
				{
sl@0
   524
				aSrce->GetScanLine (scanLineDes, srcecoord3, srceWidth, EFalse,
sl@0
   525
						KZeroPoint, dispMode, aBase, lineScanPos);
sl@0
   526
				if (srcecoord3.iY == aSrceRect.iTl.iY)
sl@0
   527
					{
sl@0
   528
					aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL);
sl@0
   529
					}
sl@0
   530
				iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode);
sl@0
   531
				}
sl@0
   532
			}
sl@0
   533
		}
sl@0
   534
	}
sl@0
   535
/** 
sl@0
   536
Performs the masked bitblt to the device.
sl@0
   537
sl@0
   538
@param aDest The target position on the device which will contain the top left 
sl@0
   539
             corner of the source bitmap.
sl@0
   540
@param aSourceBitmap The bitmap object that contains the pixels to draw.
sl@0
   541
@param aSourceBase The address of the source bitmap pixels.
sl@0
   542
@param aSourceRect The area of the bitmap to draw from.
sl@0
   543
@param aMaskBitmap The bitmap object that contains the mask.
sl@0
   544
@param aMaskBase The address of the mask pixels.
sl@0
   545
@param aInvertMask Inverts the mask if ETrue.
sl@0
   546
@panic DGDIAdapter 1013, if aDest is outside of the device bounds (debug only).
sl@0
   547
*/
sl@0
   548
void CSwDirectGdiEngine::DoBitBltMasked(const TPoint& aDest,
sl@0
   549
		   CBitwiseBitmap* aSourceBitmap,
sl@0
   550
		   TUint32* aSourceBase,
sl@0
   551
		   const TRect& aSourceRect,
sl@0
   552
		   CBitwiseBitmap* aMaskBitmap,
sl@0
   553
		   TUint32* aMaskBase,
sl@0
   554
		   TBool aInvertMask)
sl@0
   555
	{
sl@0
   556
#ifdef _DEBUG
sl@0
   557
	TRect deviceDestRect;
sl@0
   558
	iDrawDevice->GetDrawRect (deviceDestRect);
sl@0
   559
#endif
sl@0
   560
	
sl@0
   561
    GRAPHICS_ASSERT_DEBUG (aDest.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
sl@0
   562
	GRAPHICS_ASSERT_DEBUG (aDest.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
sl@0
   563
	GRAPHICS_ASSERT_DEBUG ((aDest.iX + aSourceRect.Width()) <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
sl@0
   564
	GRAPHICS_ASSERT_DEBUG ((aDest.iY + aSourceRect.Height()) <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);	
sl@0
   565
	const TPoint KZeroPoint(0,0);
sl@0
   566
sl@0
   567
	MFastBlend* fastBlend=NULL;
sl@0
   568
	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
sl@0
   569
		{
sl@0
   570
		if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
sl@0
   571
							aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aSourceRect.iTl, aInvertMask,
sl@0
   572
							GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone)
sl@0
   573
			{
sl@0
   574
			return;
sl@0
   575
			}
sl@0
   576
		}
sl@0
   577
	
sl@0
   578
	if (aMaskBitmap->DisplayMode() == EGray256)
sl@0
   579
		{
sl@0
   580
		DoBitBltAlpha (aDest, aSourceBitmap, aSourceBase, aSourceRect,
sl@0
   581
				aMaskBitmap, aMaskBase, aSourceRect.iTl, EFalse);
sl@0
   582
		}
sl@0
   583
	// if screen driver is 16MAP we avoid logical operator pen modes by using DoBitBltAlpha() for blitting
sl@0
   584
	else if(iDrawDevice->ScanLineDisplayMode() == EColor16MAP)
sl@0
   585
		{
sl@0
   586
		DoBitBltAlpha (aDest, aSourceBitmap, aSourceBase, aSourceRect,
sl@0
   587
				aMaskBitmap, aMaskBase, aSourceRect.iTl, aInvertMask);
sl@0
   588
		}
sl@0
   589
	else if (aSourceBitmap == aMaskBitmap)
sl@0
   590
		{
sl@0
   591
		const TInt width = aSourceRect.Width();
sl@0
   592
		const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
sl@0
   593
		const CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeOR;
sl@0
   594
		TPoint srcePoint(aSourceRect.iTl);
sl@0
   595
		TInt destY = aDest.iY;
sl@0
   596
		
sl@0
   597
		TLineScanningPosition lineScanPos(aSourceBase);
sl@0
   598
sl@0
   599
		const TBool useScanLinePtr = (dispMode == aSourceBitmap->DisplayMode() && 
sl@0
   600
				(TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8));
sl@0
   601
sl@0
   602
		if (useScanLinePtr)
sl@0
   603
			{
sl@0
   604
			TUint32* scanLineBuffer = NULL;
sl@0
   605
			TUint32* slptr = NULL;
sl@0
   606
			TUint offset = MemoryOffsetForPixelPitch (srcePoint.iX, dispMode);
sl@0
   607
sl@0
   608
			if (aSourceBitmap->IsCompressed())
sl@0
   609
				{
sl@0
   610
				for ( ; srcePoint.iY < aSourceRect.iBr.iY; destY++,
sl@0
   611
						srcePoint.iY++)
sl@0
   612
					{
sl@0
   613
					scanLineBuffer = GetScanLineOffsetPtr (
sl@0
   614
							aSourceBitmap, slptr, width, srcePoint,
sl@0
   615
							aSourceBase, lineScanPos, offset);
sl@0
   616
					
sl@0
   617
					iDrawDevice->WriteLine (aDest.iX, destY, width,
sl@0
   618
							scanLineBuffer, drawMode);
sl@0
   619
					}
sl@0
   620
				}
sl@0
   621
			else
sl@0
   622
				{
sl@0
   623
				TUint stride = aSourceBitmap->DataStride ();
sl@0
   624
				TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase, aSourceRect.iBr.iY-1);
sl@0
   625
sl@0
   626
				while (srcePoint.iY < aSourceRect.iBr.iY)
sl@0
   627
					{
sl@0
   628
					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint,
sl@0
   629
							aSourceBase, lineScanPos, offset);
sl@0
   630
					do
sl@0
   631
						{
sl@0
   632
						iDrawDevice->WriteLine (aDest.iX, destY, width, scanLineBuffer, drawMode);
sl@0
   633
						scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + stride);
sl@0
   634
						destY++;
sl@0
   635
						srcePoint.iY++;
sl@0
   636
						}
sl@0
   637
					while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLine));
sl@0
   638
					}
sl@0
   639
				}
sl@0
   640
			}
sl@0
   641
		else
sl@0
   642
			{
sl@0
   643
			const TInt scanLineBytes = iDrawDevice->ScanLineBytes();
sl@0
   644
			TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
sl@0
   645
			TPtr8 scanLineDes((TUint8*)scanLineBuffer, scanLineBytes,
sl@0
   646
					scanLineBytes);
sl@0
   647
			for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,
sl@0
   648
					srcePoint.iY++)
sl@0
   649
				{
sl@0
   650
				aSourceBitmap->GetScanLine (scanLineDes, srcePoint,
sl@0
   651
						width, EFalse, KZeroPoint, dispMode,
sl@0
   652
						aSourceBase, lineScanPos);
sl@0
   653
sl@0
   654
				iDrawDevice->WriteLine (aDest.iX, destY, width,
sl@0
   655
						scanLineBuffer, drawMode);
sl@0
   656
				}
sl@0
   657
			}
sl@0
   658
		}
sl@0
   659
	else
sl@0
   660
		{
sl@0
   661
		DoBitBltMaskedFlicker(aDest, aSourceBitmap, aSourceBase,
sl@0
   662
				aSourceRect, aMaskBitmap, aMaskBase, aInvertMask);		
sl@0
   663
		}
sl@0
   664
	}
sl@0
   665
		
sl@0
   666
/**
sl@0
   667
@see DoBitBltMasked()
sl@0
   668
 */
sl@0
   669
void CSwDirectGdiEngine::DoBitBltMaskedFlicker(const TPoint& aDest,
sl@0
   670
				  CBitwiseBitmap* aSourceBitmap,
sl@0
   671
				  TUint32* aSourceBase,
sl@0
   672
				  const TRect& aSourceRect,
sl@0
   673
				  CBitwiseBitmap* aMaskBitmap,
sl@0
   674
				  TUint32* aMaskBase,
sl@0
   675
				  TBool aInvertMask)
sl@0
   676
	{
sl@0
   677
	const TInt width = aSourceRect.Width();
sl@0
   678
	TInt destY = aDest.iY;
sl@0
   679
	TPoint srcePoint(aSourceRect.iTl);
sl@0
   680
	
sl@0
   681
	TLineScanningPosition lineScanPos(aSourceBase);
sl@0
   682
	TLineScanningPosition lineScanPosMask(aMaskBase);
sl@0
   683
	
sl@0
   684
	const TDisplayMode srcFormat = aSourceBitmap->DisplayMode();
sl@0
   685
	const TDisplayMode maskFormat = aMaskBitmap->DisplayMode();
sl@0
   686
	
sl@0
   687
	if (aMaskBitmap->IsCompressed()) 
sl@0
   688
		{ 
sl@0
   689
		HBufC8* hBuf = CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4);
sl@0
   690
		if (!hBuf) 
sl@0
   691
			{
sl@0
   692
			iDriver->SetError(KErrNoMemory);
sl@0
   693
			return; // Out of memory so do not draw anything 
sl@0
   694
			}
sl@0
   695
		lineScanPosMask.iScanLineBuffer = hBuf; 
sl@0
   696
		} 
sl@0
   697
	
sl@0
   698
	TAny* interface = NULL;
sl@0
   699
	if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) &&
sl@0
   700
			maskFormat == EGray2 && 
sl@0
   701
			aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
sl@0
   702
			aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
sl@0
   703
			iDrawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
sl@0
   704
		{
sl@0
   705
		// Parameters allow optimised code path
sl@0
   706
		TInt length = width;
sl@0
   707
		TUint32* srcPtr=NULL;
sl@0
   708
		TUint32* maskPtr=NULL;
sl@0
   709
		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
sl@0
   710
		while (srcePoint.iY < aSourceRect.iBr.iY)
sl@0
   711
			{
sl@0
   712
			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos);
sl@0
   713
			aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask);
sl@0
   714
			
sl@0
   715
			fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask);
sl@0
   716
			
sl@0
   717
			destY++;
sl@0
   718
			++srcePoint.iY;
sl@0
   719
			}
sl@0
   720
		return;
sl@0
   721
		}
sl@0
   722
	
sl@0
   723
	const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
sl@0
   724
	const CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeANDNOT;
sl@0
   725
	
sl@0
   726
	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
sl@0
   727
	const TInt scanLineBytes = iDrawDevice->ScanLineBytes();
sl@0
   728
	TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes);
sl@0
   729
	TLineScanningPosition lineScanPos2(aSourceBase);
sl@0
   730
	const TPoint KZeroPoint(0,0);
sl@0
   731
	
sl@0
   732
	//scanline modifications required if using different modes, bits per pixel less than 8
sl@0
   733
	if ( (dispMode == aSourceBitmap->DisplayMode()) && 
sl@0
   734
			(TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8))
sl@0
   735
		{
sl@0
   736
		TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode);
sl@0
   737
		TUint32* slptr=NULL;
sl@0
   738
		//mask scanline modifications required for EInvertPen, different screen modes
sl@0
   739
		if ((drawMode != CGraphicsContext::EDrawModeANDNOT) && (dispMode == aMaskBitmap->DisplayMode()))
sl@0
   740
			{
sl@0
   741
			TUint32* scanLineBufferMask = NULL;
sl@0
   742
			//stride jumping not possible with compressed bitmaps
sl@0
   743
			if (aSourceBitmap->IsCompressed() || aMaskBitmap->IsCompressed())
sl@0
   744
				{
sl@0
   745
				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++)
sl@0
   746
					{
sl@0
   747
					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
sl@0
   748
					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer, CGraphicsContext::EDrawModeXOR);
sl@0
   749
					scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
sl@0
   750
					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
sl@0
   751
					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer, CGraphicsContext::EDrawModeXOR);
sl@0
   752
					}
sl@0
   753
				}
sl@0
   754
			else
sl@0
   755
				{
sl@0
   756
				TUint strideSrc = aSourceBitmap->DataStride();
sl@0
   757
				TUint strideMask = aMaskBitmap->DataStride();
sl@0
   758
				TUint32* lastScanLineSrc = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
sl@0
   759
				TUint32* lastScanLineMask = aMaskBitmap->ScanLineAddress(aMaskBase,aSourceRect.iBr.iY-1);
sl@0
   760
sl@0
   761
				while (srcePoint.iY < aSourceRect.iBr.iY)
sl@0
   762
					{
sl@0
   763
					scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
sl@0
   764
					scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset);
sl@0
   765
					do
sl@0
   766
						{
sl@0
   767
						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
sl@0
   768
						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode);
sl@0
   769
						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
sl@0
   770
						destY++;
sl@0
   771
						srcePoint.iY++;
sl@0
   772
						}
sl@0
   773
					while ((srcePoint.iY < aSourceRect.iBr.iY) && 
sl@0
   774
							(scanLineBuffer < lastScanLineSrc) && 
sl@0
   775
							(scanLineBufferMask < lastScanLineMask)	&& 
sl@0
   776
							((scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + strideSrc))>(TUint32*)0) && 
sl@0
   777
							((scanLineBufferMask = (TUint32*)((TUint8*)scanLineBufferMask + strideMask))>(TUint32*)0) );
sl@0
   778
					}
sl@0
   779
				}
sl@0
   780
			}
sl@0
   781
		else
sl@0
   782
			{
sl@0
   783
			TUint32* scanLineBufferPtr = NULL;
sl@0
   784
			//stride jumping not possible with compressed bitmaps
sl@0
   785
			if (aSourceBitmap->IsCompressed())
sl@0
   786
				{
sl@0
   787
				for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++)
sl@0
   788
					{
sl@0
   789
					scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
sl@0
   790
					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
sl@0
   791
					aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint, dispMode, aMaskBase, lineScanPosMask);
sl@0
   792
					TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
sl@0
   793
					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
sl@0
   794
					iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
sl@0
   795
					}
sl@0
   796
				}
sl@0
   797
			else
sl@0
   798
				{
sl@0
   799
				TUint stride = aSourceBitmap->DataStride();
sl@0
   800
				TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1);
sl@0
   801
				while (srcePoint.iY < aSourceRect.iBr.iY)
sl@0
   802
					{
sl@0
   803
					scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset);
sl@0
   804
					do
sl@0
   805
						{
sl@0
   806
						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
sl@0
   807
						aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse, KZeroPoint, dispMode,aMaskBase, lineScanPosMask);
sl@0
   808
						TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
sl@0
   809
						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
sl@0
   810
						iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR);
sl@0
   811
						destY++;
sl@0
   812
						srcePoint.iY++;
sl@0
   813
						}
sl@0
   814
					while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBufferPtr < lastScanLine) && 
sl@0
   815
							((scanLineBufferPtr = (TUint32*)((TUint8*)scanLineBufferPtr + stride))>(TUint32*)0));
sl@0
   816
					}
sl@0
   817
				}
sl@0
   818
			}
sl@0
   819
		}
sl@0
   820
	else
sl@0
   821
		{
sl@0
   822
		for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++)
sl@0
   823
			{
sl@0
   824
			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse, KZeroPoint,
sl@0
   825
					dispMode,aSourceBase,lineScanPos);
sl@0
   826
			
sl@0
   827
			iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
sl@0
   828
			aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint, dispMode,
sl@0
   829
					aMaskBase, lineScanPosMask);
sl@0
   830
			TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode);
sl@0
   831
			iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode);
sl@0
   832
			aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint ,dispMode,
sl@0
   833
					aSourceBase,lineScanPos2);		
sl@0
   834
			
sl@0
   835
			iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
sl@0
   836
			}
sl@0
   837
		}
sl@0
   838
	}		
sl@0
   839
				
sl@0
   840
/**
sl@0
   841
@see DoBitBltMasked()
sl@0
   842
 */
sl@0
   843
void CSwDirectGdiEngine::DoBitBltAlpha(const TPoint& aDest ,CBitwiseBitmap* aSourceBitmap,
sl@0
   844
		TUint32* aSourceBase, const TRect& aSourceRect,
sl@0
   845
		CBitwiseBitmap* aMaskBitmap, TUint32* aMaskBase,
sl@0
   846
		const TPoint& aAlphaPoint, TBool aInvertMask)
sl@0
   847
	{
sl@0
   848
	MFastBlend* fastBlend=NULL;
sl@0
   849
	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
sl@0
   850
		{
sl@0
   851
		if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(),
sl@0
   852
							aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aAlphaPoint, aInvertMask,
sl@0
   853
							GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone)
sl@0
   854
			{
sl@0
   855
			return;
sl@0
   856
			}
sl@0
   857
		}
sl@0
   858
sl@0
   859
	const TPoint KZeroPoint(0,0);
sl@0
   860
	const TInt KScanLineLength = 256;
sl@0
   861
	const TInt KRgbSize = 4;
sl@0
   862
	
sl@0
   863
	TUint8 srceRgbBuffer[KScanLineLength * KRgbSize];
sl@0
   864
	TUint8 maskBuffer[KScanLineLength];
sl@0
   865
	TUint8* srceRgbBufferPtr(srceRgbBuffer);
sl@0
   866
	
sl@0
   867
	TPtr8 srceRgbDes(srceRgbBuffer, KScanLineLength * KRgbSize, KScanLineLength * KRgbSize);
sl@0
   868
	TPtr8 maskDes(maskBuffer, KScanLineLength, KScanLineLength);	
sl@0
   869
	
sl@0
   870
	TInt srceY = aSourceRect.iTl.iY;
sl@0
   871
	TInt destY = aDest.iY;
sl@0
   872
	TInt alphaY = aAlphaPoint.iY;
sl@0
   873
	
sl@0
   874
	TLineScanningPosition lineScanPosSrc(aSourceBase);
sl@0
   875
	TLineScanningPosition lineScanPosMask(aMaskBase);
sl@0
   876
	TDisplayMode sourceMode = aSourceBitmap->DisplayMode();
sl@0
   877
	
sl@0
   878
	if (aMaskBitmap->IsCompressed())
sl@0
   879
		{
sl@0
   880
		HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
sl@0
   881
		if (hBuf == NULL)
sl@0
   882
			{
sl@0
   883
			iDriver->SetError(KErrNoMemory); // Out of memory so do not draw anything
sl@0
   884
			return;
sl@0
   885
			}
sl@0
   886
		lineScanPosMask.iScanLineBuffer = hBuf;
sl@0
   887
		}
sl@0
   888
	
sl@0
   889
	TAny* interface = NULL;
sl@0
   890
	if ( (sourceMode == EColor16MU || sourceMode == EColor64K) &&
sl@0
   891
		aMaskBitmap->DisplayMode() == EGray256 && // ensure a monochrome mask isn't passed in as an alpha channel
sl@0
   892
		aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth &&
sl@0
   893
		aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight &&
sl@0
   894
		iDrawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone )
sl@0
   895
		{
sl@0
   896
		TInt length = aSourceRect.Width();
sl@0
   897
		const TInt srceX = aSourceRect.iTl.iX;
sl@0
   898
		const TInt alphaX = aAlphaPoint.iX;
sl@0
   899
		const TInt destX = aDest.iX;
sl@0
   900
		MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
sl@0
   901
		
sl@0
   902
		while (srceY < aSourceRect.iBr.iY)
sl@0
   903
			{
sl@0
   904
			TUint32* srcPtr;
sl@0
   905
			TUint32* maskPtr;
sl@0
   906
			TPoint srcPoint(srceX, srceY);
sl@0
   907
			TPoint maskPoint(alphaX, alphaY);
sl@0
   908
			
sl@0
   909
			aSourceBitmap->GetScanLinePtr(srcPtr, length, srcPoint, aSourceBase, lineScanPosSrc);
sl@0
   910
			aMaskBitmap->GetScanLinePtr(maskPtr, length, maskPoint, aMaskBase, lineScanPosMask);
sl@0
   911
			
sl@0
   912
			fastBlit->WriteAlphaLineEx(destX, destY, length, srceX, srcPtr,
sl@0
   913
					sourceMode, alphaX, maskPtr, MAlphaBlend::EShdwBefore);
sl@0
   914
			srceY++;
sl@0
   915
			destY++;
sl@0
   916
			alphaY++;
sl@0
   917
			}
sl@0
   918
		
sl@0
   919
		return;
sl@0
   920
		}
sl@0
   921
	
sl@0
   922
	const TBool useScanLinePtr = ( (EColor16MA == aSourceBitmap->DisplayMode()));
sl@0
   923
	TUint32* slptr = NULL;
sl@0
   924
	TUint offset = 0;
sl@0
   925
	
sl@0
   926
	while (srceY < aSourceRect.iBr.iY)
sl@0
   927
		{
sl@0
   928
		TInt srceX = aSourceRect.iTl.iX;
sl@0
   929
		TInt destX = aDest.iX;
sl@0
   930
		TInt alphaX = aAlphaPoint.iX;
sl@0
   931
		
sl@0
   932
		while (srceX < aSourceRect.iBr.iX)
sl@0
   933
			{
sl@0
   934
			TPoint srcePoint(srceX,srceY);
sl@0
   935
			TPoint alphaPoint(alphaX,alphaY);
sl@0
   936
			const TInt width = Min(KScanLineLength, aSourceRect.iBr.iX - srceX);
sl@0
   937
			
sl@0
   938
			if (useScanLinePtr)
sl@0
   939
				{
sl@0
   940
				offset = MemoryOffsetForPixelPitch(srceX, EColor16MU);
sl@0
   941
				srceRgbBufferPtr = (TUint8*)GetScanLineOffsetPtr(aSourceBitmap, slptr, width, 
sl@0
   942
						                       srcePoint, aSourceBase, lineScanPosSrc, offset);
sl@0
   943
				}
sl@0
   944
			else
sl@0
   945
				{
sl@0
   946
				aSourceBitmap->GetScanLine(srceRgbDes,srcePoint,width,EFalse,KZeroPoint,
sl@0
   947
						               ERgb,aSourceBase,lineScanPosSrc);
sl@0
   948
				}
sl@0
   949
			
sl@0
   950
			aMaskBitmap->GetScanLine(maskDes, alphaPoint, width, EFalse, KZeroPoint,
sl@0
   951
					                EGray256, aMaskBase, lineScanPosMask);
sl@0
   952
			TileScanLine(maskDes, width, alphaPoint, aMaskBitmap, lineScanPosMask, aMaskBase, EGray256);
sl@0
   953
			
sl@0
   954
			// aInvertMask is not used for alpha channels (EGray256 mask)
sl@0
   955
			if (aInvertMask && aMaskBitmap->DisplayMode() != EGray256)
sl@0
   956
				{
sl@0
   957
				for (TInt i = 0; i < width; ++i)
sl@0
   958
					{
sl@0
   959
					maskBuffer[i] = ~maskBuffer[i];
sl@0
   960
					}
sl@0
   961
				}
sl@0
   962
			
sl@0
   963
			iDrawDevice->WriteRgbAlphaLine(destX, destY, width, srceRgbBufferPtr, maskBuffer, GcDrawMode(iDrawMode));
sl@0
   964
			
sl@0
   965
			srceX += KScanLineLength;
sl@0
   966
			destX += KScanLineLength;
sl@0
   967
			alphaX += KScanLineLength;
sl@0
   968
			}
sl@0
   969
		
sl@0
   970
		srceY++;
sl@0
   971
		destY++;
sl@0
   972
		alphaY++;
sl@0
   973
		}		
sl@0
   974
	}
sl@0
   975
sl@0
   976
/**
sl@0
   977
Tiles the scan line if its length in pixels is less than aLengthInPixels.
sl@0
   978
sl@0
   979
@param aScanLine A pointer to the scan line buffer.
sl@0
   980
@param aLengthInPixels The scan line size in pixels.
sl@0
   981
@param aSrcPt Position of the first pixel in aMaskBitmap that should be used as a source
sl@0
   982
              for the pixels in scan line buffer.
sl@0
   983
@param aMaskBitmap Any additional pixels for the scan line buffer will be taken from here.
sl@0
   984
@param aScanLinePos This argument is used for some internal optimisations. It should not be
sl@0
   985
                    modified by the caller.
sl@0
   986
@param aMaskBase The base address of aMaskBitmap data.
sl@0
   987
@param aDisplayMode Any additional pixels should be taken from aMaskBitmap using aDisplayMode
sl@0
   988
                    as an argument for GetScanLine() call.
sl@0
   989
@panic DGDIAdapter 1021, if the memory required for the scanline is greater than the size of aScanLine (debug only).
sl@0
   990
*/
sl@0
   991
void CSwDirectGdiEngine::TileScanLine(TPtr8& aScanLine,
sl@0
   992
						  TInt aLengthInPixels,
sl@0
   993
						  const TPoint& aSrcPt,
sl@0
   994
						  const CBitwiseBitmap* aMaskBitmap,
sl@0
   995
						  TLineScanningPosition& aScanLinePos,
sl@0
   996
						  TUint32* aMaskBase,
sl@0
   997
						  TDisplayMode aDisplayMode
sl@0
   998
						  )
sl@0
   999
	{
sl@0
  1000
	TInt lengthInBytes = CFbsBitmap::ScanLineLength(aLengthInPixels, aDisplayMode);
sl@0
  1001
	GRAPHICS_ASSERT_DEBUG(lengthInBytes <= aScanLine.MaxLength(), EDirectGdiPanicInvalidArg);
sl@0
  1002
	TInt scanLineLength = aScanLine.Length();
sl@0
  1003
	if(scanLineLength < lengthInBytes && aSrcPt.iX > 0)
sl@0
  1004
		{
sl@0
  1005
		//If, for example, src bmp is 100 pixels width, mask bmp is 20 pixels width and src
sl@0
  1006
		//rect is (10, 0, 100, 1) -> We will read only pixels 10..19 from the first scan line
sl@0
  1007
		//of the mask bmp. We have to have 90 mask bmp pixels.
sl@0
  1008
		//So we have to make a second mask bmp read startig from pixel 0 - 10 pixels length.
sl@0
  1009
		TInt maxLen = Min(aScanLine.MaxLength() - scanLineLength, aSrcPt.iX);
sl@0
  1010
		TPtr8 maskDes2(const_cast <TUint8*> (aScanLine.Ptr()) + scanLineLength, maxLen, maxLen);
sl@0
  1011
		TPoint srcPt(0, aSrcPt.iY);
sl@0
  1012
		TPoint zeroPt(0, 0);
sl@0
  1013
		aMaskBitmap->GetScanLine(maskDes2, srcPt, maxLen, EFalse, zeroPt, aDisplayMode, aMaskBase, aScanLinePos);
sl@0
  1014
		aScanLine.SetLength(scanLineLength + maskDes2.Length());
sl@0
  1015
		scanLineLength = aScanLine.Length();
sl@0
  1016
		}
sl@0
  1017
	if(scanLineLength >= lengthInBytes || scanLineLength == 0)
sl@0
  1018
		{
sl@0
  1019
		return;
sl@0
  1020
		}
sl@0
  1021
	//If we still don't have enough mask bmp pixels - we have to tile the scan line
sl@0
  1022
	TInt repeatCnt = lengthInBytes / scanLineLength - 1;
sl@0
  1023
	TInt bytesLeft = lengthInBytes % scanLineLength;
sl@0
  1024
	const TUint8* src = aScanLine.Ptr();
sl@0
  1025
	TUint8* dest = const_cast <TUint8*> (src) + scanLineLength;
sl@0
  1026
	for(;repeatCnt>0;dest+=scanLineLength,repeatCnt--)
sl@0
  1027
		{
sl@0
  1028
		Mem::Copy(dest, src, scanLineLength);
sl@0
  1029
		}
sl@0
  1030
	if(bytesLeft)
sl@0
  1031
		{
sl@0
  1032
		Mem::Copy(dest, src, bytesLeft);
sl@0
  1033
		}
sl@0
  1034
	aScanLine.SetLength(lengthInBytes);
sl@0
  1035
	}
sl@0
  1036
sl@0
  1037
/**
sl@0
  1038
Draws a masked rectangular section of the source bitmap and does a compress/stretch to 
sl@0
  1039
fit a given destination rectangle. It uses DoBitBltMasked() if no stretching is involved. 
sl@0
  1040
sl@0
  1041
@see DrawBitmapMasked()
sl@0
  1042
sl@0
  1043
@param aDestRect The target position on the device containing the top left corner of the source bitmap.
sl@0
  1044
@param aSourceBitmap The bitmap object that contains the pixels to draw.
sl@0
  1045
@param aSourceBase The address of the source bitmap pixels.
sl@0
  1046
@param aSourceRect The area of the bitmap to draw from.
sl@0
  1047
@param aMaskBitmap The bitmap object that contains the mask.
sl@0
  1048
@param aMaskBase The address of the mask pixels.
sl@0
  1049
@param aInvertMask Inverts the mask if ETrue.
sl@0
  1050
@param aClipRect A clipping rectangle.
sl@0
  1051
@panic DGDIAdapter 1013, if the clipping rectangle is fully outside of the device bounds (debug only).
sl@0
  1052
*/
sl@0
  1053
void CSwDirectGdiEngine::DoDrawBitmapMasked(const TRect& aDestRect,
sl@0
  1054
							   CBitwiseBitmap* aSourceBitmap,
sl@0
  1055
							   TUint32* aSourceBase,
sl@0
  1056
							   const TRect& aSourceRect,
sl@0
  1057
							   CBitwiseBitmap* aMaskBitmap,
sl@0
  1058
							   TUint32* aMaskBase,
sl@0
  1059
							   TBool aInvertMask,
sl@0
  1060
							   const TRect& aClipRect)
sl@0
  1061
	{
sl@0
  1062
	CFbsDrawDevice* drawDevice = iDrawDevice;
sl@0
  1063
#ifdef _DEBUG
sl@0
  1064
	TRect deviceDestRect;
sl@0
  1065
	drawDevice->GetDrawRect(deviceDestRect);
sl@0
  1066
	GRAPHICS_ASSERT_DEBUG(aClipRect.iTl.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
sl@0
  1067
	GRAPHICS_ASSERT_DEBUG(aClipRect.iTl.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
sl@0
  1068
	GRAPHICS_ASSERT_DEBUG(aClipRect.iBr.iX <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
sl@0
  1069
	GRAPHICS_ASSERT_DEBUG(aClipRect.iBr.iY <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);
sl@0
  1070
#endif
sl@0
  1071
sl@0
  1072
	// The clipped version of the destination rectangle
sl@0
  1073
	TRect clippedDestRect(aDestRect);
sl@0
  1074
	clippedDestRect.Intersection(aClipRect);
sl@0
  1075
sl@0
  1076
	// If the source rectangle and the destination rectangle are same,
sl@0
  1077
	// no stretch/compress operation required, just do BitBltMasked
sl@0
  1078
	if (aDestRect.Size() == aSourceRect.Size())
sl@0
  1079
		{
sl@0
  1080
		if (!clippedDestRect.IsEmpty())
sl@0
  1081
			{
sl@0
  1082
			const TPoint destPoint(clippedDestRect.iTl);
sl@0
  1083
			clippedDestRect.Move(aSourceRect.iTl - aDestRect.iTl);
sl@0
  1084
			DoBitBltMasked(destPoint,
sl@0
  1085
						   aSourceBitmap,
sl@0
  1086
						   aSourceBase,
sl@0
  1087
						   clippedDestRect,
sl@0
  1088
						   aMaskBitmap,
sl@0
  1089
						   aMaskBase,
sl@0
  1090
						   aInvertMask);
sl@0
  1091
			}
sl@0
  1092
		return;
sl@0
  1093
		}
sl@0
  1094
sl@0
  1095
	MFastBlend* fastBlend=NULL;
sl@0
  1096
	if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone)
sl@0
  1097
		{
sl@0
  1098
		if (fastBlend->FastBlendBitmapMaskedScaled(aClipRect, aDestRect, aSourceRect, aSourceBase, aSourceBitmap->DataStride(),
sl@0
  1099
				aSourceBitmap->DisplayMode(),aSourceBitmap->SizeInPixels(), 
sl@0
  1100
				aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aInvertMask, 
sl@0
  1101
				GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone)
sl@0
  1102
			{
sl@0
  1103
			return;
sl@0
  1104
			}
sl@0
  1105
		}
sl@0
  1106
	
sl@0
  1107
	TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
sl@0
  1108
	const TInt scanLineBytes = drawDevice->ScanLineBytes();
sl@0
  1109
	TPtr8 scanLineDes(reinterpret_cast<TUint8*>(scanLineBuffer),scanLineBytes,scanLineBytes);
sl@0
  1110
sl@0
  1111
	const TInt KScanLineLength = 256;
sl@0
  1112
	const TInt KRgbSize = 4;
sl@0
  1113
	TUint8 maskBuffer[KScanLineLength];
sl@0
  1114
sl@0
  1115
	TUint8 sourceBuffer[KScanLineLength*KRgbSize];
sl@0
  1116
	TPtr8 sourceDes(sourceBuffer,KScanLineLength*KRgbSize,KScanLineLength*KRgbSize);
sl@0
  1117
sl@0
  1118
	const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
sl@0
  1119
	CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeANDNOT;
sl@0
  1120
	// If the source bitmap and the mask bitmap are same, draw the source bitmap either
sl@0
  1121
	// with EDrawModeAND or EDrawModeOR based on aInvertMask parameter.
sl@0
  1122
	if (aSourceBitmap == aMaskBitmap)
sl@0
  1123
		{
sl@0
  1124
		drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeOR;
sl@0
  1125
		}
sl@0
  1126
sl@0
  1127
	TLinearDDA xLine;
sl@0
  1128
	TInt bitmapXStart = 0;
sl@0
  1129
	xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
sl@0
  1130
					TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
sl@0
  1131
	xLine.JumpToYCoord2(bitmapXStart,clippedDestRect.iTl.iX);
sl@0
  1132
sl@0
  1133
	TLinearDDA yLine;
sl@0
  1134
	TPoint yCoord(aSourceRect.iTl.iY,aDestRect.iTl.iY);
sl@0
  1135
	yLine.Construct(yCoord,TPoint(aSourceRect.iBr.iY,aDestRect.iBr.iY),TLinearDDA::ELeft);
sl@0
  1136
	TInt dummy;
sl@0
  1137
	yLine.JumpToYCoord2(dummy,clippedDestRect.iTl.iY);
sl@0
  1138
	yCoord.SetXY(dummy,clippedDestRect.iTl.iY);
sl@0
  1139
sl@0
  1140
	const TInt srceWidth = aSourceRect.Width();
sl@0
  1141
	const TInt destWidth = aDestRect.Width();
sl@0
  1142
	const TInt clipWidth = clippedDestRect.Width();
sl@0
  1143
	const TInt clipStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
sl@0
  1144
	const TInt sourceBmpWidth = aSourceBitmap->SizeInPixels().iWidth;
sl@0
  1145
	const TInt maskWidth = aMaskBitmap->SizeInPixels().iWidth;
sl@0
  1146
	const TInt maskHeight = aMaskBitmap->SizeInPixels().iHeight;
sl@0
  1147
sl@0
  1148
	TLineScanningPosition lineScanPos(aSourceBase);
sl@0
  1149
	TLineScanningPosition lineScanPos2(aSourceBase);
sl@0
  1150
	TLineScanningPosition lineScanPosMask(aMaskBase);
sl@0
  1151
sl@0
  1152
	HBufC8* alphaBuffer = NULL;
sl@0
  1153
	TPtr8 alphaBufferDes(NULL, 0);
sl@0
  1154
	const TDisplayMode maskDisplayMode = aMaskBitmap->DisplayMode();
sl@0
  1155
sl@0
  1156
	// Mask inversion is not supported if the original source mask format is EGray256.
sl@0
  1157
	// Note that this is only used for pre-multiplied alpha targets.
sl@0
  1158
	TUint8 maskInverter = (aInvertMask && maskDisplayMode != EGray256) ? 0xFF : 0x00;
sl@0
  1159
sl@0
  1160
	if (aSourceBitmap != aMaskBitmap)
sl@0
  1161
		{
sl@0
  1162
		// Get buffer to be used to convert non-EGray256 masks to EGray256 when display mode is EColor16MAP
sl@0
  1163
		// or to tile the mask when the mask width is smaller than the source bitmap width.
sl@0
  1164
		if (maskDisplayMode != EGray256 && (dispMode == EColor16MAP || maskWidth < sourceBmpWidth))
sl@0
  1165
			{
sl@0
  1166
			alphaBuffer = CFbsBitmap::GetExtraBuffer(CFbsBitmap::ScanLineLength(maskWidth, EGray256));
sl@0
  1167
			if (!alphaBuffer)
sl@0
  1168
				{
sl@0
  1169
				return;  // Out of memory so do not draw anything 
sl@0
  1170
				}
sl@0
  1171
			alphaBufferDes.Set(alphaBuffer->Des());
sl@0
  1172
			}
sl@0
  1173
sl@0
  1174
		// Get buffer to be used for decompressing compressed masks when mask is EGray256
sl@0
  1175
		if (maskDisplayMode == EGray256 && aMaskBitmap->IsCompressed())
sl@0
  1176
			{
sl@0
  1177
			HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride());
sl@0
  1178
			if (!hBuf)
sl@0
  1179
				{
sl@0
  1180
				return;  // Out of memory so do not draw anything
sl@0
  1181
				}
sl@0
  1182
			lineScanPosMask.iScanLineBuffer = hBuf;
sl@0
  1183
			}
sl@0
  1184
		}
sl@0
  1185
	const TPoint KZeroPoint(0,0);
sl@0
  1186
sl@0
  1187
	while (yCoord.iY < clippedDestRect.iBr.iY)
sl@0
  1188
		{
sl@0
  1189
		// Draw only the source bitmap, if the source bitmap and the mask bitmap are same.
sl@0
  1190
		// else draw both the bitmaps
sl@0
  1191
		if (aSourceBitmap == aMaskBitmap)
sl@0
  1192
			{
sl@0
  1193
			aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
sl@0
  1194
								 clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
sl@0
  1195
								 srceWidth, KZeroPoint,dispMode,aSourceBase,lineScanPos);
sl@0
  1196
			if (yCoord.iY==clippedDestRect.iTl.iY)
sl@0
  1197
				aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
sl@0
  1198
			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
sl@0
  1199
			}
sl@0
  1200
		else if ((maskDisplayMode == EGray256) || (dispMode == EColor16MAP))
sl@0
  1201
			{
sl@0
  1202
			// Stretch the source bitmap and the mask bitmap for KScanLineLength as stretch length
sl@0
  1203
			// then do alpha blending for this length. If the length is more then KScanLineLength
sl@0
  1204
			// repeat it till you stretch complete destination length.
sl@0
  1205
			const TPoint startPt(bitmapXStart,yCoord.iX);
sl@0
  1206
			TInt clipWidthPart = clippedDestRect.Width();
sl@0
  1207
			TBool loopLast = ETrue;
sl@0
  1208
			if(clipWidthPart > KScanLineLength)
sl@0
  1209
				{
sl@0
  1210
				clipWidthPart = KScanLineLength;
sl@0
  1211
				loopLast = EFalse;
sl@0
  1212
				}
sl@0
  1213
			TInt clipIncStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX;
sl@0
  1214
			TInt startClip=clippedDestRect.iTl.iX;
sl@0
  1215
			TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
sl@0
  1216
			xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
sl@0
  1217
							TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
sl@0
  1218
			xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
sl@0
  1219
			TPoint srcPixel(bitmapXStart % maskWidth,yCoord.iX % maskHeight);
sl@0
  1220
			TInt spaceLeft = 0;
sl@0
  1221
			TRgb maskRgbValue;
sl@0
  1222
			TUint32* maskScanLinePtr32 = NULL;
sl@0
  1223
			TPoint currentYValue(0,srcPixel.iY);
sl@0
  1224
			aMaskBitmap->GetScanLinePtr(maskScanLinePtr32, currentYValue, maskWidth, aMaskBase, lineScanPosMask);
sl@0
  1225
			// To implement non EGray256 mask support with EColor16MAP display mode, we convert
sl@0
  1226
			// the mask to EGray256.
sl@0
  1227
			if (maskDisplayMode != EGray256) // Convert scan-line to EGray256 and set maskScanLinePtr32 to the conversion.
sl@0
  1228
				{
sl@0
  1229
				aMaskBitmap->GetScanLine(maskScanLinePtr32, alphaBufferDes, currentYValue, maskWidth, EFalse, TPoint(0, 0), EGray256);
sl@0
  1230
				maskScanLinePtr32 = (TUint32*)alphaBuffer->Ptr();
sl@0
  1231
				}
sl@0
  1232
			TUint8* maskScanLinePtr = reinterpret_cast<TUint8*>(maskScanLinePtr32);
sl@0
  1233
sl@0
  1234
			// Outer loop over all KScanLineLengths
sl@0
  1235
			FOREVER
sl@0
  1236
				{
sl@0
  1237
				aSourceBitmap->StretchScanLine(sourceDes,startPt,clipIncStrch,clipWidthPart,destWidth,
sl@0
  1238
								aSourceRect.iTl.iX,srceWidth, KZeroPoint ,EColor16MU,aSourceBase,lineScanPos);
sl@0
  1239
				// Inner loop to tile the mask if necessary
sl@0
  1240
				spaceLeft = clipWidthPart;
sl@0
  1241
				do	{
sl@0
  1242
					srcPixel.iX = sourceDestXCoords.iX % maskWidth;
sl@0
  1243
			
sl@0
  1244
					// Invert the mask using the inversion mask.
sl@0
  1245
					maskBuffer[(sourceDestXCoords.iY-clippedDestRect.iTl.iX)%KScanLineLength]=
sl@0
  1246
						maskInverter^maskScanLinePtr[srcPixel.iX];
sl@0
  1247
					xLine.NextStep(sourceDestXCoords);
sl@0
  1248
					} while (--spaceLeft>0);
sl@0
  1249
				
sl@0
  1250
				if (yCoord.iY == clippedDestRect.iTl.iY && startClip == clippedDestRect.iTl.iX)
sl@0
  1251
					{
sl@0
  1252
					aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL);
sl@0
  1253
					aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
sl@0
  1254
					}
sl@0
  1255
				drawDevice->WriteRgbAlphaLine(startClip,yCoord.iY,clipWidthPart,sourceBuffer,maskBuffer, GcDrawMode(iDrawMode));
sl@0
  1256
				if (loopLast)
sl@0
  1257
					{
sl@0
  1258
					break;
sl@0
  1259
					}
sl@0
  1260
				startClip+=KScanLineLength;
sl@0
  1261
				if (clippedDestRect.iBr.iX - startClip <= KScanLineLength)
sl@0
  1262
 					{
sl@0
  1263
					loopLast = ETrue;
sl@0
  1264
					clipWidthPart = clippedDestRect.iBr.iX - startClip;
sl@0
  1265
					}
sl@0
  1266
				clipIncStrch += KScanLineLength;
sl@0
  1267
				}
sl@0
  1268
			}
sl@0
  1269
		else
sl@0
  1270
			{
sl@0
  1271
			aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
sl@0
  1272
									 clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
sl@0
  1273
									 srceWidth, KZeroPoint ,dispMode,aSourceBase,lineScanPos2);
sl@0
  1274
			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
sl@0
  1275
sl@0
  1276
			TInt maskXStart = bitmapXStart % maskWidth;
sl@0
  1277
			if(maskWidth < sourceBmpWidth)
sl@0
  1278
				{
sl@0
  1279
				TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX);
sl@0
  1280
				xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX),
sl@0
  1281
								TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
sl@0
  1282
				xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY);
sl@0
  1283
				TPoint srcPixel(maskXStart,yCoord.iX % maskHeight);
sl@0
  1284
				TInt spaceLeft = clipWidth;
sl@0
  1285
				TPoint prevSourceDestXCoords(-1,-1);
sl@0
  1286
				TRgb maskRgbValue;
sl@0
  1287
				aMaskBitmap->GetScanLine(alphaBufferDes, TPoint(0,srcPixel.iY), maskWidth, EFalse, TPoint(0, 0), EGray256, aMaskBase, lineScanPosMask);
sl@0
  1288
sl@0
  1289
				// Loop to tile the mask
sl@0
  1290
				do	{
sl@0
  1291
					if (sourceDestXCoords.iY != prevSourceDestXCoords.iY)
sl@0
  1292
						{
sl@0
  1293
						if (sourceDestXCoords.iX != prevSourceDestXCoords.iX)
sl@0
  1294
							{
sl@0
  1295
							srcPixel.iX = sourceDestXCoords.iX % maskWidth;
sl@0
  1296
							if (srcPixel.iX < 0)
sl@0
  1297
								srcPixel.iX += maskWidth;
sl@0
  1298
							maskRgbValue = TRgb::Gray256((*alphaBuffer)[srcPixel.iX]);
sl@0
  1299
							}
sl@0
  1300
						drawDevice->WriteRgb(sourceDestXCoords.iY,yCoord.iY,maskRgbValue,drawMode);
sl@0
  1301
						spaceLeft--;
sl@0
  1302
						}
sl@0
  1303
					prevSourceDestXCoords = sourceDestXCoords;
sl@0
  1304
					xLine.SingleStep(sourceDestXCoords);
sl@0
  1305
					} while (spaceLeft > 0);
sl@0
  1306
				}
sl@0
  1307
			else
sl@0
  1308
				{
sl@0
  1309
				// No need to tile the mask
sl@0
  1310
				aMaskBitmap->StretchScanLine(scanLineDes,TPoint(maskXStart,yCoord.iX % maskHeight),
sl@0
  1311
										clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
sl@0
  1312
										srceWidth, KZeroPoint ,dispMode,aMaskBase,lineScanPosMask);
sl@0
  1313
				drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode);
sl@0
  1314
				// Redo stretching of the aSourceBitmap scanline
sl@0
  1315
				aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
sl@0
  1316
									 	clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX,
sl@0
  1317
									 	srceWidth, KZeroPoint ,dispMode,aSourceBase,lineScanPos2);
sl@0
  1318
				}
sl@0
  1319
sl@0
  1320
			if (yCoord.iY==clippedDestRect.iTl.iY)
sl@0
  1321
				{
sl@0
  1322
				aSourceBitmap->SetCompressionBookmark(lineScanPos2,aSourceBase,NULL);
sl@0
  1323
				aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL);
sl@0
  1324
				}
sl@0
  1325
sl@0
  1326
			drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,CGraphicsContext::EDrawModeXOR);
sl@0
  1327
			}
sl@0
  1328
		yLine.NextStep(yCoord);
sl@0
  1329
		}
sl@0
  1330
	}
sl@0
  1331
sl@0
  1332
TInt CSwDirectGdiEngine::FastBlendInterface(const CBitwiseBitmap* aSource, const CBitwiseBitmap* aMask, MFastBlend*& aFastBlend) const
sl@0
  1333
	{
sl@0
  1334
	#if defined(__ALLOW_FAST_BLEND_DISABLE__)
sl@0
  1335
	if (iFastBlendDisabled)
sl@0
  1336
		return(KErrNotSupported);
sl@0
  1337
	#endif
sl@0
  1338
	if ((aSource && aSource->IsCompressed()) || (aMask && aMask->IsCompressed()))
sl@0
  1339
		return(KErrNotSupported);
sl@0
  1340
	TAny* interface=NULL;
sl@0
  1341
	TInt ret= iDrawDevice->GetInterface(KFastBlendInterfaceID, interface);
sl@0
  1342
	aFastBlend=(MFastBlend*)interface;
sl@0
  1343
	return(ret);
sl@0
  1344
	}
sl@0
  1345
sl@0
  1346
/*
sl@0
  1347
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.
sl@0
  1348
sl@0
  1349
@see CBitwiseBitmap::GetScanLine()
sl@0
  1350
@see CBitwiseBitmap::GetVerticalScanLine()
sl@0
  1351
@see CBitwiseBitmap::StretchScanLine()
sl@0
  1352
@see CFbsDrawDevice::WriteLine()
sl@0
  1353
@internalComponent
sl@0
  1354
*/
sl@0
  1355
TDisplayMode CSwDirectGdiEngine::ScanLineBufferDisplayMode(CFbsDrawDevice* aDrawDevice)
sl@0
  1356
	{
sl@0
  1357
	return iDrawMode == DirectGdi::EDrawModeWriteAlpha ? aDrawDevice->DisplayMode() : aDrawDevice->ScanLineDisplayMode();
sl@0
  1358
	}