sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "swdirectgdiengine.h" sl@0: #include "swdirectgdidriverimpl.h" sl@0: #include "directgdiadapter.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::BitBlt() sl@0: @panic DGDIAdapter 7, aBitmap is invalid (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::BitBlt(const TPoint& aDestPos, sl@0: const CFbsBitmap& aBitmap, sl@0: const TRect& aSrceRect) sl@0: { sl@0: if (aBitmap.ExtendedBitmapType() != KNullUid) sl@0: { sl@0: iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps sl@0: return; sl@0: } sl@0: sl@0: TRect srceRect(aSrceRect); sl@0: const TPoint destPoint(aDestPos + iOrigin + srceRect.iTl - aSrceRect.iTl); sl@0: const TPoint offset(srceRect.iTl - destPoint); sl@0: sl@0: TRect targetRect(destPoint,srceRect.Size()); sl@0: aBitmap.BeginDataAccess(); sl@0: sl@0: CBitwiseBitmap* srce = static_cast(aBitmap).Address(); sl@0: GRAPHICS_ASSERT_DEBUG(srce,EDirectGdiPanicInvalidBitmap); sl@0: sl@0: const TInt limit = iDefaultRegionPtr->Count(); sl@0: sl@0: TBool opaqueSource = (!IsAlphaChannel(aBitmap.DisplayMode())) && (iDrawMode == DirectGdi::EDrawModePEN); sl@0: sl@0: TRect clipRect; sl@0: for (TInt count = 0; count < limit; count++) sl@0: { sl@0: clipRect = (*iDefaultRegionPtr)[count]; sl@0: if(!clipRect.Intersects(targetRect)) sl@0: { sl@0: continue; sl@0: } sl@0: sl@0: clipRect.Intersection(targetRect); sl@0: sl@0: TRect clippedSrceRect(clipRect); sl@0: clippedSrceRect.Move(offset); sl@0: sl@0: if (opaqueSource) sl@0: { sl@0: iDrawMode = DirectGdi::EDrawModeWriteAlpha; // write rather than blend. sl@0: } sl@0: sl@0: DoBitBlt(clipRect.iTl, srce, aBitmap.DataAddress(), aBitmap.DataStride(), clippedSrceRect); sl@0: sl@0: if (opaqueSource) sl@0: { sl@0: iDrawMode = DirectGdi::EDrawModePEN; // set it back to how it was. sl@0: } sl@0: sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: sl@0: aBitmap.EndDataAccess(ETrue); sl@0: } sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, TBool) sl@0: @panic DGDIAdapter 7, if either aMaskBitmap or aBitmap are invalid (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::BitBltMasked(const TPoint& aDestPos, sl@0: const CFbsBitmap& aBitmap, sl@0: const TRect& aSrcRect, sl@0: const CFbsBitmap& aMaskBitmap, sl@0: TBool aInvertMask) sl@0: { sl@0: if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid)) sl@0: { sl@0: iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps sl@0: return; sl@0: } sl@0: sl@0: TRect localSrcRect(aSrcRect); sl@0: const TPoint destPoint(aDestPos + iOrigin + localSrcRect.iTl - aSrcRect.iTl); sl@0: const TRect destRect(destPoint, localSrcRect.Size()); sl@0: const TPoint offset(localSrcRect.iTl - destPoint); sl@0: sl@0: TRect targetRect(destRect); sl@0: aBitmap.BeginDataAccess(); sl@0: aMaskBitmap.BeginDataAccess(); sl@0: sl@0: CBitwiseBitmap* srcebmp = static_cast(aBitmap).Address(); sl@0: CBitwiseBitmap* maskbmp = static_cast(aMaskBitmap).Address(); sl@0: sl@0: GRAPHICS_ASSERT_DEBUG(srcebmp,EDirectGdiPanicInvalidBitmap); sl@0: GRAPHICS_ASSERT_DEBUG(maskbmp,EDirectGdiPanicInvalidBitmap); sl@0: sl@0: const TDisplayMode maskMode = maskbmp->DisplayMode(); sl@0: const TInt limit = iDefaultRegionPtr->Count(); sl@0: TBool opaqueSource = (!IsAlphaChannel(aBitmap.DisplayMode())) && (iDrawMode == DirectGdi::EDrawModePEN); sl@0: TRect clipRect; sl@0: for (TInt count = 0; count < limit; count++) sl@0: { sl@0: clipRect = (*iDefaultRegionPtr)[count]; sl@0: if (!clipRect.Intersects(targetRect)) sl@0: { sl@0: continue; sl@0: } sl@0: sl@0: clipRect.Intersection(targetRect); sl@0: TRect clippedSrceRect(clipRect); sl@0: clippedSrceRect.Move(offset); sl@0: sl@0: if (opaqueSource) sl@0: { sl@0: iDrawMode = DirectGdi::EDrawModeWriteAlpha; // ie write rather than blend sl@0: } sl@0: sl@0: DoBitBltMasked(clipRect.iTl, srcebmp, aBitmap.DataAddress(), clippedSrceRect, maskbmp, sl@0: aMaskBitmap.DataAddress(), aInvertMask); sl@0: sl@0: if (opaqueSource) sl@0: { sl@0: iDrawMode = DirectGdi::EDrawModePEN; // set to default sl@0: } sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: sl@0: aBitmap.EndDataAccess(ETrue); sl@0: aMaskBitmap.EndDataAccess(ETrue); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::BitBltMasked(const TPoint&, const CFbsBitmap&, const TRect&, const CFbsBitmap&, const TPoint&) sl@0: @panic DGDIAdapter 7, if either aBitmap or aMaskBitmap are invalid. sl@0: @panic DGDIAdapter 1022, if the top-left corner of aSrcRect is out of bounds (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::BitBltMasked(const TPoint& aDestPt, sl@0: const CFbsBitmap& aBitmap, const TRect& aSrcRect, sl@0: const CFbsBitmap& aMaskBitmap, const TPoint& aAlphaPt) sl@0: { sl@0: if ((aBitmap.ExtendedBitmapType() != KNullUid) || (aMaskBitmap.ExtendedBitmapType() != KNullUid)) sl@0: { sl@0: iDriver->SetError(KErrNotSupported); // Not supported for extended bitmaps sl@0: return; sl@0: } sl@0: sl@0: TRect srcRect(aSrcRect); sl@0: //Calculate the destination rect sl@0: TPoint destPt(aDestPt + iOrigin); sl@0: TRect destRect(destPt, srcRect.Size()); sl@0: TPoint offset(srcRect.iTl - destPt); sl@0: TRect targetRect(destRect); sl@0: sl@0: aBitmap.BeginDataAccess(); sl@0: aMaskBitmap.BeginDataAccess(); sl@0: CBitwiseBitmap* srcBmp = static_cast(aBitmap).Address(); sl@0: CBitwiseBitmap* alphaBmp = static_cast(aMaskBitmap).Address(); sl@0: GRAPHICS_ASSERT_DEBUG(srcBmp, EDirectGdiPanicInvalidBitmap); sl@0: GRAPHICS_ASSERT_DEBUG(alphaBmp, EDirectGdiPanicInvalidBitmap); sl@0: TUint32* srcDataAddr = aBitmap.DataAddress(); sl@0: TUint32* alphaDataAddr = aMaskBitmap.DataAddress(); sl@0: sl@0: //For each region - find the clipping rect and draw sl@0: TInt limit = iDefaultRegionPtr->Count (); sl@0: TRect clipRect; sl@0: for (TInt count=0; count= 0, EDirectGdiPanicNegativeShift); sl@0: GRAPHICS_ASSERT_DEBUG(shift.iY >= 0, EDirectGdiPanicNegativeShift); sl@0: DoBitBltAlpha (clipRect.iTl, srcBmp, srcDataAddr, clippedSrcRect, sl@0: alphaBmp, alphaDataAddr, aAlphaPt + shift, EFalse); sl@0: iDrawDevice->UpdateRegion (clipRect); sl@0: } sl@0: sl@0: aBitmap.EndDataAccess(ETrue); sl@0: aMaskBitmap.EndDataAccess(ETrue); sl@0: return; sl@0: } sl@0: sl@0: /** sl@0: Calculates the position into the scanline for the given x coordinate. sl@0: sl@0: @param aX The given x-coordinate. sl@0: @param aDisplayMode The applied display mode. sl@0: @return The memory offset, or 0 if the mode is not supported. sl@0: @panic DGDIAdapter 1009, if aDisplayMode is not supported (debug only). sl@0: */ sl@0: TUint CSwDirectGdiEngine::MemoryOffsetForPixelPitch(TUint aX, TDisplayMode aDisplayMode) const sl@0: { sl@0: switch (aDisplayMode) sl@0: { sl@0: case EColor16MU: sl@0: case EColor16MAP: sl@0: return aX << 2; sl@0: case EColor64K: sl@0: return aX << 1; sl@0: default: sl@0: GRAPHICS_PANIC_DEBUG(EDirectGdiPanicInvalidDisplayMode); sl@0: } sl@0: return 0; sl@0: } sl@0: sl@0: TUint32* CSwDirectGdiEngine::GetScanLineOffsetPtr(CBitwiseBitmap* aSrce, TUint32*& aSlptr, sl@0: TInt aLength, TPoint aPixel, TUint32* aBase, sl@0: TLineScanningPosition& aLineScanningPosition, TUint aXOffset) sl@0: { sl@0: aSrce->GetScanLinePtr(aSlptr, aLength, aPixel, aBase, aLineScanningPosition); sl@0: return (TUint32*)((TUint8*)aSlptr + aXOffset); sl@0: } sl@0: sl@0: /** sl@0: Performs the actual bitblt to the device. sl@0: This function may also be called by DrawBitmap(), and DrawRect() when using a patterned brush, sl@0: so any changes to this function may impact on them also. sl@0: sl@0: @pre aSrce A bitmap with non-zero dimensions. aSrceRect has been clipped against the target. sl@0: sl@0: @param aDest The target position on the device which will contain the top left sl@0: corner of the source bitmap. sl@0: @param aSrce The bitmap object that contains the pixels to draw. sl@0: @param aBase The address of the bitmap pixels. sl@0: @param aStride The length in bytes between scanlines in memory. sl@0: @param aSrceRect The area of the bitmap to draw from. sl@0: @panic DGDIAdapter 1013, if aDest is fully outside of the bounds of the target, or aSrceRect.iTl is not sl@0: within the drawing area (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::DoBitBlt(const TPoint& aDest, sl@0: CBitwiseBitmap* aSrce, sl@0: TUint32* aBase, sl@0: TInt aStride, sl@0: const TRect& aSrceRect) sl@0: { sl@0: // Does multiple bitmap widths for painting rects only sl@0: const TInt width = aSrceRect.Width (); sl@0: sl@0: #ifdef _DEBUG sl@0: TRect deviceDestRect; sl@0: iDrawDevice->GetDrawRect(deviceDestRect); sl@0: GRAPHICS_ASSERT_DEBUG(aDest.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aDest.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG((aDest.iX + aSrceRect.Width()) <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG((aDest.iY + aSrceRect.Height()) <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aDest.iX >= 0 && aDest.iY >= 0, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aSrceRect.iTl.iX >= 0 && aSrceRect.iTl.iY >= 0, EDirectGdiPanicOutOfBounds); sl@0: #endif sl@0: sl@0: TSize srcSize = aSrce->SizeInPixels (); sl@0: sl@0: const TPoint KZeroPoint(0,0); sl@0: TAny* interface = NULL; sl@0: if (iDrawMode == DirectGdi::EDrawModeWriteAlpha && sl@0: aSrceRect.iBr.iX <= srcSize.iWidth && sl@0: aSrceRect.iBr.iY <= srcSize.iHeight && sl@0: !aSrce->IsCompressed() && sl@0: aSrce->DisplayMode() == iDrawDevice->DisplayMode() && sl@0: iDrawDevice->GetInterface(KFastBlit2InterfaceID, interface) == KErrNone) sl@0: { sl@0: // Conditions in CFbsBitGc allow for optimised blitting. sl@0: // The draw device supports the optimised blitting function. sl@0: // Operation may fail regardless due to unacceptable conditions in the draw device. sl@0: MFastBlit2* fastBlit = reinterpret_cast(interface); sl@0: if (fastBlit && (fastBlit->WriteBitmapBlock(aDest, aBase, aStride, srcSize, aSrceRect) == KErrNone)) sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: MFastBlend* fastBlend=NULL; sl@0: if (FastBlendInterface(aSrce,NULL,fastBlend)==KErrNone) sl@0: { sl@0: if (fastBlend->FastBlendBitmap(aDest, aBase, aStride, srcSize, aSrceRect, aSrce->DisplayMode(), GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)== KErrNone) sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: const TInt scanLineBytes = iDrawDevice->ScanLineBytes(); sl@0: TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer(); sl@0: TPtr8 scanLineDes((TUint8*)scanLineBuffer, scanLineBytes, scanLineBytes); sl@0: sl@0: const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice); sl@0: sl@0: const TBool useScanLinePtr = (dispMode == aSrce->DisplayMode()) && sl@0: (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode) >= 8); sl@0: sl@0: TUint32* slptr = NULL; sl@0: TUint offset = 0; sl@0: TUint32* lastScanLine = NULL; sl@0: if (useScanLinePtr) sl@0: { sl@0: lastScanLine = aSrce->ScanLineAddress(aBase, aSrceRect.iBr.iY-1); sl@0: } sl@0: sl@0: TInt srceWidth = srcSize.iWidth; sl@0: TInt partlinestart = aSrceRect.iTl.iX % srceWidth; sl@0: sl@0: if (partlinestart < 0) sl@0: { sl@0: partlinestart += srceWidth; sl@0: } sl@0: sl@0: const TInt partlinelength = Min(srceWidth - partlinestart, width); sl@0: TInt destX = aDest.iX; sl@0: const TInt destXlimit = destX+width; sl@0: const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode); sl@0: sl@0: // first part line sl@0: if (partlinestart > 0 && partlinelength > 0) sl@0: { sl@0: TPoint srcecoord1(partlinestart, aSrceRect.iTl.iY); sl@0: TInt desty = aDest.iY; sl@0: sl@0: TLineScanningPosition lineScanPos(aBase); sl@0: sl@0: if (useScanLinePtr) sl@0: { sl@0: offset = MemoryOffsetForPixelPitch(partlinestart, dispMode); sl@0: if (aSrce->IsCompressed ()) sl@0: { sl@0: sl@0: while (srcecoord1.iY < aSrceRect.iBr.iY) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr, sl@0: partlinelength, srcecoord1, aBase, lineScanPos, offset); sl@0: if (srcecoord1.iY == aSrceRect.iTl.iY) sl@0: { sl@0: aSrce->SetCompressionBookmark(lineScanPos, aBase, NULL); sl@0: } sl@0: iDrawDevice->WriteLine(aDest.iX, desty, partlinelength, sl@0: scanLineBuffer, drawMode); sl@0: srcecoord1.iY++; sl@0: desty++; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: while (srcecoord1.iY < aSrceRect.iBr.iY) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr, sl@0: partlinelength, srcecoord1, aBase, lineScanPos, sl@0: offset); sl@0: do sl@0: { sl@0: iDrawDevice->WriteLine (aDest.iX, desty, sl@0: partlinelength, scanLineBuffer, drawMode); sl@0: scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride); sl@0: srcecoord1.iY++; sl@0: desty++; sl@0: } sl@0: while ((srcecoord1.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine)) ; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for ( ; srcecoord1.iY < aSrceRect.iBr.iY; srcecoord1.iY++, desty++) sl@0: { sl@0: aSrce->GetScanLine (scanLineDes, srcecoord1, partlinelength, sl@0: EFalse, KZeroPoint, dispMode, aBase, lineScanPos); sl@0: if ( srcecoord1.iY==aSrceRect.iTl.iY) sl@0: { sl@0: aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL); sl@0: } sl@0: iDrawDevice->WriteLine (aDest.iX, desty, partlinelength, sl@0: scanLineBuffer, drawMode); sl@0: } sl@0: } sl@0: sl@0: destX += partlinelength; sl@0: } sl@0: sl@0: // multiple complete lines - columns sl@0: TInt numcolumns = (destXlimit - destX) / srceWidth; sl@0: sl@0: if (numcolumns > 0) sl@0: { sl@0: TPoint srcecoord2(0, aSrceRect.iTl.iY); sl@0: TInt desty = aDest.iY; sl@0: sl@0: TLineScanningPosition lineScanPos(aBase); sl@0: sl@0: if (useScanLinePtr) sl@0: { sl@0: if (aSrce->IsCompressed()) sl@0: { sl@0: while (srcecoord2.iY < aSrceRect.iBr.iY) sl@0: { sl@0: TPoint coord(srcecoord2); sl@0: aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos); sl@0: if (srcecoord2.iY == aSrceRect.iTl.iY) sl@0: { sl@0: aSrce->SetCompressionBookmark(lineScanPos, aBase, NULL); sl@0: } sl@0: TInt tempdestX = destX; sl@0: for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth) sl@0: { sl@0: iDrawDevice->WriteLine(tempdestX, desty, srceWidth, slptr, drawMode); sl@0: } sl@0: srcecoord2.iY++; sl@0: desty++; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: while (srcecoord2.iY < aSrceRect.iBr.iY) sl@0: { sl@0: TPoint coord(srcecoord2); sl@0: aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos); sl@0: do sl@0: { sl@0: TInt tempdestX = destX; sl@0: for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth) sl@0: { sl@0: iDrawDevice->WriteLine (tempdestX, desty, srceWidth, slptr, drawMode); sl@0: } sl@0: slptr = (TUint32*)((TUint8*)slptr + aStride); sl@0: srcecoord2.iY++; sl@0: desty++; sl@0: } sl@0: while ((srcecoord2.iY < aSrceRect.iBr.iY) && (slptr < lastScanLine)); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (; srcecoord2.iY < aSrceRect.iBr.iY; srcecoord2.iY++, desty++) sl@0: { sl@0: TInt tempdestX = destX; sl@0: TPoint coord(srcecoord2); sl@0: aSrce->GetScanLinePtr (slptr, srceWidth, coord, aBase, lineScanPos); sl@0: if (srcecoord2.iY == aSrceRect.iTl.iY) sl@0: { sl@0: aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL); sl@0: } sl@0: for (TInt count = 0; count < numcolumns; count++, tempdestX += srceWidth) sl@0: { sl@0: aSrce->GetScanLine(slptr, scanLineDes, coord, srceWidth, sl@0: EFalse, KZeroPoint, dispMode); sl@0: iDrawDevice->WriteLine(tempdestX, desty, srceWidth, scanLineBuffer, drawMode); sl@0: } sl@0: } sl@0: } sl@0: sl@0: destX += numcolumns * srceWidth; sl@0: } sl@0: sl@0: // final part line sl@0: if (destX < destXlimit) sl@0: { sl@0: const TInt restofline = destXlimit - destX; sl@0: TPoint srcecoord3(0, aSrceRect.iTl.iY); sl@0: TInt desty = aDest.iY; sl@0: sl@0: TLineScanningPosition lineScanPos(aBase); sl@0: sl@0: if (useScanLinePtr) sl@0: { sl@0: offset = 0; sl@0: if (aSrce->IsCompressed()) sl@0: { sl@0: while (srcecoord3.iY < aSrceRect.iBr.iY) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr, sl@0: srceWidth, srcecoord3, aBase, lineScanPos, offset); sl@0: if (srcecoord3.iY == aSrceRect.iTl.iY) sl@0: { sl@0: aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL); sl@0: } sl@0: iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode); sl@0: srcecoord3.iY++; sl@0: desty++; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: while (srcecoord3.iY < aSrceRect.iBr.iY) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr (aSrce, slptr, sl@0: srceWidth, srcecoord3, aBase, lineScanPos, offset); sl@0: do sl@0: { sl@0: iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode); sl@0: scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + aStride); sl@0: srcecoord3.iY++; sl@0: desty++; sl@0: } sl@0: while ((srcecoord3.iY < aSrceRect.iBr.iY) && (scanLineBuffer < lastScanLine)); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (; srcecoord3.iY < aSrceRect.iBr.iY; srcecoord3.iY++, desty++) sl@0: { sl@0: aSrce->GetScanLine (scanLineDes, srcecoord3, srceWidth, EFalse, sl@0: KZeroPoint, dispMode, aBase, lineScanPos); sl@0: if (srcecoord3.iY == aSrceRect.iTl.iY) sl@0: { sl@0: aSrce->SetCompressionBookmark (lineScanPos, aBase, NULL); sl@0: } sl@0: iDrawDevice->WriteLine(destX, desty, restofline, scanLineBuffer, drawMode); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: /** sl@0: Performs the masked bitblt to the device. sl@0: sl@0: @param aDest The target position on the device which will contain the top left sl@0: corner of the source bitmap. sl@0: @param aSourceBitmap The bitmap object that contains the pixels to draw. sl@0: @param aSourceBase The address of the source bitmap pixels. sl@0: @param aSourceRect The area of the bitmap to draw from. sl@0: @param aMaskBitmap The bitmap object that contains the mask. sl@0: @param aMaskBase The address of the mask pixels. sl@0: @param aInvertMask Inverts the mask if ETrue. sl@0: @panic DGDIAdapter 1013, if aDest is outside of the device bounds (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::DoBitBltMasked(const TPoint& aDest, sl@0: CBitwiseBitmap* aSourceBitmap, sl@0: TUint32* aSourceBase, sl@0: const TRect& aSourceRect, sl@0: CBitwiseBitmap* aMaskBitmap, sl@0: TUint32* aMaskBase, sl@0: TBool aInvertMask) sl@0: { sl@0: #ifdef _DEBUG sl@0: TRect deviceDestRect; sl@0: iDrawDevice->GetDrawRect (deviceDestRect); sl@0: #endif sl@0: sl@0: GRAPHICS_ASSERT_DEBUG (aDest.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG (aDest.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG ((aDest.iX + aSourceRect.Width()) <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG ((aDest.iY + aSourceRect.Height()) <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: const TPoint KZeroPoint(0,0); sl@0: sl@0: MFastBlend* fastBlend=NULL; sl@0: if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone) sl@0: { sl@0: if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(), sl@0: aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aSourceRect.iTl, aInvertMask, sl@0: GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone) sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: if (aMaskBitmap->DisplayMode() == EGray256) sl@0: { sl@0: DoBitBltAlpha (aDest, aSourceBitmap, aSourceBase, aSourceRect, sl@0: aMaskBitmap, aMaskBase, aSourceRect.iTl, EFalse); sl@0: } sl@0: // if screen driver is 16MAP we avoid logical operator pen modes by using DoBitBltAlpha() for blitting sl@0: else if(iDrawDevice->ScanLineDisplayMode() == EColor16MAP) sl@0: { sl@0: DoBitBltAlpha (aDest, aSourceBitmap, aSourceBase, aSourceRect, sl@0: aMaskBitmap, aMaskBase, aSourceRect.iTl, aInvertMask); sl@0: } sl@0: else if (aSourceBitmap == aMaskBitmap) sl@0: { sl@0: const TInt width = aSourceRect.Width(); sl@0: const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice); sl@0: const CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeOR; sl@0: TPoint srcePoint(aSourceRect.iTl); sl@0: TInt destY = aDest.iY; sl@0: sl@0: TLineScanningPosition lineScanPos(aSourceBase); sl@0: sl@0: const TBool useScanLinePtr = (dispMode == aSourceBitmap->DisplayMode() && sl@0: (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8)); sl@0: sl@0: if (useScanLinePtr) sl@0: { sl@0: TUint32* scanLineBuffer = NULL; sl@0: TUint32* slptr = NULL; sl@0: TUint offset = MemoryOffsetForPixelPitch (srcePoint.iX, dispMode); sl@0: sl@0: if (aSourceBitmap->IsCompressed()) sl@0: { sl@0: for ( ; srcePoint.iY < aSourceRect.iBr.iY; destY++, sl@0: srcePoint.iY++) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr ( sl@0: aSourceBitmap, slptr, width, srcePoint, sl@0: aSourceBase, lineScanPos, offset); sl@0: sl@0: iDrawDevice->WriteLine (aDest.iX, destY, width, sl@0: scanLineBuffer, drawMode); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TUint stride = aSourceBitmap->DataStride (); sl@0: TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase, aSourceRect.iBr.iY-1); sl@0: sl@0: while (srcePoint.iY < aSourceRect.iBr.iY) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, sl@0: aSourceBase, lineScanPos, offset); sl@0: do sl@0: { sl@0: iDrawDevice->WriteLine (aDest.iX, destY, width, scanLineBuffer, drawMode); sl@0: scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + stride); sl@0: destY++; sl@0: srcePoint.iY++; sl@0: } sl@0: while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBuffer < lastScanLine)); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: const TInt scanLineBytes = iDrawDevice->ScanLineBytes(); sl@0: TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer(); sl@0: TPtr8 scanLineDes((TUint8*)scanLineBuffer, scanLineBytes, sl@0: scanLineBytes); sl@0: for (; srcePoint.iY < aSourceRect.iBr.iY; destY++, sl@0: srcePoint.iY++) sl@0: { sl@0: aSourceBitmap->GetScanLine (scanLineDes, srcePoint, sl@0: width, EFalse, KZeroPoint, dispMode, sl@0: aSourceBase, lineScanPos); sl@0: sl@0: iDrawDevice->WriteLine (aDest.iX, destY, width, sl@0: scanLineBuffer, drawMode); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: DoBitBltMaskedFlicker(aDest, aSourceBitmap, aSourceBase, sl@0: aSourceRect, aMaskBitmap, aMaskBase, aInvertMask); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: @see DoBitBltMasked() sl@0: */ sl@0: void CSwDirectGdiEngine::DoBitBltMaskedFlicker(const TPoint& aDest, sl@0: CBitwiseBitmap* aSourceBitmap, sl@0: TUint32* aSourceBase, sl@0: const TRect& aSourceRect, sl@0: CBitwiseBitmap* aMaskBitmap, sl@0: TUint32* aMaskBase, sl@0: TBool aInvertMask) sl@0: { sl@0: const TInt width = aSourceRect.Width(); sl@0: TInt destY = aDest.iY; sl@0: TPoint srcePoint(aSourceRect.iTl); sl@0: sl@0: TLineScanningPosition lineScanPos(aSourceBase); sl@0: TLineScanningPosition lineScanPosMask(aMaskBase); sl@0: sl@0: const TDisplayMode srcFormat = aSourceBitmap->DisplayMode(); sl@0: const TDisplayMode maskFormat = aMaskBitmap->DisplayMode(); sl@0: sl@0: if (aMaskBitmap->IsCompressed()) sl@0: { sl@0: HBufC8* hBuf = CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride() + 4); sl@0: if (!hBuf) sl@0: { sl@0: iDriver->SetError(KErrNoMemory); sl@0: return; // Out of memory so do not draw anything sl@0: } sl@0: lineScanPosMask.iScanLineBuffer = hBuf; sl@0: } sl@0: sl@0: TAny* interface = NULL; sl@0: if ( (srcFormat == EColor16MU || srcFormat == EColor64K ) && sl@0: maskFormat == EGray2 && sl@0: aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth && sl@0: aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight && sl@0: iDrawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone ) sl@0: { sl@0: // Parameters allow optimised code path sl@0: TInt length = width; sl@0: TUint32* srcPtr=NULL; sl@0: TUint32* maskPtr=NULL; sl@0: MFastBlit* fastBlit = reinterpret_cast(interface); sl@0: while (srcePoint.iY < aSourceRect.iBr.iY) sl@0: { sl@0: aSourceBitmap->GetScanLinePtr(srcPtr, length, srcePoint, aSourceBase, lineScanPos); sl@0: aMaskBitmap->GetScanLinePtr(maskPtr, length, srcePoint, aMaskBase, lineScanPosMask); sl@0: sl@0: fastBlit->WriteMaskLineEx(aDest.iX,destY,length,srcePoint.iX,srcPtr,srcFormat,srcePoint.iX,maskPtr,aInvertMask); sl@0: sl@0: destY++; sl@0: ++srcePoint.iY; sl@0: } sl@0: return; sl@0: } sl@0: sl@0: const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice); sl@0: const CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeANDNOT; sl@0: sl@0: TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer(); sl@0: const TInt scanLineBytes = iDrawDevice->ScanLineBytes(); sl@0: TPtr8 scanLineDes((TUint8*)scanLineBuffer,scanLineBytes,scanLineBytes); sl@0: TLineScanningPosition lineScanPos2(aSourceBase); sl@0: const TPoint KZeroPoint(0,0); sl@0: sl@0: //scanline modifications required if using different modes, bits per pixel less than 8 sl@0: if ( (dispMode == aSourceBitmap->DisplayMode()) && sl@0: (TDisplayModeUtils::NumDisplayModeBitsPerPixel(dispMode)>=8)) sl@0: { sl@0: TUint offset = MemoryOffsetForPixelPitch(srcePoint.iX, dispMode); sl@0: TUint32* slptr=NULL; sl@0: //mask scanline modifications required for EInvertPen, different screen modes sl@0: if ((drawMode != CGraphicsContext::EDrawModeANDNOT) && (dispMode == aMaskBitmap->DisplayMode())) sl@0: { sl@0: TUint32* scanLineBufferMask = NULL; sl@0: //stride jumping not possible with compressed bitmaps sl@0: if (aSourceBitmap->IsCompressed() || aMaskBitmap->IsCompressed()) sl@0: { sl@0: for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer, CGraphicsContext::EDrawModeXOR); sl@0: scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer, CGraphicsContext::EDrawModeXOR); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TUint strideSrc = aSourceBitmap->DataStride(); sl@0: TUint strideMask = aMaskBitmap->DataStride(); sl@0: TUint32* lastScanLineSrc = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1); sl@0: TUint32* lastScanLineMask = aMaskBitmap->ScanLineAddress(aMaskBase,aSourceRect.iBr.iY-1); sl@0: sl@0: while (srcePoint.iY < aSourceRect.iBr.iY) sl@0: { sl@0: scanLineBuffer = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset); sl@0: scanLineBufferMask = GetScanLineOffsetPtr(aMaskBitmap, slptr, width, srcePoint, aMaskBase, lineScanPosMask, offset); sl@0: do sl@0: { sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferMask,drawMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR); sl@0: destY++; sl@0: srcePoint.iY++; sl@0: } sl@0: while ((srcePoint.iY < aSourceRect.iBr.iY) && sl@0: (scanLineBuffer < lastScanLineSrc) && sl@0: (scanLineBufferMask < lastScanLineMask) && sl@0: ((scanLineBuffer = (TUint32*)((TUint8*)scanLineBuffer + strideSrc))>(TUint32*)0) && sl@0: ((scanLineBufferMask = (TUint32*)((TUint8*)scanLineBufferMask + strideMask))>(TUint32*)0) ); sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TUint32* scanLineBufferPtr = NULL; sl@0: //stride jumping not possible with compressed bitmaps sl@0: if (aSourceBitmap->IsCompressed()) sl@0: { sl@0: for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++) sl@0: { sl@0: scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR); sl@0: aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint, dispMode, aMaskBase, lineScanPosMask); sl@0: TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TUint stride = aSourceBitmap->DataStride(); sl@0: TUint32* lastScanLine = aSourceBitmap->ScanLineAddress(aSourceBase,aSourceRect.iBr.iY-1); sl@0: while (srcePoint.iY < aSourceRect.iBr.iY) sl@0: { sl@0: scanLineBufferPtr = GetScanLineOffsetPtr(aSourceBitmap, slptr, width, srcePoint, aSourceBase, lineScanPos, offset); sl@0: do sl@0: { sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR); sl@0: aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse, KZeroPoint, dispMode,aMaskBase, lineScanPosMask); sl@0: TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBufferPtr,CGraphicsContext::EDrawModeXOR); sl@0: destY++; sl@0: srcePoint.iY++; sl@0: } sl@0: while ((srcePoint.iY < aSourceRect.iBr.iY) && (scanLineBufferPtr < lastScanLine) && sl@0: ((scanLineBufferPtr = (TUint32*)((TUint8*)scanLineBufferPtr + stride))>(TUint32*)0)); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (; srcePoint.iY < aSourceRect.iBr.iY; destY++,srcePoint.iY++) sl@0: { sl@0: aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse, KZeroPoint, sl@0: dispMode,aSourceBase,lineScanPos); sl@0: sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR); sl@0: aMaskBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint, dispMode, sl@0: aMaskBase, lineScanPosMask); sl@0: TileScanLine(scanLineDes, width, srcePoint, aMaskBitmap, lineScanPosMask, aMaskBase, dispMode); sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,drawMode); sl@0: aSourceBitmap->GetScanLine(scanLineDes,srcePoint,width,EFalse , KZeroPoint ,dispMode, sl@0: aSourceBase,lineScanPos2); sl@0: sl@0: iDrawDevice->WriteLine(aDest.iX,destY,width,scanLineBuffer,CGraphicsContext::EDrawModeXOR); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: @see DoBitBltMasked() sl@0: */ sl@0: void CSwDirectGdiEngine::DoBitBltAlpha(const TPoint& aDest ,CBitwiseBitmap* aSourceBitmap, sl@0: TUint32* aSourceBase, const TRect& aSourceRect, sl@0: CBitwiseBitmap* aMaskBitmap, TUint32* aMaskBase, sl@0: const TPoint& aAlphaPoint, TBool aInvertMask) sl@0: { sl@0: MFastBlend* fastBlend=NULL; sl@0: if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone) sl@0: { sl@0: if (fastBlend->FastBlendBitmapMasked(aDest, aSourceBase, aSourceBitmap->DataStride(), aSourceBitmap->SizeInPixels(), aSourceRect, aSourceBitmap->DisplayMode(), sl@0: aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aAlphaPoint, aInvertMask, sl@0: GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone) sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: const TPoint KZeroPoint(0,0); sl@0: const TInt KScanLineLength = 256; sl@0: const TInt KRgbSize = 4; sl@0: sl@0: TUint8 srceRgbBuffer[KScanLineLength * KRgbSize]; sl@0: TUint8 maskBuffer[KScanLineLength]; sl@0: TUint8* srceRgbBufferPtr(srceRgbBuffer); sl@0: sl@0: TPtr8 srceRgbDes(srceRgbBuffer, KScanLineLength * KRgbSize, KScanLineLength * KRgbSize); sl@0: TPtr8 maskDes(maskBuffer, KScanLineLength, KScanLineLength); sl@0: sl@0: TInt srceY = aSourceRect.iTl.iY; sl@0: TInt destY = aDest.iY; sl@0: TInt alphaY = aAlphaPoint.iY; sl@0: sl@0: TLineScanningPosition lineScanPosSrc(aSourceBase); sl@0: TLineScanningPosition lineScanPosMask(aMaskBase); sl@0: TDisplayMode sourceMode = aSourceBitmap->DisplayMode(); sl@0: sl@0: if (aMaskBitmap->IsCompressed()) sl@0: { sl@0: HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride()); sl@0: if (hBuf == NULL) sl@0: { sl@0: iDriver->SetError(KErrNoMemory); // Out of memory so do not draw anything sl@0: return; sl@0: } sl@0: lineScanPosMask.iScanLineBuffer = hBuf; sl@0: } sl@0: sl@0: TAny* interface = NULL; sl@0: if ( (sourceMode == EColor16MU || sourceMode == EColor64K) && sl@0: aMaskBitmap->DisplayMode() == EGray256 && // ensure a monochrome mask isn't passed in as an alpha channel sl@0: aSourceBitmap->SizeInPixels().iWidth <= aMaskBitmap->SizeInPixels().iWidth && sl@0: aSourceBitmap->SizeInPixels().iHeight <= aMaskBitmap->SizeInPixels().iHeight && sl@0: iDrawDevice->GetInterface(KFastBlitInterfaceID, interface) == KErrNone ) sl@0: { sl@0: TInt length = aSourceRect.Width(); sl@0: const TInt srceX = aSourceRect.iTl.iX; sl@0: const TInt alphaX = aAlphaPoint.iX; sl@0: const TInt destX = aDest.iX; sl@0: MFastBlit* fastBlit = reinterpret_cast(interface); sl@0: sl@0: while (srceY < aSourceRect.iBr.iY) sl@0: { sl@0: TUint32* srcPtr; sl@0: TUint32* maskPtr; sl@0: TPoint srcPoint(srceX, srceY); sl@0: TPoint maskPoint(alphaX, alphaY); sl@0: sl@0: aSourceBitmap->GetScanLinePtr(srcPtr, length, srcPoint, aSourceBase, lineScanPosSrc); sl@0: aMaskBitmap->GetScanLinePtr(maskPtr, length, maskPoint, aMaskBase, lineScanPosMask); sl@0: sl@0: fastBlit->WriteAlphaLineEx(destX, destY, length, srceX, srcPtr, sl@0: sourceMode, alphaX, maskPtr, MAlphaBlend::EShdwBefore); sl@0: srceY++; sl@0: destY++; sl@0: alphaY++; sl@0: } sl@0: sl@0: return; sl@0: } sl@0: sl@0: const TBool useScanLinePtr = ( (EColor16MA == aSourceBitmap->DisplayMode())); sl@0: TUint32* slptr = NULL; sl@0: TUint offset = 0; sl@0: sl@0: while (srceY < aSourceRect.iBr.iY) sl@0: { sl@0: TInt srceX = aSourceRect.iTl.iX; sl@0: TInt destX = aDest.iX; sl@0: TInt alphaX = aAlphaPoint.iX; sl@0: sl@0: while (srceX < aSourceRect.iBr.iX) sl@0: { sl@0: TPoint srcePoint(srceX,srceY); sl@0: TPoint alphaPoint(alphaX,alphaY); sl@0: const TInt width = Min(KScanLineLength, aSourceRect.iBr.iX - srceX); sl@0: sl@0: if (useScanLinePtr) sl@0: { sl@0: offset = MemoryOffsetForPixelPitch(srceX, EColor16MU); sl@0: srceRgbBufferPtr = (TUint8*)GetScanLineOffsetPtr(aSourceBitmap, slptr, width, sl@0: srcePoint, aSourceBase, lineScanPosSrc, offset); sl@0: } sl@0: else sl@0: { sl@0: aSourceBitmap->GetScanLine(srceRgbDes,srcePoint,width,EFalse,KZeroPoint, sl@0: ERgb,aSourceBase,lineScanPosSrc); sl@0: } sl@0: sl@0: aMaskBitmap->GetScanLine(maskDes, alphaPoint, width, EFalse, KZeroPoint, sl@0: EGray256, aMaskBase, lineScanPosMask); sl@0: TileScanLine(maskDes, width, alphaPoint, aMaskBitmap, lineScanPosMask, aMaskBase, EGray256); sl@0: sl@0: // aInvertMask is not used for alpha channels (EGray256 mask) sl@0: if (aInvertMask && aMaskBitmap->DisplayMode() != EGray256) sl@0: { sl@0: for (TInt i = 0; i < width; ++i) sl@0: { sl@0: maskBuffer[i] = ~maskBuffer[i]; sl@0: } sl@0: } sl@0: sl@0: iDrawDevice->WriteRgbAlphaLine(destX, destY, width, srceRgbBufferPtr, maskBuffer, GcDrawMode(iDrawMode)); sl@0: sl@0: srceX += KScanLineLength; sl@0: destX += KScanLineLength; sl@0: alphaX += KScanLineLength; sl@0: } sl@0: sl@0: srceY++; sl@0: destY++; sl@0: alphaY++; sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Tiles the scan line if its length in pixels is less than aLengthInPixels. sl@0: sl@0: @param aScanLine A pointer to the scan line buffer. sl@0: @param aLengthInPixels The scan line size in pixels. sl@0: @param aSrcPt Position of the first pixel in aMaskBitmap that should be used as a source sl@0: for the pixels in scan line buffer. sl@0: @param aMaskBitmap Any additional pixels for the scan line buffer will be taken from here. sl@0: @param aScanLinePos This argument is used for some internal optimisations. It should not be sl@0: modified by the caller. sl@0: @param aMaskBase The base address of aMaskBitmap data. sl@0: @param aDisplayMode Any additional pixels should be taken from aMaskBitmap using aDisplayMode sl@0: as an argument for GetScanLine() call. sl@0: @panic DGDIAdapter 1021, if the memory required for the scanline is greater than the size of aScanLine (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::TileScanLine(TPtr8& aScanLine, sl@0: TInt aLengthInPixels, sl@0: const TPoint& aSrcPt, sl@0: const CBitwiseBitmap* aMaskBitmap, sl@0: TLineScanningPosition& aScanLinePos, sl@0: TUint32* aMaskBase, sl@0: TDisplayMode aDisplayMode sl@0: ) sl@0: { sl@0: TInt lengthInBytes = CFbsBitmap::ScanLineLength(aLengthInPixels, aDisplayMode); sl@0: GRAPHICS_ASSERT_DEBUG(lengthInBytes <= aScanLine.MaxLength(), EDirectGdiPanicInvalidArg); sl@0: TInt scanLineLength = aScanLine.Length(); sl@0: if(scanLineLength < lengthInBytes && aSrcPt.iX > 0) sl@0: { sl@0: //If, for example, src bmp is 100 pixels width, mask bmp is 20 pixels width and src sl@0: //rect is (10, 0, 100, 1) -> We will read only pixels 10..19 from the first scan line sl@0: //of the mask bmp. We have to have 90 mask bmp pixels. sl@0: //So we have to make a second mask bmp read startig from pixel 0 - 10 pixels length. sl@0: TInt maxLen = Min(aScanLine.MaxLength() - scanLineLength, aSrcPt.iX); sl@0: TPtr8 maskDes2(const_cast (aScanLine.Ptr()) + scanLineLength, maxLen, maxLen); sl@0: TPoint srcPt(0, aSrcPt.iY); sl@0: TPoint zeroPt(0, 0); sl@0: aMaskBitmap->GetScanLine(maskDes2, srcPt, maxLen, EFalse, zeroPt, aDisplayMode, aMaskBase, aScanLinePos); sl@0: aScanLine.SetLength(scanLineLength + maskDes2.Length()); sl@0: scanLineLength = aScanLine.Length(); sl@0: } sl@0: if(scanLineLength >= lengthInBytes || scanLineLength == 0) sl@0: { sl@0: return; sl@0: } sl@0: //If we still don't have enough mask bmp pixels - we have to tile the scan line sl@0: TInt repeatCnt = lengthInBytes / scanLineLength - 1; sl@0: TInt bytesLeft = lengthInBytes % scanLineLength; sl@0: const TUint8* src = aScanLine.Ptr(); sl@0: TUint8* dest = const_cast (src) + scanLineLength; sl@0: for(;repeatCnt>0;dest+=scanLineLength,repeatCnt--) sl@0: { sl@0: Mem::Copy(dest, src, scanLineLength); sl@0: } sl@0: if(bytesLeft) sl@0: { sl@0: Mem::Copy(dest, src, bytesLeft); sl@0: } sl@0: aScanLine.SetLength(lengthInBytes); sl@0: } sl@0: sl@0: /** sl@0: Draws a masked rectangular section of the source bitmap and does a compress/stretch to sl@0: fit a given destination rectangle. It uses DoBitBltMasked() if no stretching is involved. sl@0: sl@0: @see DrawBitmapMasked() sl@0: sl@0: @param aDestRect The target position on the device containing the top left corner of the source bitmap. sl@0: @param aSourceBitmap The bitmap object that contains the pixels to draw. sl@0: @param aSourceBase The address of the source bitmap pixels. sl@0: @param aSourceRect The area of the bitmap to draw from. sl@0: @param aMaskBitmap The bitmap object that contains the mask. sl@0: @param aMaskBase The address of the mask pixels. sl@0: @param aInvertMask Inverts the mask if ETrue. sl@0: @param aClipRect A clipping rectangle. sl@0: @panic DGDIAdapter 1013, if the clipping rectangle is fully outside of the device bounds (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::DoDrawBitmapMasked(const TRect& aDestRect, sl@0: CBitwiseBitmap* aSourceBitmap, sl@0: TUint32* aSourceBase, sl@0: const TRect& aSourceRect, sl@0: CBitwiseBitmap* aMaskBitmap, sl@0: TUint32* aMaskBase, sl@0: TBool aInvertMask, sl@0: const TRect& aClipRect) sl@0: { sl@0: CFbsDrawDevice* drawDevice = iDrawDevice; sl@0: #ifdef _DEBUG sl@0: TRect deviceDestRect; sl@0: drawDevice->GetDrawRect(deviceDestRect); sl@0: GRAPHICS_ASSERT_DEBUG(aClipRect.iTl.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aClipRect.iTl.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aClipRect.iBr.iX <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aClipRect.iBr.iY <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: #endif sl@0: sl@0: // The clipped version of the destination rectangle sl@0: TRect clippedDestRect(aDestRect); sl@0: clippedDestRect.Intersection(aClipRect); sl@0: sl@0: // If the source rectangle and the destination rectangle are same, sl@0: // no stretch/compress operation required, just do BitBltMasked sl@0: if (aDestRect.Size() == aSourceRect.Size()) sl@0: { sl@0: if (!clippedDestRect.IsEmpty()) sl@0: { sl@0: const TPoint destPoint(clippedDestRect.iTl); sl@0: clippedDestRect.Move(aSourceRect.iTl - aDestRect.iTl); sl@0: DoBitBltMasked(destPoint, sl@0: aSourceBitmap, sl@0: aSourceBase, sl@0: clippedDestRect, sl@0: aMaskBitmap, sl@0: aMaskBase, sl@0: aInvertMask); sl@0: } sl@0: return; sl@0: } sl@0: sl@0: MFastBlend* fastBlend=NULL; sl@0: if (FastBlendInterface(aSourceBitmap,aMaskBitmap,fastBlend)==KErrNone) sl@0: { sl@0: if (fastBlend->FastBlendBitmapMaskedScaled(aClipRect, aDestRect, aSourceRect, aSourceBase, aSourceBitmap->DataStride(), sl@0: aSourceBitmap->DisplayMode(),aSourceBitmap->SizeInPixels(), sl@0: aMaskBase, aMaskBitmap->DataStride(), aMaskBitmap->DisplayMode(), aMaskBitmap->SizeInPixels(), aInvertMask, sl@0: GcDrawMode(iDrawMode), CFbsDrawDevice::ENoShadow)==KErrNone) sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: TUint32* scanLineBuffer = drawDevice->ScanLineBuffer(); sl@0: const TInt scanLineBytes = drawDevice->ScanLineBytes(); sl@0: TPtr8 scanLineDes(reinterpret_cast(scanLineBuffer),scanLineBytes,scanLineBytes); sl@0: sl@0: const TInt KScanLineLength = 256; sl@0: const TInt KRgbSize = 4; sl@0: TUint8 maskBuffer[KScanLineLength]; sl@0: sl@0: TUint8 sourceBuffer[KScanLineLength*KRgbSize]; sl@0: TPtr8 sourceDes(sourceBuffer,KScanLineLength*KRgbSize,KScanLineLength*KRgbSize); sl@0: sl@0: const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice); sl@0: CGraphicsContext::TDrawMode drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeANDNOT; sl@0: // If the source bitmap and the mask bitmap are same, draw the source bitmap either sl@0: // with EDrawModeAND or EDrawModeOR based on aInvertMask parameter. sl@0: if (aSourceBitmap == aMaskBitmap) sl@0: { sl@0: drawMode = aInvertMask ? CGraphicsContext::EDrawModeAND : CGraphicsContext::EDrawModeOR; sl@0: } sl@0: sl@0: TLinearDDA xLine; sl@0: TInt bitmapXStart = 0; sl@0: xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX), sl@0: TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft); sl@0: xLine.JumpToYCoord2(bitmapXStart,clippedDestRect.iTl.iX); sl@0: sl@0: TLinearDDA yLine; sl@0: TPoint yCoord(aSourceRect.iTl.iY,aDestRect.iTl.iY); sl@0: yLine.Construct(yCoord,TPoint(aSourceRect.iBr.iY,aDestRect.iBr.iY),TLinearDDA::ELeft); sl@0: TInt dummy; sl@0: yLine.JumpToYCoord2(dummy,clippedDestRect.iTl.iY); sl@0: yCoord.SetXY(dummy,clippedDestRect.iTl.iY); sl@0: sl@0: const TInt srceWidth = aSourceRect.Width(); sl@0: const TInt destWidth = aDestRect.Width(); sl@0: const TInt clipWidth = clippedDestRect.Width(); sl@0: const TInt clipStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX; sl@0: const TInt sourceBmpWidth = aSourceBitmap->SizeInPixels().iWidth; sl@0: const TInt maskWidth = aMaskBitmap->SizeInPixels().iWidth; sl@0: const TInt maskHeight = aMaskBitmap->SizeInPixels().iHeight; sl@0: sl@0: TLineScanningPosition lineScanPos(aSourceBase); sl@0: TLineScanningPosition lineScanPos2(aSourceBase); sl@0: TLineScanningPosition lineScanPosMask(aMaskBase); sl@0: sl@0: HBufC8* alphaBuffer = NULL; sl@0: TPtr8 alphaBufferDes(NULL, 0); sl@0: const TDisplayMode maskDisplayMode = aMaskBitmap->DisplayMode(); sl@0: sl@0: // Mask inversion is not supported if the original source mask format is EGray256. sl@0: // Note that this is only used for pre-multiplied alpha targets. sl@0: TUint8 maskInverter = (aInvertMask && maskDisplayMode != EGray256) ? 0xFF : 0x00; sl@0: sl@0: if (aSourceBitmap != aMaskBitmap) sl@0: { sl@0: // Get buffer to be used to convert non-EGray256 masks to EGray256 when display mode is EColor16MAP sl@0: // or to tile the mask when the mask width is smaller than the source bitmap width. sl@0: if (maskDisplayMode != EGray256 && (dispMode == EColor16MAP || maskWidth < sourceBmpWidth)) sl@0: { sl@0: alphaBuffer = CFbsBitmap::GetExtraBuffer(CFbsBitmap::ScanLineLength(maskWidth, EGray256)); sl@0: if (!alphaBuffer) sl@0: { sl@0: return; // Out of memory so do not draw anything sl@0: } sl@0: alphaBufferDes.Set(alphaBuffer->Des()); sl@0: } sl@0: sl@0: // Get buffer to be used for decompressing compressed masks when mask is EGray256 sl@0: if (maskDisplayMode == EGray256 && aMaskBitmap->IsCompressed()) sl@0: { sl@0: HBufC8* hBuf= CFbsBitmap::GetDecompressionBuffer(aMaskBitmap->DataStride()); sl@0: if (!hBuf) sl@0: { sl@0: return; // Out of memory so do not draw anything sl@0: } sl@0: lineScanPosMask.iScanLineBuffer = hBuf; sl@0: } sl@0: } sl@0: const TPoint KZeroPoint(0,0); sl@0: sl@0: while (yCoord.iY < clippedDestRect.iBr.iY) sl@0: { sl@0: // Draw only the source bitmap, if the source bitmap and the mask bitmap are same. sl@0: // else draw both the bitmaps sl@0: if (aSourceBitmap == aMaskBitmap) sl@0: { sl@0: aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX), sl@0: clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX, sl@0: srceWidth, KZeroPoint,dispMode,aSourceBase,lineScanPos); sl@0: if (yCoord.iY==clippedDestRect.iTl.iY) sl@0: aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL); sl@0: drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode); sl@0: } sl@0: else if ((maskDisplayMode == EGray256) || (dispMode == EColor16MAP)) sl@0: { sl@0: // Stretch the source bitmap and the mask bitmap for KScanLineLength as stretch length sl@0: // then do alpha blending for this length. If the length is more then KScanLineLength sl@0: // repeat it till you stretch complete destination length. sl@0: const TPoint startPt(bitmapXStart,yCoord.iX); sl@0: TInt clipWidthPart = clippedDestRect.Width(); sl@0: TBool loopLast = ETrue; sl@0: if(clipWidthPart > KScanLineLength) sl@0: { sl@0: clipWidthPart = KScanLineLength; sl@0: loopLast = EFalse; sl@0: } sl@0: TInt clipIncStrch = clippedDestRect.iTl.iX - aDestRect.iTl.iX; sl@0: TInt startClip=clippedDestRect.iTl.iX; sl@0: TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX); sl@0: xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX), sl@0: TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft); sl@0: xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY); sl@0: TPoint srcPixel(bitmapXStart % maskWidth,yCoord.iX % maskHeight); sl@0: TInt spaceLeft = 0; sl@0: TRgb maskRgbValue; sl@0: TUint32* maskScanLinePtr32 = NULL; sl@0: TPoint currentYValue(0,srcPixel.iY); sl@0: aMaskBitmap->GetScanLinePtr(maskScanLinePtr32, currentYValue, maskWidth, aMaskBase, lineScanPosMask); sl@0: // To implement non EGray256 mask support with EColor16MAP display mode, we convert sl@0: // the mask to EGray256. sl@0: if (maskDisplayMode != EGray256) // Convert scan-line to EGray256 and set maskScanLinePtr32 to the conversion. sl@0: { sl@0: aMaskBitmap->GetScanLine(maskScanLinePtr32, alphaBufferDes, currentYValue, maskWidth, EFalse, TPoint(0, 0), EGray256); sl@0: maskScanLinePtr32 = (TUint32*)alphaBuffer->Ptr(); sl@0: } sl@0: TUint8* maskScanLinePtr = reinterpret_cast(maskScanLinePtr32); sl@0: sl@0: // Outer loop over all KScanLineLengths sl@0: FOREVER sl@0: { sl@0: aSourceBitmap->StretchScanLine(sourceDes,startPt,clipIncStrch,clipWidthPart,destWidth, sl@0: aSourceRect.iTl.iX,srceWidth, KZeroPoint ,EColor16MU,aSourceBase,lineScanPos); sl@0: // Inner loop to tile the mask if necessary sl@0: spaceLeft = clipWidthPart; sl@0: do { sl@0: srcPixel.iX = sourceDestXCoords.iX % maskWidth; sl@0: sl@0: // Invert the mask using the inversion mask. sl@0: maskBuffer[(sourceDestXCoords.iY-clippedDestRect.iTl.iX)%KScanLineLength]= sl@0: maskInverter^maskScanLinePtr[srcPixel.iX]; sl@0: xLine.NextStep(sourceDestXCoords); sl@0: } while (--spaceLeft>0); sl@0: sl@0: if (yCoord.iY == clippedDestRect.iTl.iY && startClip == clippedDestRect.iTl.iX) sl@0: { sl@0: aSourceBitmap->SetCompressionBookmark(lineScanPos,aSourceBase,NULL); sl@0: aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL); sl@0: } sl@0: drawDevice->WriteRgbAlphaLine(startClip,yCoord.iY,clipWidthPart,sourceBuffer,maskBuffer, GcDrawMode(iDrawMode)); sl@0: if (loopLast) sl@0: { sl@0: break; sl@0: } sl@0: startClip+=KScanLineLength; sl@0: if (clippedDestRect.iBr.iX - startClip <= KScanLineLength) sl@0: { sl@0: loopLast = ETrue; sl@0: clipWidthPart = clippedDestRect.iBr.iX - startClip; sl@0: } sl@0: clipIncStrch += KScanLineLength; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX), sl@0: clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX, sl@0: srceWidth, KZeroPoint ,dispMode,aSourceBase,lineScanPos2); sl@0: drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,CGraphicsContext::EDrawModeXOR); sl@0: sl@0: TInt maskXStart = bitmapXStart % maskWidth; sl@0: if(maskWidth < sourceBmpWidth) sl@0: { sl@0: TPoint sourceDestXCoords(bitmapXStart,clippedDestRect.iTl.iX); sl@0: xLine.Construct(TPoint(aSourceRect.iTl.iX,aDestRect.iTl.iX), sl@0: TPoint(aSourceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft); sl@0: xLine.JumpToYCoord2(sourceDestXCoords.iX,sourceDestXCoords.iY); sl@0: TPoint srcPixel(maskXStart,yCoord.iX % maskHeight); sl@0: TInt spaceLeft = clipWidth; sl@0: TPoint prevSourceDestXCoords(-1,-1); sl@0: TRgb maskRgbValue; sl@0: aMaskBitmap->GetScanLine(alphaBufferDes, TPoint(0,srcPixel.iY), maskWidth, EFalse, TPoint(0, 0), EGray256, aMaskBase, lineScanPosMask); sl@0: sl@0: // Loop to tile the mask sl@0: do { sl@0: if (sourceDestXCoords.iY != prevSourceDestXCoords.iY) sl@0: { sl@0: if (sourceDestXCoords.iX != prevSourceDestXCoords.iX) sl@0: { sl@0: srcPixel.iX = sourceDestXCoords.iX % maskWidth; sl@0: if (srcPixel.iX < 0) sl@0: srcPixel.iX += maskWidth; sl@0: maskRgbValue = TRgb::Gray256((*alphaBuffer)[srcPixel.iX]); sl@0: } sl@0: drawDevice->WriteRgb(sourceDestXCoords.iY,yCoord.iY,maskRgbValue,drawMode); sl@0: spaceLeft--; sl@0: } sl@0: prevSourceDestXCoords = sourceDestXCoords; sl@0: xLine.SingleStep(sourceDestXCoords); sl@0: } while (spaceLeft > 0); sl@0: } sl@0: else sl@0: { sl@0: // No need to tile the mask sl@0: aMaskBitmap->StretchScanLine(scanLineDes,TPoint(maskXStart,yCoord.iX % maskHeight), sl@0: clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX, sl@0: srceWidth, KZeroPoint ,dispMode,aMaskBase,lineScanPosMask); sl@0: drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,drawMode); sl@0: // Redo stretching of the aSourceBitmap scanline sl@0: aSourceBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX), sl@0: clipStrch,clipWidth,destWidth,aSourceRect.iTl.iX, sl@0: srceWidth, KZeroPoint ,dispMode,aSourceBase,lineScanPos2); sl@0: } sl@0: sl@0: if (yCoord.iY==clippedDestRect.iTl.iY) sl@0: { sl@0: aSourceBitmap->SetCompressionBookmark(lineScanPos2,aSourceBase,NULL); sl@0: aMaskBitmap->SetCompressionBookmark(lineScanPosMask,aMaskBase,NULL); sl@0: } sl@0: sl@0: drawDevice->WriteLine(clippedDestRect.iTl.iX,yCoord.iY,clipWidth,scanLineBuffer,CGraphicsContext::EDrawModeXOR); sl@0: } sl@0: yLine.NextStep(yCoord); sl@0: } sl@0: } sl@0: sl@0: TInt CSwDirectGdiEngine::FastBlendInterface(const CBitwiseBitmap* aSource, const CBitwiseBitmap* aMask, MFastBlend*& aFastBlend) const sl@0: { sl@0: #if defined(__ALLOW_FAST_BLEND_DISABLE__) sl@0: if (iFastBlendDisabled) sl@0: return(KErrNotSupported); sl@0: #endif sl@0: if ((aSource && aSource->IsCompressed()) || (aMask && aMask->IsCompressed())) sl@0: return(KErrNotSupported); sl@0: TAny* interface=NULL; sl@0: TInt ret= iDrawDevice->GetInterface(KFastBlendInterfaceID, interface); sl@0: aFastBlend=(MFastBlend*)interface; sl@0: return(ret); sl@0: } sl@0: sl@0: /* sl@0: 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: sl@0: @see CBitwiseBitmap::GetScanLine() sl@0: @see CBitwiseBitmap::GetVerticalScanLine() sl@0: @see CBitwiseBitmap::StretchScanLine() sl@0: @see CFbsDrawDevice::WriteLine() sl@0: @internalComponent sl@0: */ sl@0: TDisplayMode CSwDirectGdiEngine::ScanLineBufferDisplayMode(CFbsDrawDevice* aDrawDevice) sl@0: { sl@0: return iDrawMode == DirectGdi::EDrawModeWriteAlpha ? aDrawDevice->DisplayMode() : aDrawDevice->ScanLineDisplayMode(); sl@0: }