--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgditext.cpp Tue Feb 02 01:47:50 2010 +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 <bitdrawinterfaceid.h>
+#include <bmalphablend.h>
+
+/**
+@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 <TAny*&> (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 <TAny*&> (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;
+ }