diff -r 000000000000 -r bde4ae8d615e os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgditext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgditext.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,818 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "swdirectgdiengine.h" +#include +#include + +/** +@see MDirectGdiEngine::SetFont() +*/ +void CSwDirectGdiEngine::SetFont(TUint32 /*aFontId*/) + { + // Do nothing. + // The SW adapter doesn't need the font ID to index a separate font cache because it uses the standard one. + } + + +/** +@see MDirectGdiEngine::ResetFont() +*/ +void CSwDirectGdiEngine::ResetFont() + { + } + + +/** +@see MDirectGdiEngine::SetTextShadowColor() +*/ +void CSwDirectGdiEngine::SetTextShadowColor(const TRgb& aColor) + { + iTextShadowColor = aColor; + } + +/** +@see MDirectGdiEngine::BeginDrawGlyph() +*/ +void CSwDirectGdiEngine::BeginDrawGlyph() + { + } + +/** +@see MDirectGdiEngine::DrawGlyph() +@panic DGDIAdapter 56, if an invalid glyph bitmap type is passed in. +*/ +void CSwDirectGdiEngine::DrawGlyph(const TPoint& aScrPos, const TChar /*aChar*/, const TUint8* aGlyphImage, + const TGlyphBitmapType aGlyphBitmapType, const TSize& aGlyphImageSize, + const TRect& aScrClipRect, const DirectGdi::TGraphicsRotation aRotation) + { + TPoint pos=aScrPos; + pos+=iDrawOrigin; + TRect clipRect=aScrClipRect; + clipRect.iTl+=iDrawOrigin; + clipRect.iBr+=iDrawOrigin; + TRect regionRect(0, 0, 0, 0); + TInt numRects = iDefaultRegionPtr->Count(); + for (TInt count = 0; count < numRects; count++) + { + // Do the clip rects intersect? + regionRect = (*iDefaultRegionPtr)[count]; + if (!regionRect.Intersects(clipRect)) + { + // Nothing to draw + continue; + } + // Clip to intersection of two clip rects + regionRect.Intersection(clipRect); + + if (aRotation == DirectGdi::EGraphicsRotationNone) // Horizontal text + { + // Do the glyph and the clip rect intersect? + TRect glyphRect(pos, aGlyphImageSize); + if (!regionRect.Intersects(glyphRect)) + { + // Nothing to draw + continue; + } + // Clip to intersection with glyph bitmap + regionRect.Intersection(glyphRect); + + switch (aGlyphBitmapType) + { + case EMonochromeGlyphBitmap: + { + DrawBitmapGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect); + break; + } + case EAntiAliasedGlyphBitmap: + { + DrawAntiAliasedGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect); + break; + } + case EFourColourBlendGlyphBitmap: + { + DrawFourColourGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect); + break; + } + default: + GRAPHICS_PANIC_ALWAYS(EDirectGdiPanicInvalidGlyphBitmapType); + } + } + else // Vertical text + { + /* + // Do the glyph and the clip rect intersect? + TRect glyphRect(aPos, aGlyphImageSize); + if (!regionRect.Intersects(glyphRect)) + { + // Nothing to draw + continue; + } + // Clip to intersection with glyph bitmap + regionRect.Intersection(glyphRect); + */ + + switch (aGlyphBitmapType) + { + case EMonochromeGlyphBitmap: + { + DrawRotatedBitmapGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect, aRotation); + break; + } + case EAntiAliasedGlyphBitmap: + { + DrawRotatedAntiAliasedGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect, aRotation); + break; + } + case EFourColourBlendGlyphBitmap: + { + DrawRotatedFourColourGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect, aRotation); + break; + } + default: + GRAPHICS_PANIC_ALWAYS(EDirectGdiPanicInvalidGlyphBitmapType); + } + } + // Now display it + iDrawDevice->UpdateRegion(regionRect); + } + } + +/** +@see MDirectGdiEngine::EndDrawGlyph() +*/ +void CSwDirectGdiEngine::EndDrawGlyph() + { + } + +/** +Draw a bitmap glyph. + +@param aPos Position to start drawing gyph. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +*/ +void CSwDirectGdiEngine::DrawBitmapGlyph(const TPoint& aPos, const TUint8* aGlyphImage, + const TSize& aGlyphImageSize, const TRect& aClipRect) + { + // aChar parameter not needed because SW implementation uses the default glyph cache + // therefore does not need aChar to index its own local cache + + /* + Divert if the character is large. + Large is defined as wider than 30 bits (a scan line won't fit in a TInt32) + or greater than 32 bits high (because that's the current array size - could be changed). + */ + TInt dataHeight = aGlyphImageSize.iHeight; + TInt dataLength = aGlyphImageSize.iWidth; + if (dataLength > 30 || dataHeight > 32) + { + DrawLargeBitmapGlyph(aPos, aGlyphImage, aGlyphImageSize, aClipRect); + return; + } + + TInt bitIndex = 0; + TInt16 repeatCount = 0; + TUint32 binaryData[32]; + TUint32* binaryDataPtr = binaryData; + TUint32* binaryDataPtrLimit; + for (TInt glyphLine = 0; glyphLine < dataHeight; glyphLine += repeatCount) // for lines in the glyph bitmap + { + repeatCount = Load16(aGlyphImage + (bitIndex >> 3)); + repeatCount >>= bitIndex & 7; + TInt multiLineFlag = repeatCount & 1; + repeatCount >>= 1; + repeatCount &= 0xf; + bitIndex += 5; + binaryDataPtrLimit = binaryData + glyphLine + repeatCount; + if (multiLineFlag) + { + while (binaryDataPtr < binaryDataPtrLimit) + { + TInt glyphDataOffsetPtr = TInt(aGlyphImage) + (bitIndex >> 3); + TUint32* glyphDataWord = (TUint32*)(glyphDataOffsetPtr & ~3); + TInt bitShift = bitIndex & 7; + bitShift += (glyphDataOffsetPtr & 3) << 3; + *binaryDataPtr = (*glyphDataWord++) >> bitShift; + if (bitShift) + { + *binaryDataPtr |= (*glyphDataWord << (32 - bitShift)); + } + bitIndex += dataLength; + binaryDataPtr++; + } + } + else + { + TInt glyphDataOffsetPtr = TInt(aGlyphImage) + (bitIndex >> 3); + TUint32* glyphDataWord = (TUint32*)(glyphDataOffsetPtr & ~3); + TInt bitShift = bitIndex & 7; + bitShift += (glyphDataOffsetPtr & 3) << 3; + TUint32 data = (*glyphDataWord++) >> bitShift; + if (bitShift) + { + data |= (*glyphDataWord << (32 - bitShift)); + } + while (binaryDataPtr < binaryDataPtrLimit) + { + *binaryDataPtr++ = data; + } + bitIndex += dataLength; + } + } + TPoint topLeft(aPos); + binaryDataPtr = ClipBinaryArray(binaryData, binaryData + dataHeight, dataLength, dataHeight, topLeft, aClipRect); + if ((dataLength > 0) && (dataHeight > 0)) + { + iDrawDevice->WriteBinary(topLeft.iX, topLeft.iY, binaryDataPtr, dataLength, dataHeight, iPenColor, GcDrawMode(iDrawMode) ); + } + } + + +/** +Draw a large bitmap glyph. + +@param aPos Position to start drawing gyph. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +*/ +void CSwDirectGdiEngine::DrawLargeBitmapGlyph(const TPoint& aPos, const TUint8* aGlyphImage, + const TSize& aGlyphImageSize, const TRect& aClipRect) + { + TPoint printPos(aPos); + const TInt dataLength = aGlyphImageSize.iWidth; + const TInt dataHeight = aGlyphImageSize.iHeight; + TInt bitIndex = 0; + TInt16 repeatCount = 0; + TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer(); + const TInt scanLineWords = (iDrawDevice->ScanLineBytes()) << 3; + for (TInt glyphLine = 0; glyphLine < dataHeight; glyphLine += repeatCount) // for lines in the glyph bitmap + { + repeatCount = Load16(aGlyphImage + (bitIndex >> 3)); + repeatCount >>= bitIndex & 7; + const TInt multiLineFlag = repeatCount & 1; + repeatCount >>= 1; + repeatCount &= 0xf; + bitIndex += 5; + if (multiLineFlag) + { + for (TInt currentLine = 0; currentLine < repeatCount; currentLine++) + { + CopyCharLine(scanLineBuffer, scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength); + OutputCharLineMultiplied(printPos, scanLineBuffer, dataLength, 1, aClipRect); + bitIndex += dataLength; + printPos.iY++; + } + } + else + { + CopyCharLine(scanLineBuffer, scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength); + OutputCharLineMultiplied(printPos, scanLineBuffer, dataLength, repeatCount, aClipRect); + printPos.iY += repeatCount; + bitIndex += dataLength; + } + } + } + + +/** + +*/ +void CSwDirectGdiEngine::CopyCharLine(TUint32* aBinaryDataPtr, TInt aBufferWords, const TUint8* aData, TInt aBitShift, TInt aCharWidth) + { + aBitShift &= 7; + TInt wordsToCopy = (aCharWidth + 31) >> 5; + if (wordsToCopy > aBufferWords) + { + wordsToCopy = aBufferWords; + } + TUint32* ptrLimit = aBinaryDataPtr + wordsToCopy; + TUint32* dataWord = (TUint32*)(TInt(aData) & ~3); + aBitShift += (TInt(aData) - TInt(dataWord)) << 3; + while (aBinaryDataPtr < ptrLimit) + { + *aBinaryDataPtr = *dataWord++; + *aBinaryDataPtr >>= aBitShift; + if (aBitShift) + { + *aBinaryDataPtr |= (*dataWord << (32 - aBitShift)); + } + aBinaryDataPtr++; + } + } + + +/** + +*/ +void CSwDirectGdiEngine::OutputCharLineMultiplied(TPoint aPrintPos, TUint32* aBuffer, TInt aDataLength, TInt aNum, const TRect& aClipRect) + { + if (aDataLength <= 0) + { + return; + } + TInt bufferWords = (aDataLength + 31) >> 5; + TUint32* bufferLimit = aBuffer + bufferWords; + if (aPrintPos.iX < aClipRect.iTl.iX) + { + TInt pixelExcess = aClipRect.iTl.iX - aPrintPos.iX; + while (pixelExcess >= 32) + { + aBuffer++; + bufferWords--; + aDataLength -= 32; + pixelExcess -= 32; + } + if (aDataLength <= 0) + { + return; + } + if (pixelExcess > 0) + { + TInt shiftUp = 32 - pixelExcess; + TUint32* bufferPtr = aBuffer; + while (bufferPtr < bufferLimit) + { + *bufferPtr >>= pixelExcess; + if (bufferPtr < bufferLimit - 1) + { + *bufferPtr |= (*(bufferPtr + 1) << shiftUp); + } + bufferPtr++; + } + aDataLength -= pixelExcess; + if (aDataLength <= 0) + { + return; + } + } + aPrintPos.iX = aClipRect.iTl.iX; + } + if (aPrintPos.iX + aDataLength > aClipRect.iBr.iX) + { + TInt pixelExcess = aPrintPos.iX + aDataLength - aClipRect.iBr.iX; + aDataLength -= pixelExcess; + if (aDataLength <= 0) + { + return; + } + } + while (aNum > 0) + { + if ((aPrintPos.iY >= aClipRect.iTl.iY) && (aPrintPos.iY < aClipRect.iBr.iY)) + { + iDrawDevice->WriteBinaryLine(aPrintPos.iX, aPrintPos.iY, aBuffer, aDataLength, iPenColor, GcDrawMode(iDrawMode)); + } + aPrintPos.iY++; + aNum--; + } + } + + +/** +Draw a rotated bitmap glyph. + +@param aPos Position to start drawing glyph after rotation has been applied. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +@param aRotation Rotation specifying how the glyph will be drawn. +*/ +void CSwDirectGdiEngine::DrawRotatedBitmapGlyph(const TPoint& aPos, const TUint8* aGlyphImage, + const TSize& aGlyphImageSize, const TRect& aClipRect, const DirectGdi::TGraphicsRotation aRotation) + { + TPoint printPos(aPos); + TInt dataLength = aGlyphImageSize.iWidth; + TInt dataHeight = aGlyphImageSize.iHeight; + TInt bitIndex = 0; + TInt16 repeatCount = 0; + TInt direction = (aRotation == DirectGdi::EGraphicsRotation270) ? 1 : -1; + TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer(); + TInt scanLineWords = (iDrawDevice->ScanLineBytes()) << 3; + for (TInt glyphLine = 0; glyphLine < dataHeight; glyphLine += repeatCount) // for lines in the glyph bitmap... + { + repeatCount = Load16(aGlyphImage + (bitIndex >> 3)); + repeatCount >>= bitIndex & 7; + TInt multiLineFlag = repeatCount & 1; + repeatCount >>= 1; + repeatCount &= 0xf; + bitIndex += 5; + TInt signedRepeatCount = repeatCount * direction; + if (multiLineFlag) + { + for (TInt currentLine = 0; currentLine < repeatCount; currentLine++) + { + CopyCharLine(scanLineBuffer, scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength); + OutputCharLineVertical(printPos, scanLineBuffer, dataLength, 1, direction, aClipRect); + bitIndex += dataLength; + printPos.iX += direction; + } + } + else + { + CopyCharLine(scanLineBuffer,scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength); + OutputCharLineVertical(printPos, scanLineBuffer, dataLength, repeatCount, direction, aClipRect); + printPos.iX += signedRepeatCount; + bitIndex += dataLength; + } + } + } + + +/** + +*/ +void CSwDirectGdiEngine::OutputCharLineVertical(TPoint aPrintPos, TUint32* aBuffer, TInt aDataLength, + TInt aNum, TInt aDirection, const TRect& aClipRect) + { +// const DirectGdi::TGraphicsRotation rotation = aUp ? DirectGdi::EGraphicsRotation270 : DirectGdi::EGraphicsRotation90; +// TInt direction = (aRotation == DirectGdi::EGraphicsRotation270) ? 1 : -1; + if (aDataLength <= 0) + { + return; + } + TInt bufferWords = (aDataLength + 31) >> 5; + TUint32* bufferLimit = aBuffer + bufferWords; + if (aDirection == 1) + { + if (aPrintPos.iY >= aClipRect.iBr.iY) + { + TInt pixelExcess = aPrintPos.iY - aClipRect.iBr.iY + 1; + while (pixelExcess >= 32) + { + aBuffer++; + aDataLength -= 32; + pixelExcess -= 32; + } + if (aDataLength <= 0) + { + return; + } + if (pixelExcess > 0) + { + TInt shiftUp = 32 - pixelExcess; + TUint32* bufferPtr = aBuffer; + while (bufferPtr < bufferLimit) + { + *bufferPtr >>= pixelExcess; + if (bufferPtr < bufferLimit - 1) + *bufferPtr |= (*(bufferPtr + 1) << shiftUp); + bufferPtr++; + } + aDataLength -= pixelExcess; + if (aDataLength <= 0) + { + return; + } + } + aPrintPos.iY = aClipRect.iBr.iY - 1; + } + if ((aPrintPos.iY - aDataLength) < (aClipRect.iTl.iY - 1)) + { + TInt pixelExcess = aClipRect.iTl.iY - 1 - aPrintPos.iY + aDataLength; + aDataLength -= pixelExcess; + if (aDataLength <= 0) + { + return; + } + } + } + else + { + if (aPrintPos.iY < aClipRect.iTl.iY) + { + TInt pixelExcess = aClipRect.iTl.iY - aPrintPos.iY; + while (pixelExcess >= 32) + { + aBuffer++; + aDataLength -= 32; + pixelExcess -= 32; + } + if (aDataLength <= 0) + { + return; + } + if (pixelExcess > 0) + { + TInt shiftup = 32 - pixelExcess; + TUint32* bufferptr = aBuffer; + while (bufferptr < bufferLimit) + { + *bufferptr >>= pixelExcess; + if (bufferptr < bufferLimit - 1) + *bufferptr |= (*(bufferptr + 1) << shiftup); + bufferptr++; + } + aDataLength -= pixelExcess; + if (aDataLength <= 0) + { + return; + } + } + aPrintPos.iY = aClipRect.iTl.iY; + } + if (aPrintPos.iY + aDataLength > aClipRect.iBr.iY) + { + TInt pixelExcess = aPrintPos.iY + aDataLength - aClipRect.iBr.iY; + aDataLength -= pixelExcess; + if (aDataLength <= 0) + { + return; + } + } + } + CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode); + while (aNum > 0) + { + if ((aPrintPos.iX >= aClipRect.iTl.iX) && (aPrintPos.iX < aClipRect.iBr.iX)) + iDrawDevice->WriteBinaryLineVertical(aPrintPos.iX, aPrintPos.iY, aBuffer, aDataLength, iPenColor, drawMode, (aDirection == 1)); + aPrintPos.iX += aDirection; + aNum--; + } + } + + +/** +Draw an antialiased glyph. + +@param aPos Position to start drawing gyph. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +*/ +void CSwDirectGdiEngine::DrawAntiAliasedGlyph(const TPoint& aPos, const TUint8* aGlyphImage, + const TSize& aGlyphImageSize, const TRect& aClipRect) + { + const TInt topRow = Max(0, aClipRect.iTl.iY - aPos.iY); + const TInt bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iY - aPos.iY); + const TInt leftCol = Max(0, aClipRect.iTl.iX - aPos.iX); + const TInt rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iX - aPos.iX); + const TUint8* p = aGlyphImage + (topRow * aGlyphImageSize.iWidth) + leftCol; + const TInt x = aPos.iX + leftCol; + TInt y = aPos.iY + topRow; + const TInt cols = rightCol - leftCol; + + for (TInt row = topRow; row < bottomRow; row++, p += aGlyphImageSize.iWidth, y++) + { + iDrawDevice->WriteRgbAlphaMulti(x, y, cols, iPenColor, p); + } + } + + +/** +Draw a rotated antialiased glyph. + +@param aPos Position to start drawing gyph after rotation has been applied. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +@param aRotation Rotation specifying how the glyph will be drawn. +*/ +void CSwDirectGdiEngine::DrawRotatedAntiAliasedGlyph(const TPoint& aPos, const TUint8* aGlyphImage, + const TSize& aGlyphImageSize, const TRect& aClipRect, const DirectGdi::TGraphicsRotation aRotation) + { + const int KBufferSize = 32; + TUint8 maskBuffer[KBufferSize]; + int topRow = 0; + int bottomRow = 0; + int leftCol = 0; + int rightCol = 0; + const TUint32 penColor = iPenColor.Internal(); + const TUint32 brushColor = iBrushColor.Internal(); + + if (aRotation == DirectGdi::EGraphicsRotation270) + { + topRow = Max(0, aClipRect.iTl.iX - aPos.iX); + bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iX - aPos.iX); + leftCol = Max(0, aPos.iY - aClipRect.iBr.iY + 1); + rightCol = Min(aGlyphImageSize.iWidth, aPos.iY - aClipRect.iTl.iY + 1); + TInt y = aPos.iY - (rightCol - 1); + for (TInt col = rightCol - 1; col >= leftCol; col--, y++) + { + TInt x = aPos.iX + topRow; + for (TInt row = topRow; row < bottomRow; row += KBufferSize, x += KBufferSize) + { + TInt length = KBufferSize; + if (length > bottomRow - row) + { + length = bottomRow - row; + } + const TUint8* p = aGlyphImage + row * aGlyphImageSize.iWidth + col; + for (TInt i = 0; i < length; i++, p += aGlyphImageSize.iWidth) + { + maskBuffer[i] = *p; + } + iDrawDevice->WriteRgbAlphaMulti(x, y, length, iPenColor, maskBuffer); + } + } + } + else + { + topRow = Max(0, aPos.iX - aClipRect.iBr.iX + 1); + bottomRow = Min(aGlyphImageSize.iHeight, aPos.iX - aClipRect.iTl.iX + 1); + leftCol = Max(0, aClipRect.iTl.iY - aPos.iY); + rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iY - aPos.iY); + int y = aPos.iY + leftCol; + for (TInt col = leftCol; col < rightCol; col++, y++) + { + TInt x = aPos.iX - (bottomRow - 1); + for (TInt row = bottomRow; row > topRow; row -= KBufferSize, x += KBufferSize) + { + int length = KBufferSize; + if (length > row - topRow) + length = row - topRow; + const TUint8* p = aGlyphImage + (row - 1) * aGlyphImageSize.iWidth + col; + for (TInt i = 0; i < length; i++, p -= aGlyphImageSize.iWidth) + { + maskBuffer[i] = *p; + } + iDrawDevice->WriteRgbAlphaMulti(x, y, length, iPenColor, maskBuffer); + } + } + } + } + + +/** +Draw a four colour glyph. + +@param aPos Position to start drawing gyph. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +*/ +void CSwDirectGdiEngine::DrawFourColourGlyph(const TPoint& aPos, const TUint8* aGlyphImage, + const TSize& aGlyphImageSize, const TRect& aClipRect) + { + const TInt topRow = Max(0, aClipRect.iTl.iY - aPos.iY); + const TInt bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iY - aPos.iY); + const TInt leftCol = Max(0, aClipRect.iTl.iX - aPos.iX); + const TInt rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iX - aPos.iX); + const TUint8* p = aGlyphImage + (topRow * aGlyphImageSize.iWidth) + leftCol; + const TInt x = aPos.iX + leftCol; + TInt y = aPos.iY + topRow; + const TInt cols = rightCol - leftCol; + const TUint32 penColor = iPenColor.Internal(); + const TUint32 shadowColor = iTextShadowColor.Internal(); + const TUint32 brushColor = iBrushColor.Internal(); + + MOutlineAndShadowBlend* outlineAndShadow = NULL; + const TInt err = iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast (outlineAndShadow)); + if (err == KErrNone) + { + //There is a support for the interface with KOutlineAndShadowInterface id. + for (TInt row = topRow; row < bottomRow; row++, p += aGlyphImageSize.iWidth, y++) + { + outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p); + } + } + else + { + // Assert if MOutlineAndShadowBlend interface is not implemented + GRAPHICS_ASSERT_DEBUG(outlineAndShadow, EDirectGdiPanicInvalidInterfaceHandle); + } + } + + +/** +Draw a rotated four colour glyph. + +@param aPos Position to start drawing gyph after rotation has been applied. +@param aGlyphImage Pointer to the glyph image data. +@param aGlyphImageSize Glyph image size. +@param aClipRect Clipping rect. +@param aRotation Rotation specifying how the glyph will be drawn. +*/ +void CSwDirectGdiEngine::DrawRotatedFourColourGlyph(const TPoint& aPos, const TUint8* aGlyphImage, const TSize& aGlyphImageSize, + const TRect& aClipRect, const DirectGdi::TGraphicsRotation aRotation) + { + const int KBufferSize = 32; + TUint8 maskBuffer[KBufferSize]; + int topRow = 0; + int bottomRow = 0; + int leftCol = 0; + int rightCol = 0; + const TUint32 penColor = iPenColor.Internal(); + const TUint32 shadowColor = iTextShadowColor.Internal(); + const TUint32 brushColor = iBrushColor.Internal(); + + MOutlineAndShadowBlend* outlineAndShadow = NULL; + TInt err = iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast (outlineAndShadow)); + if(err != KErrNone) + { + // Assert if MOutlineAndShadowBlend interface is not implemented + GRAPHICS_ASSERT_DEBUG(outlineAndShadow, EDirectGdiPanicInvalidInterfaceHandle); + } + + if (aRotation == DirectGdi::EGraphicsRotation270) + { + topRow = Max(0, aClipRect.iTl.iX - aPos.iX); + bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iX - aPos.iX); + leftCol = Max(0, aPos.iY - aClipRect.iBr.iY + 1); + rightCol = Min(aGlyphImageSize.iWidth, aPos.iY - aClipRect.iTl.iY + 1); + TInt y = aPos.iY - (rightCol - 1); + for (TInt col = rightCol - 1; col >= leftCol; col--, y++) + { + TInt x = aPos.iX + topRow; + for (TInt row = topRow; row < bottomRow; row += KBufferSize, x += KBufferSize) + { + TInt length = KBufferSize; + if (length > bottomRow - row) + { + length = bottomRow - row; + } + const TUint8* p = aGlyphImage + row * aGlyphImageSize.iWidth + col; + for (TInt i = 0; i < length; i++, p += aGlyphImageSize.iWidth) + { + maskBuffer[i] = *p; + } + //There is a support for the interface with KOutlineAndShadowInterface id. + outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor, brushColor, maskBuffer); + } + } + } + else + { + topRow = Max(0, aPos.iX - aClipRect.iBr.iX + 1); + bottomRow = Min(aGlyphImageSize.iHeight, aPos.iX - aClipRect.iTl.iX + 1); + leftCol = Max(0, aClipRect.iTl.iY - aPos.iY); + rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iY - aPos.iY); + int y = aPos.iY + leftCol; + for (TInt col = leftCol; col < rightCol; col++, y++) + { + TInt x = aPos.iX - (bottomRow - 1); + for (TInt row = bottomRow; row > topRow; row -= KBufferSize, x += KBufferSize) + { + int length = KBufferSize; + if (length > row - topRow) + length = row - topRow; + const TUint8* p = aGlyphImage + (row - 1) * aGlyphImageSize.iWidth + col; + for (TInt i = 0; i < length; i++, p -= aGlyphImageSize.iWidth) + { + maskBuffer[i] = *p; + } + //There is a support for the interface with KOutlineAndShadowInterface id. + outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor, brushColor, maskBuffer); + } + } + } + } + + +/** +Helper function to clip the array to the clip rect. + +@param aArray Start of array of data to be clipped. +@param aArrayLimit End of array of data to be clipped. +@param aDataWd Length of data. +@param aDataHt Height of data. +@param aPos Position to start drawing from. +@param aClipRect Rectangle to clip data array to. + +@return Pointer to array of clipped data. +*/ +TUint32* CSwDirectGdiEngine::ClipBinaryArray(TUint32* aArray, TUint32* aArrayLimit, TInt& aDataWd, TInt& aDataHt, TPoint& aPos, const TRect& aClipRect) + { + TUint32* arrayPtr = aArray; + TInt clipDiff = aClipRect.iTl.iX - aPos.iX; + if (clipDiff > 0) + { + while (arrayPtr < aArrayLimit) + { + *arrayPtr++ >>= clipDiff; + } + aDataWd -= clipDiff; + aPos.iX = aClipRect.iTl.iX; + arrayPtr = aArray; + } + if ((aPos.iX + aDataWd > aClipRect.iBr.iX) && (aDataWd > 0)) + { + aDataWd = aClipRect.iBr.iX - aPos.iX; + } + clipDiff = aClipRect.iTl.iY - aPos.iY; + if (clipDiff > 0) + { + aDataHt -= clipDiff; + arrayPtr += clipDiff; + aPos.iY = aClipRect.iTl.iY; + } + if (((aPos.iY + aDataHt) > (aClipRect.iBr.iY)) && (aDataHt > 0)) + { + aDataHt = aClipRect.iBr.iY - aPos.iY; + } + return arrayPtr; + }