graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgditext.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "swdirectgdiengine.h"
       
    17 #include <bitdrawinterfaceid.h>
       
    18 #include <bmalphablend.h>
       
    19 
       
    20 /**
       
    21 @see MDirectGdiEngine::SetFont()
       
    22 */
       
    23 void CSwDirectGdiEngine::SetFont(TUint32 /*aFontId*/)
       
    24 	{
       
    25 	// Do nothing.
       
    26 	// The SW adapter doesn't need the font ID to index a separate font cache because it uses the standard one.
       
    27 	}
       
    28 
       
    29 
       
    30 /**
       
    31 @see MDirectGdiEngine::ResetFont()
       
    32 */
       
    33 void CSwDirectGdiEngine::ResetFont()
       
    34 	{
       
    35 	}
       
    36 
       
    37 
       
    38 /**
       
    39 @see MDirectGdiEngine::SetTextShadowColor()
       
    40 */
       
    41 void CSwDirectGdiEngine::SetTextShadowColor(const TRgb& aColor)
       
    42 	{	
       
    43 	iTextShadowColor = aColor;
       
    44 	}
       
    45 
       
    46 /**
       
    47 @see MDirectGdiEngine::BeginDrawGlyph()
       
    48 */
       
    49 void CSwDirectGdiEngine::BeginDrawGlyph()
       
    50 	{
       
    51 	}
       
    52 
       
    53 /**
       
    54 @see MDirectGdiEngine::DrawGlyph()
       
    55 @panic DGDIAdapter 56, if an invalid glyph bitmap type is passed in.
       
    56 */
       
    57 void CSwDirectGdiEngine::DrawGlyph(const TPoint& aScrPos, const TChar /*aChar*/, const TUint8* aGlyphImage,
       
    58 								   const TGlyphBitmapType aGlyphBitmapType, const TSize& aGlyphImageSize,
       
    59 								   const TRect& aScrClipRect, const DirectGdi::TGraphicsRotation aRotation)
       
    60 	{
       
    61 	TPoint pos=aScrPos;
       
    62 	pos+=iDrawOrigin;
       
    63 	TRect clipRect=aScrClipRect;
       
    64 	clipRect.iTl+=iDrawOrigin;
       
    65 	clipRect.iBr+=iDrawOrigin;
       
    66 	TRect regionRect(0, 0, 0, 0);
       
    67 	TInt numRects = iDefaultRegionPtr->Count();
       
    68 	for (TInt count = 0; count < numRects; count++)
       
    69 		{
       
    70 		// Do the clip rects intersect?
       
    71 		regionRect = (*iDefaultRegionPtr)[count];
       
    72 		if (!regionRect.Intersects(clipRect))
       
    73 			{
       
    74 			// Nothing to draw
       
    75 			continue;
       
    76 			}
       
    77 		// Clip to intersection of two clip rects
       
    78 		regionRect.Intersection(clipRect);
       
    79 		
       
    80 		if (aRotation == DirectGdi::EGraphicsRotationNone)	// Horizontal text
       
    81 			{
       
    82 			// Do the glyph and the clip rect intersect?
       
    83 			TRect glyphRect(pos, aGlyphImageSize);
       
    84 			if (!regionRect.Intersects(glyphRect))
       
    85 				{
       
    86 				// Nothing to draw
       
    87 				continue;
       
    88 				}
       
    89 			// Clip to intersection with glyph bitmap 
       
    90 			regionRect.Intersection(glyphRect);
       
    91 			
       
    92 			switch (aGlyphBitmapType)
       
    93 				{
       
    94 				case EMonochromeGlyphBitmap:
       
    95 					{
       
    96 					DrawBitmapGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect);
       
    97 					break;
       
    98 					}
       
    99 				case EAntiAliasedGlyphBitmap:
       
   100 					{
       
   101 					DrawAntiAliasedGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect);
       
   102 					break;
       
   103 					}
       
   104 				case EFourColourBlendGlyphBitmap:
       
   105 					{
       
   106 					DrawFourColourGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect);
       
   107 					break;
       
   108 					}
       
   109 				default:
       
   110 					GRAPHICS_PANIC_ALWAYS(EDirectGdiPanicInvalidGlyphBitmapType);
       
   111 				}
       
   112 			}
       
   113 		else	// Vertical text
       
   114 			{
       
   115 			/*
       
   116 			// Do the glyph and the clip rect intersect?
       
   117 			TRect glyphRect(aPos, aGlyphImageSize);
       
   118 			if (!regionRect.Intersects(glyphRect))
       
   119 				{
       
   120 				// Nothing to draw
       
   121 				continue;
       
   122 				}
       
   123 			// Clip to intersection with glyph bitmap 
       
   124 			regionRect.Intersection(glyphRect);
       
   125 			*/
       
   126 			
       
   127 			switch (aGlyphBitmapType)
       
   128 				{
       
   129 				case EMonochromeGlyphBitmap:
       
   130 					{
       
   131 					DrawRotatedBitmapGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect, aRotation);
       
   132 					break;
       
   133 					}
       
   134 				case EAntiAliasedGlyphBitmap:
       
   135 					{
       
   136 					DrawRotatedAntiAliasedGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect, aRotation);
       
   137 					break;
       
   138 					}
       
   139 				case EFourColourBlendGlyphBitmap:
       
   140 					{
       
   141 					DrawRotatedFourColourGlyph(pos, aGlyphImage, aGlyphImageSize, regionRect, aRotation);
       
   142 					break;
       
   143 					}
       
   144 				default:
       
   145 					GRAPHICS_PANIC_ALWAYS(EDirectGdiPanicInvalidGlyphBitmapType);
       
   146 				}
       
   147 			}
       
   148 		// Now display it
       
   149 		iDrawDevice->UpdateRegion(regionRect);
       
   150 		}
       
   151 	}
       
   152 
       
   153 /**
       
   154 @see MDirectGdiEngine::EndDrawGlyph()
       
   155 */
       
   156 void CSwDirectGdiEngine::EndDrawGlyph()
       
   157 	{
       
   158 	}
       
   159 
       
   160 /**
       
   161 Draw a bitmap glyph.
       
   162 	
       
   163 @param	aPos			Position to start drawing gyph.
       
   164 @param	aGlyphImage		Pointer to the glyph image data.
       
   165 @param	aGlyphImageSize	Glyph image size.
       
   166 @param	aClipRect		Clipping rect.
       
   167 */
       
   168 void CSwDirectGdiEngine::DrawBitmapGlyph(const TPoint& aPos, const TUint8* aGlyphImage,
       
   169 										 const TSize& aGlyphImageSize, const TRect& aClipRect)
       
   170 	{
       
   171 	// aChar parameter not needed because SW implementation uses the default glyph cache
       
   172 	// therefore does not need aChar to index its own local cache
       
   173 	
       
   174 	/*
       
   175 	Divert if the character is large.
       
   176 	Large is defined as wider than 30 bits (a scan line won't fit in a TInt32)
       
   177 	or greater than 32 bits high (because that's the current array size - could be changed).
       
   178 	*/
       
   179 	TInt dataHeight = aGlyphImageSize.iHeight;
       
   180 	TInt dataLength = aGlyphImageSize.iWidth;
       
   181 	if (dataLength > 30 || dataHeight > 32)
       
   182 		{
       
   183 		DrawLargeBitmapGlyph(aPos, aGlyphImage, aGlyphImageSize, aClipRect);
       
   184 		return;
       
   185 		}
       
   186 	
       
   187 	TInt bitIndex = 0;
       
   188 	TInt16 repeatCount = 0;
       
   189 	TUint32 binaryData[32];
       
   190 	TUint32* binaryDataPtr = binaryData;
       
   191 	TUint32* binaryDataPtrLimit;
       
   192 	for (TInt glyphLine = 0; glyphLine < dataHeight; glyphLine += repeatCount) // for lines in the glyph bitmap
       
   193 		{
       
   194 		repeatCount = Load16(aGlyphImage + (bitIndex >> 3));
       
   195 		repeatCount >>= bitIndex & 7;
       
   196 		TInt multiLineFlag = repeatCount & 1;
       
   197 		repeatCount >>= 1;
       
   198 		repeatCount &= 0xf;
       
   199 		bitIndex += 5;
       
   200 		binaryDataPtrLimit = binaryData + glyphLine + repeatCount;
       
   201 		if (multiLineFlag)
       
   202 			{
       
   203 			while (binaryDataPtr < binaryDataPtrLimit)
       
   204 				{
       
   205 				TInt glyphDataOffsetPtr = TInt(aGlyphImage) + (bitIndex >> 3);
       
   206 				TUint32* glyphDataWord = (TUint32*)(glyphDataOffsetPtr & ~3);
       
   207 				TInt bitShift = bitIndex & 7;
       
   208 				bitShift += (glyphDataOffsetPtr & 3) << 3;
       
   209 				*binaryDataPtr = (*glyphDataWord++) >> bitShift;
       
   210 				if (bitShift)
       
   211 					{
       
   212 					*binaryDataPtr |= (*glyphDataWord << (32 - bitShift));
       
   213 					}
       
   214 				bitIndex += dataLength;
       
   215 				binaryDataPtr++;
       
   216 				}
       
   217 			}
       
   218 		else
       
   219 			{
       
   220 			TInt glyphDataOffsetPtr = TInt(aGlyphImage) + (bitIndex >> 3);
       
   221 			TUint32* glyphDataWord = (TUint32*)(glyphDataOffsetPtr & ~3);
       
   222 			TInt bitShift = bitIndex & 7;
       
   223 			bitShift += (glyphDataOffsetPtr & 3) << 3;
       
   224 			TUint32 data = (*glyphDataWord++) >> bitShift;
       
   225 			if (bitShift)
       
   226 				{
       
   227 				data |= (*glyphDataWord << (32 - bitShift));
       
   228 				}
       
   229 			while (binaryDataPtr < binaryDataPtrLimit)
       
   230 				{
       
   231 				*binaryDataPtr++ = data;
       
   232 				}
       
   233 			bitIndex += dataLength;
       
   234 			}
       
   235 		}
       
   236 	TPoint topLeft(aPos);
       
   237 	binaryDataPtr = ClipBinaryArray(binaryData, binaryData + dataHeight, dataLength, dataHeight, topLeft, aClipRect);
       
   238 	if ((dataLength > 0) && (dataHeight > 0))
       
   239 		{
       
   240 		iDrawDevice->WriteBinary(topLeft.iX, topLeft.iY, binaryDataPtr, dataLength, dataHeight, iPenColor, GcDrawMode(iDrawMode) );
       
   241 		}
       
   242 	}
       
   243 	
       
   244 	
       
   245 /**
       
   246 Draw a large bitmap glyph.
       
   247 	
       
   248 @param	aPos			Position to start drawing gyph.
       
   249 @param	aGlyphImage		Pointer to the glyph image data.
       
   250 @param	aGlyphImageSize	Glyph image size.
       
   251 @param	aClipRect		Clipping rect.
       
   252 */
       
   253 void CSwDirectGdiEngine::DrawLargeBitmapGlyph(const TPoint& aPos, const TUint8* aGlyphImage,
       
   254 											 const TSize& aGlyphImageSize, const TRect& aClipRect)
       
   255 	{
       
   256 	TPoint printPos(aPos);
       
   257 	const TInt dataLength = aGlyphImageSize.iWidth;
       
   258 	const TInt dataHeight = aGlyphImageSize.iHeight;
       
   259 	TInt bitIndex = 0;
       
   260 	TInt16 repeatCount = 0;
       
   261 	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
       
   262 	const TInt scanLineWords = (iDrawDevice->ScanLineBytes()) << 3;
       
   263 	for (TInt glyphLine = 0; glyphLine < dataHeight; glyphLine += repeatCount) // for lines in the glyph bitmap
       
   264 		{
       
   265 		repeatCount = Load16(aGlyphImage + (bitIndex >> 3));
       
   266 		repeatCount >>= bitIndex & 7;
       
   267 		const TInt multiLineFlag = repeatCount & 1;
       
   268 		repeatCount >>= 1;
       
   269 		repeatCount &= 0xf;
       
   270 		bitIndex += 5;
       
   271 		if (multiLineFlag)
       
   272 			{
       
   273 			for (TInt currentLine = 0; currentLine < repeatCount; currentLine++)
       
   274 				{
       
   275 				CopyCharLine(scanLineBuffer, scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength);
       
   276 				OutputCharLineMultiplied(printPos, scanLineBuffer, dataLength, 1, aClipRect);
       
   277 				bitIndex += dataLength;
       
   278 				printPos.iY++;
       
   279 				}
       
   280 			}
       
   281 		else
       
   282 			{
       
   283 			CopyCharLine(scanLineBuffer, scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength);
       
   284 			OutputCharLineMultiplied(printPos, scanLineBuffer, dataLength, repeatCount, aClipRect);
       
   285 			printPos.iY += repeatCount;
       
   286 			bitIndex += dataLength;
       
   287 			}
       
   288 		}
       
   289 	}
       
   290 
       
   291 
       
   292 /**
       
   293 
       
   294 */
       
   295 void CSwDirectGdiEngine::CopyCharLine(TUint32* aBinaryDataPtr, TInt aBufferWords, const TUint8* aData, TInt aBitShift, TInt aCharWidth)
       
   296 	{
       
   297 	aBitShift &= 7;
       
   298 	TInt wordsToCopy = (aCharWidth + 31) >> 5;
       
   299 	if (wordsToCopy > aBufferWords)
       
   300 		{
       
   301 		wordsToCopy = aBufferWords;
       
   302 		}
       
   303 	TUint32* ptrLimit = aBinaryDataPtr + wordsToCopy;
       
   304 	TUint32* dataWord = (TUint32*)(TInt(aData) & ~3);
       
   305 	aBitShift += (TInt(aData) - TInt(dataWord)) << 3;
       
   306 	while (aBinaryDataPtr < ptrLimit)
       
   307 		{
       
   308 		*aBinaryDataPtr = *dataWord++;
       
   309 		*aBinaryDataPtr >>= aBitShift;
       
   310 		if (aBitShift)
       
   311 			{
       
   312 			*aBinaryDataPtr |= (*dataWord << (32 - aBitShift));
       
   313 			}
       
   314 		aBinaryDataPtr++;
       
   315 		}
       
   316 	}
       
   317 
       
   318 
       
   319 /**
       
   320 
       
   321 */
       
   322 void CSwDirectGdiEngine::OutputCharLineMultiplied(TPoint aPrintPos, TUint32* aBuffer, TInt aDataLength, TInt aNum, const TRect& aClipRect)
       
   323 	{
       
   324 	if (aDataLength <= 0)
       
   325 		{
       
   326 		return;
       
   327 		}
       
   328 	TInt bufferWords = (aDataLength + 31) >> 5;
       
   329 	TUint32* bufferLimit = aBuffer + bufferWords;
       
   330 	if (aPrintPos.iX < aClipRect.iTl.iX)
       
   331 		{
       
   332 		TInt pixelExcess = aClipRect.iTl.iX - aPrintPos.iX;
       
   333 		while (pixelExcess >= 32)
       
   334 			{
       
   335 			aBuffer++;
       
   336 			bufferWords--;
       
   337 			aDataLength -= 32;
       
   338 			pixelExcess -= 32;
       
   339 			}
       
   340 		if (aDataLength <= 0)
       
   341 			{
       
   342 			return;
       
   343 			}
       
   344 		if (pixelExcess > 0)
       
   345 			{
       
   346 			TInt shiftUp = 32 - pixelExcess;
       
   347 			TUint32* bufferPtr = aBuffer;
       
   348 			while (bufferPtr < bufferLimit)
       
   349 				{
       
   350 				*bufferPtr >>= pixelExcess;
       
   351 				if (bufferPtr < bufferLimit - 1)
       
   352 					{
       
   353 					*bufferPtr |= (*(bufferPtr + 1) << shiftUp);
       
   354 					}
       
   355 				bufferPtr++;
       
   356 				}
       
   357 			aDataLength -= pixelExcess;
       
   358 			if (aDataLength <= 0)
       
   359 				{
       
   360 				return;
       
   361 				}
       
   362 			}
       
   363 		aPrintPos.iX = aClipRect.iTl.iX;
       
   364 		}
       
   365 	if (aPrintPos.iX + aDataLength > aClipRect.iBr.iX)
       
   366 		{
       
   367 		TInt pixelExcess = aPrintPos.iX + aDataLength - aClipRect.iBr.iX;
       
   368 		aDataLength -= pixelExcess;
       
   369 		if (aDataLength <= 0)
       
   370 			{
       
   371 			return;
       
   372 			}
       
   373 		}
       
   374 	while (aNum > 0)
       
   375 		{
       
   376 		if ((aPrintPos.iY >= aClipRect.iTl.iY) && (aPrintPos.iY < aClipRect.iBr.iY))
       
   377 			{
       
   378 			iDrawDevice->WriteBinaryLine(aPrintPos.iX, aPrintPos.iY, aBuffer, aDataLength, iPenColor, GcDrawMode(iDrawMode));
       
   379 			}
       
   380 		aPrintPos.iY++;
       
   381 		aNum--;
       
   382 		}
       
   383 	}
       
   384 
       
   385 
       
   386 /**
       
   387 Draw a rotated bitmap glyph.
       
   388 	
       
   389 @param	aPos			Position to start drawing glyph after rotation has been applied.
       
   390 @param	aGlyphImage		Pointer to the glyph image data.
       
   391 @param	aGlyphImageSize	Glyph image size.
       
   392 @param	aClipRect		Clipping rect.
       
   393 @param	aRotation		Rotation specifying how the glyph will be drawn.
       
   394 */
       
   395 void CSwDirectGdiEngine::DrawRotatedBitmapGlyph(const TPoint& aPos, const TUint8* aGlyphImage,
       
   396 												const TSize& aGlyphImageSize, const TRect& aClipRect, const DirectGdi::TGraphicsRotation aRotation)
       
   397 	{
       
   398 	TPoint printPos(aPos);
       
   399 	TInt dataLength = aGlyphImageSize.iWidth;
       
   400 	TInt dataHeight = aGlyphImageSize.iHeight;
       
   401 	TInt bitIndex = 0;
       
   402 	TInt16 repeatCount = 0;
       
   403 	TInt direction = (aRotation == DirectGdi::EGraphicsRotation270) ? 1 : -1;
       
   404 	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
       
   405 	TInt scanLineWords = (iDrawDevice->ScanLineBytes()) << 3;
       
   406 	for (TInt glyphLine = 0; glyphLine < dataHeight; glyphLine += repeatCount) // for lines in the glyph bitmap...
       
   407 		{
       
   408 		repeatCount = Load16(aGlyphImage + (bitIndex >> 3));
       
   409 		repeatCount >>= bitIndex & 7;
       
   410 		TInt multiLineFlag = repeatCount & 1;
       
   411 		repeatCount >>= 1;
       
   412 		repeatCount &= 0xf;
       
   413 		bitIndex += 5;
       
   414 		TInt signedRepeatCount = repeatCount * direction;
       
   415 		if (multiLineFlag)
       
   416 			{
       
   417 			for (TInt currentLine = 0; currentLine < repeatCount; currentLine++)
       
   418 				{
       
   419 				CopyCharLine(scanLineBuffer, scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength);
       
   420 				OutputCharLineVertical(printPos, scanLineBuffer, dataLength, 1, direction, aClipRect);
       
   421 				bitIndex += dataLength;
       
   422 				printPos.iX += direction;
       
   423 				}
       
   424 			}
       
   425 		else
       
   426 			{
       
   427 			CopyCharLine(scanLineBuffer,scanLineWords, aGlyphImage + (bitIndex >> 3), bitIndex & 7, dataLength);
       
   428 			OutputCharLineVertical(printPos, scanLineBuffer, dataLength, repeatCount, direction, aClipRect);
       
   429 			printPos.iX += signedRepeatCount;
       
   430 			bitIndex += dataLength;
       
   431 			}
       
   432 		}
       
   433 	}
       
   434 
       
   435 
       
   436 /**
       
   437 
       
   438 */
       
   439 void CSwDirectGdiEngine::OutputCharLineVertical(TPoint aPrintPos, TUint32* aBuffer, TInt aDataLength,
       
   440 												TInt aNum, TInt aDirection, const TRect& aClipRect)
       
   441 	{
       
   442 //	const DirectGdi::TGraphicsRotation rotation = aUp ? DirectGdi::EGraphicsRotation270 : DirectGdi::EGraphicsRotation90;
       
   443 //	TInt direction = (aRotation == DirectGdi::EGraphicsRotation270) ? 1 : -1;
       
   444 	if (aDataLength <= 0)
       
   445 		{
       
   446 		return;
       
   447 		}
       
   448 	TInt bufferWords = (aDataLength + 31) >> 5;
       
   449 	TUint32* bufferLimit = aBuffer + bufferWords;
       
   450 	if (aDirection == 1)
       
   451 		{
       
   452 		if (aPrintPos.iY >= aClipRect.iBr.iY)
       
   453 			{
       
   454 			TInt pixelExcess = aPrintPos.iY - aClipRect.iBr.iY + 1;
       
   455 			while (pixelExcess >= 32)
       
   456 				{
       
   457 				aBuffer++;
       
   458 				aDataLength -= 32;
       
   459 				pixelExcess -= 32;
       
   460 				}
       
   461 			if (aDataLength <= 0)
       
   462 				{
       
   463 				return;
       
   464 				}
       
   465 			if (pixelExcess > 0)
       
   466 				{
       
   467 				TInt shiftUp = 32 - pixelExcess;
       
   468 				TUint32* bufferPtr = aBuffer;
       
   469 				while (bufferPtr < bufferLimit)
       
   470 					{
       
   471 					*bufferPtr >>= pixelExcess;
       
   472 					if (bufferPtr < bufferLimit - 1)
       
   473 						*bufferPtr |= (*(bufferPtr + 1) << shiftUp);
       
   474 					bufferPtr++;
       
   475 					}
       
   476 				aDataLength -= pixelExcess;
       
   477 				if (aDataLength <= 0)
       
   478 					{
       
   479 					return;
       
   480 					}
       
   481 				}
       
   482 			aPrintPos.iY = aClipRect.iBr.iY - 1;
       
   483 			}
       
   484 		if ((aPrintPos.iY - aDataLength) < (aClipRect.iTl.iY - 1))
       
   485 			{
       
   486 			TInt pixelExcess = aClipRect.iTl.iY - 1 - aPrintPos.iY + aDataLength;
       
   487 			aDataLength -= pixelExcess;
       
   488 			if (aDataLength <= 0)
       
   489 				{
       
   490 				return;
       
   491 				}
       
   492 			}
       
   493 		}
       
   494 	else
       
   495 		{
       
   496 		if (aPrintPos.iY < aClipRect.iTl.iY)
       
   497 			{
       
   498 			TInt pixelExcess = aClipRect.iTl.iY - aPrintPos.iY;
       
   499 			while (pixelExcess >= 32)
       
   500 				{
       
   501 				aBuffer++;
       
   502 				aDataLength -= 32;
       
   503 				pixelExcess -= 32;
       
   504 				}
       
   505 			if (aDataLength <= 0)
       
   506 				{
       
   507 				return;
       
   508 				}
       
   509 			if (pixelExcess > 0)
       
   510 				{
       
   511 				TInt shiftup = 32 - pixelExcess;
       
   512 				TUint32* bufferptr = aBuffer;
       
   513 				while (bufferptr < bufferLimit)
       
   514 					{
       
   515 					*bufferptr >>= pixelExcess;
       
   516 					if (bufferptr < bufferLimit - 1)
       
   517 						*bufferptr |= (*(bufferptr + 1) << shiftup);
       
   518 					bufferptr++;
       
   519 					}
       
   520 				aDataLength -= pixelExcess;
       
   521 				if (aDataLength <= 0)
       
   522 					{
       
   523 					return;
       
   524 					}
       
   525 				}
       
   526 			aPrintPos.iY = aClipRect.iTl.iY;
       
   527 			}
       
   528 		if (aPrintPos.iY + aDataLength > aClipRect.iBr.iY)
       
   529 			{
       
   530 			TInt pixelExcess = aPrintPos.iY + aDataLength - aClipRect.iBr.iY;
       
   531 			aDataLength -= pixelExcess;
       
   532 			if (aDataLength <= 0)
       
   533 				{
       
   534 				return;
       
   535 				}
       
   536 			}
       
   537 		}
       
   538 	CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
       
   539 	while (aNum > 0)
       
   540 		{
       
   541 		if ((aPrintPos.iX >= aClipRect.iTl.iX) && (aPrintPos.iX < aClipRect.iBr.iX))
       
   542 			iDrawDevice->WriteBinaryLineVertical(aPrintPos.iX, aPrintPos.iY, aBuffer, aDataLength, iPenColor, drawMode, (aDirection == 1));
       
   543 		aPrintPos.iX += aDirection;
       
   544 		aNum--;
       
   545 		}
       
   546 	}
       
   547 
       
   548 
       
   549 /**
       
   550 Draw an antialiased glyph.
       
   551 	
       
   552 @param	aPos			Position to start drawing gyph.
       
   553 @param	aGlyphImage		Pointer to the glyph image data.
       
   554 @param	aGlyphImageSize	Glyph image size.
       
   555 @param	aClipRect		Clipping rect.
       
   556 */
       
   557 void CSwDirectGdiEngine::DrawAntiAliasedGlyph(const TPoint& aPos, const TUint8* aGlyphImage,
       
   558 											  const TSize& aGlyphImageSize, const TRect& aClipRect)
       
   559 	{
       
   560 	const TInt topRow = Max(0, aClipRect.iTl.iY - aPos.iY);
       
   561 	const TInt bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iY - aPos.iY);
       
   562 	const TInt leftCol = Max(0, aClipRect.iTl.iX - aPos.iX);
       
   563 	const TInt rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iX - aPos.iX);
       
   564 	const TUint8* p = aGlyphImage + (topRow * aGlyphImageSize.iWidth) + leftCol;
       
   565 	const TInt x = aPos.iX + leftCol;
       
   566 	TInt y = aPos.iY + topRow;
       
   567 	const TInt cols = rightCol - leftCol;
       
   568 
       
   569 	for (TInt row = topRow; row < bottomRow; row++, p += aGlyphImageSize.iWidth, y++)
       
   570 		{
       
   571 		iDrawDevice->WriteRgbAlphaMulti(x, y, cols, iPenColor, p);
       
   572 		}
       
   573 	}
       
   574 
       
   575 
       
   576 /**
       
   577 Draw a rotated antialiased glyph.
       
   578 	
       
   579 @param	aPos			Position to start drawing gyph after rotation has been applied.
       
   580 @param	aGlyphImage		Pointer to the glyph image data.
       
   581 @param	aGlyphImageSize	Glyph image size.
       
   582 @param	aClipRect		Clipping rect.
       
   583 @param	aRotation		Rotation specifying how the glyph will be drawn.
       
   584 */
       
   585 void CSwDirectGdiEngine::DrawRotatedAntiAliasedGlyph(const TPoint& aPos, const TUint8* aGlyphImage,
       
   586 													 const TSize& aGlyphImageSize, const TRect& aClipRect, const DirectGdi::TGraphicsRotation aRotation)
       
   587 	{
       
   588 	const int KBufferSize = 32;
       
   589 	TUint8 maskBuffer[KBufferSize];
       
   590 	int topRow = 0;
       
   591 	int bottomRow = 0;
       
   592 	int leftCol = 0;
       
   593 	int rightCol = 0;
       
   594 	const TUint32 penColor = iPenColor.Internal();
       
   595 	const TUint32 brushColor = iBrushColor.Internal();
       
   596 	
       
   597 	if (aRotation == DirectGdi::EGraphicsRotation270)
       
   598 		{
       
   599 		topRow = Max(0, aClipRect.iTl.iX - aPos.iX);
       
   600 		bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iX - aPos.iX);
       
   601 		leftCol = Max(0, aPos.iY - aClipRect.iBr.iY + 1);
       
   602 		rightCol = Min(aGlyphImageSize.iWidth, aPos.iY - aClipRect.iTl.iY + 1);
       
   603 		TInt y = aPos.iY - (rightCol - 1);
       
   604 		for (TInt col = rightCol - 1; col >= leftCol; col--, y++)
       
   605 			{
       
   606 			TInt x = aPos.iX + topRow;
       
   607 			for (TInt row = topRow; row < bottomRow; row += KBufferSize, x += KBufferSize)
       
   608 				{
       
   609 				TInt length = KBufferSize;
       
   610 				if (length > bottomRow - row)
       
   611 					{
       
   612 					length = bottomRow - row;
       
   613 					}
       
   614 				const TUint8* p = aGlyphImage + row * aGlyphImageSize.iWidth + col;
       
   615 				for (TInt i = 0; i < length; i++, p += aGlyphImageSize.iWidth)
       
   616 					{
       
   617 					maskBuffer[i] = *p;
       
   618 					}
       
   619 				iDrawDevice->WriteRgbAlphaMulti(x, y, length, iPenColor, maskBuffer);
       
   620 				}
       
   621 			}
       
   622 		}
       
   623 	else
       
   624 		{
       
   625 		topRow = Max(0, aPos.iX - aClipRect.iBr.iX + 1);
       
   626 		bottomRow = Min(aGlyphImageSize.iHeight, aPos.iX - aClipRect.iTl.iX + 1);
       
   627 		leftCol = Max(0, aClipRect.iTl.iY - aPos.iY);
       
   628 		rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iY - aPos.iY);
       
   629 		int y = aPos.iY + leftCol;
       
   630 		for (TInt col = leftCol; col < rightCol; col++, y++)
       
   631 			{
       
   632 			TInt x = aPos.iX - (bottomRow - 1);
       
   633 			for (TInt row = bottomRow; row > topRow; row -= KBufferSize, x += KBufferSize)
       
   634 				{
       
   635 				int length = KBufferSize;
       
   636 				if (length > row - topRow)
       
   637 					length = row - topRow;
       
   638 				const TUint8* p = aGlyphImage + (row - 1) * aGlyphImageSize.iWidth + col;
       
   639 				for (TInt i = 0; i < length; i++, p -= aGlyphImageSize.iWidth)
       
   640 					{
       
   641 					maskBuffer[i] = *p;
       
   642 					}
       
   643 				iDrawDevice->WriteRgbAlphaMulti(x, y, length, iPenColor, maskBuffer);
       
   644 				}
       
   645 			}
       
   646 		}
       
   647 	}
       
   648 
       
   649 
       
   650 /**
       
   651 Draw a four colour glyph.
       
   652 	
       
   653 @param	aPos			Position to start drawing gyph.
       
   654 @param	aGlyphImage		Pointer to the glyph image data.
       
   655 @param	aGlyphImageSize	Glyph image size.
       
   656 @param	aClipRect		Clipping rect.
       
   657 */
       
   658 void CSwDirectGdiEngine::DrawFourColourGlyph(const TPoint& aPos, const TUint8* aGlyphImage,
       
   659 											 const TSize& aGlyphImageSize, const TRect& aClipRect)
       
   660 	{
       
   661 	const TInt topRow = Max(0, aClipRect.iTl.iY - aPos.iY);
       
   662 	const TInt bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iY - aPos.iY);
       
   663 	const TInt leftCol = Max(0, aClipRect.iTl.iX - aPos.iX);
       
   664 	const TInt rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iX - aPos.iX);
       
   665 	const TUint8* p = aGlyphImage + (topRow * aGlyphImageSize.iWidth) + leftCol;
       
   666 	const TInt x = aPos.iX + leftCol;
       
   667 	TInt y = aPos.iY + topRow;
       
   668 	const TInt cols = rightCol - leftCol;
       
   669 	const TUint32 penColor = iPenColor.Internal();
       
   670 	const TUint32 shadowColor = iTextShadowColor.Internal();
       
   671 	const TUint32 brushColor = iBrushColor.Internal();
       
   672 
       
   673 	MOutlineAndShadowBlend* outlineAndShadow = NULL;
       
   674 	const TInt err = iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
       
   675 	if (err == KErrNone) 
       
   676 		{
       
   677 		//There is a support for the interface with KOutlineAndShadowInterface id.
       
   678 		for (TInt row = topRow; row < bottomRow; row++, p += aGlyphImageSize.iWidth, y++)
       
   679 			{
       
   680 			outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p);
       
   681 			}
       
   682 		}
       
   683 	else
       
   684 		{
       
   685 		// Assert if MOutlineAndShadowBlend interface is not implemented
       
   686 		GRAPHICS_ASSERT_DEBUG(outlineAndShadow, EDirectGdiPanicInvalidInterfaceHandle);
       
   687 		}
       
   688 	}
       
   689 
       
   690 
       
   691 /**
       
   692 Draw a rotated four colour glyph.
       
   693 	
       
   694 @param	aPos			Position to start drawing gyph after rotation has been applied.
       
   695 @param	aGlyphImage		Pointer to the glyph image data.
       
   696 @param	aGlyphImageSize	Glyph image size.
       
   697 @param	aClipRect		Clipping rect.
       
   698 @param	aRotation		Rotation specifying how the glyph will be drawn.
       
   699 */
       
   700 void CSwDirectGdiEngine::DrawRotatedFourColourGlyph(const TPoint& aPos, const TUint8* aGlyphImage, const TSize& aGlyphImageSize,
       
   701 													const TRect& aClipRect, const DirectGdi::TGraphicsRotation aRotation)
       
   702 	{
       
   703 	const int KBufferSize = 32;
       
   704 	TUint8 maskBuffer[KBufferSize];
       
   705 	int topRow = 0;
       
   706 	int bottomRow = 0;
       
   707 	int leftCol = 0;
       
   708 	int rightCol = 0;
       
   709 	const TUint32 penColor = iPenColor.Internal();
       
   710 	const TUint32 shadowColor = iTextShadowColor.Internal();
       
   711 	const TUint32 brushColor = iBrushColor.Internal();
       
   712 	
       
   713 	MOutlineAndShadowBlend* outlineAndShadow = NULL;
       
   714 	TInt err = iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
       
   715 	if(err != KErrNone)
       
   716 		{
       
   717 		// Assert if MOutlineAndShadowBlend interface is not implemented
       
   718 		GRAPHICS_ASSERT_DEBUG(outlineAndShadow, EDirectGdiPanicInvalidInterfaceHandle);
       
   719 		}
       
   720 	
       
   721 	if (aRotation == DirectGdi::EGraphicsRotation270)
       
   722 		{
       
   723 		topRow = Max(0, aClipRect.iTl.iX - aPos.iX);
       
   724 		bottomRow = Min(aGlyphImageSize.iHeight, aClipRect.iBr.iX - aPos.iX);
       
   725 		leftCol = Max(0, aPos.iY - aClipRect.iBr.iY + 1);
       
   726 		rightCol = Min(aGlyphImageSize.iWidth, aPos.iY - aClipRect.iTl.iY + 1);
       
   727 		TInt y = aPos.iY - (rightCol - 1);
       
   728 		for (TInt col = rightCol - 1; col >= leftCol; col--, y++)
       
   729 			{
       
   730 			TInt x = aPos.iX + topRow;
       
   731 			for (TInt row = topRow; row < bottomRow; row += KBufferSize, x += KBufferSize)
       
   732 				{
       
   733 				TInt length = KBufferSize;
       
   734 				if (length > bottomRow - row)
       
   735 					{
       
   736 					length = bottomRow - row;
       
   737 					}
       
   738 				const TUint8* p = aGlyphImage + row * aGlyphImageSize.iWidth + col;
       
   739 				for (TInt i = 0; i < length; i++, p += aGlyphImageSize.iWidth)
       
   740 					{
       
   741 					maskBuffer[i] = *p;
       
   742 					}
       
   743 				//There is a support for the interface with KOutlineAndShadowInterface id.
       
   744 				outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, maskBuffer);
       
   745 				}
       
   746 			}
       
   747 		}
       
   748 	else
       
   749 		{
       
   750 		topRow = Max(0, aPos.iX - aClipRect.iBr.iX + 1);
       
   751 		bottomRow = Min(aGlyphImageSize.iHeight, aPos.iX - aClipRect.iTl.iX + 1);
       
   752 		leftCol = Max(0, aClipRect.iTl.iY - aPos.iY);
       
   753 		rightCol = Min(aGlyphImageSize.iWidth, aClipRect.iBr.iY - aPos.iY);
       
   754 		int y = aPos.iY + leftCol;
       
   755 		for (TInt col = leftCol; col < rightCol; col++, y++)
       
   756 			{
       
   757 			TInt x = aPos.iX - (bottomRow - 1);
       
   758 			for (TInt row = bottomRow; row > topRow; row -= KBufferSize, x += KBufferSize)
       
   759 				{
       
   760 				int length = KBufferSize;
       
   761 				if (length > row - topRow)
       
   762 					length = row - topRow;
       
   763 				const TUint8* p = aGlyphImage + (row - 1) * aGlyphImageSize.iWidth + col;
       
   764 				for (TInt i = 0; i < length; i++, p -= aGlyphImageSize.iWidth)
       
   765 					{
       
   766 					maskBuffer[i] = *p;
       
   767 					}
       
   768 				//There is a support for the interface with KOutlineAndShadowInterface id.
       
   769 				outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, maskBuffer);
       
   770 				}
       
   771 			}
       
   772 		}
       
   773 	}
       
   774 
       
   775 
       
   776 /**
       
   777 Helper function to clip the array to the clip rect.
       
   778 
       
   779 @param	aArray		Start of array of data to be clipped.
       
   780 @param	aArrayLimit	End of array of data to be clipped.
       
   781 @param	aDataWd 	Length of data.
       
   782 @param	aDataHt		Height of data.
       
   783 @param	aPos		Position to start drawing from.
       
   784 @param	aClipRect	Rectangle to clip data array to.
       
   785 
       
   786 @return Pointer to array of clipped data.
       
   787 */
       
   788 TUint32* CSwDirectGdiEngine::ClipBinaryArray(TUint32* aArray, TUint32* aArrayLimit, TInt& aDataWd, TInt& aDataHt, TPoint& aPos, const TRect& aClipRect)
       
   789 	{
       
   790 	TUint32* arrayPtr = aArray;
       
   791 	TInt clipDiff = aClipRect.iTl.iX - aPos.iX;
       
   792 	if (clipDiff > 0)
       
   793 		{
       
   794 		while (arrayPtr < aArrayLimit)
       
   795 			{
       
   796 			*arrayPtr++ >>= clipDiff;
       
   797 			}
       
   798 		aDataWd -= clipDiff;
       
   799 		aPos.iX = aClipRect.iTl.iX;
       
   800 		arrayPtr = aArray;
       
   801 		}
       
   802 	if ((aPos.iX + aDataWd > aClipRect.iBr.iX) && (aDataWd > 0))
       
   803 		{
       
   804 		aDataWd = aClipRect.iBr.iX - aPos.iX;
       
   805 		}
       
   806 	clipDiff = aClipRect.iTl.iY - aPos.iY;
       
   807 	if (clipDiff > 0)
       
   808 		{
       
   809 		aDataHt -= clipDiff;
       
   810 		arrayPtr += clipDiff;
       
   811 		aPos.iY = aClipRect.iTl.iY;
       
   812 		}
       
   813 	if (((aPos.iY + aDataHt) > (aClipRect.iBr.iY)) && (aDataHt > 0))
       
   814 		{
       
   815 		aDataHt = aClipRect.iBr.iY - aPos.iY;
       
   816 		}
       
   817 	return arrayPtr;
       
   818 	}