graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1997-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 <fntstore.h>
       
    17 #include <bitdraw.h>
       
    18 #include <bitstd.h>
       
    19 #include <bitdev.h>
       
    20 #include "BITPANIC.H"
       
    21 #include <shapeinfo.h>
       
    22 #include <bmalphablend.h>
       
    23 #include <bitdrawinterfaceid.h>
       
    24 #include <graphics/fbsrasterizer.h>
       
    25 #include "bitgcextradata.h"
       
    26 #include <graphics/gdi/gdiconsts.h>
       
    27 #include <graphics/gdi/gdistructs.h>
       
    28 
       
    29 
       
    30 /** Draws text at the last print position.
       
    31 
       
    32 @param aText The text string to be drawn. */
       
    33 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText)
       
    34 	{
       
    35 	TTextParameters* param = NULL;
       
    36 	DrawText(aText,param,iLastPrintPosition,ELeft,CFont::EHorizontal);
       
    37 	}
       
    38 
       
    39 /** Draws text at the specified position and updates the print position.
       
    40 
       
    41 @param  aText The text string to be drawn
       
    42 @param aCoords Coordinates to draw the text at. */
       
    43 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TPoint& aCoords)
       
    44 	{
       
    45 	TTextParameters* param = NULL;
       
    46 	DrawText(aText,param,aCoords,ELeft,CFont::EHorizontal);
       
    47 	}
       
    48 
       
    49 
       
    50 /** Draws text clipped to the specified rectangle.
       
    51 
       
    52 @param aText The text string to be drawn 
       
    53 @param aBox The clipping rectangle. */
       
    54 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox)
       
    55 	{
       
    56 	TTextParameters* param = NULL;
       
    57 	DrawText(aText,param,aBox);
       
    58 	}
       
    59 
       
    60 
       
    61 /** Draws text clipped to the specified rectangle using a baseline offset,
       
    62 horizontal alignment and a margin.
       
    63 
       
    64 @param  aText The text string to be drawn
       
    65 @param aBox The clipping rectangle.
       
    66 @param  aBLOff An offset in pixels for the baseline from the normal position
       
    67         (bottom of the rectangle minus the descent of the font).
       
    68 @param  aHrz Horizontal alignment option relative to the specified rectangle.
       
    69 @param aMargin Offset to add to the position as calculated using specified 
       
    70 		rectangle. */	
       
    71 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,TInt aBLOff,
       
    72 								  TTextAlign aHrz,TInt aMargin)
       
    73     {
       
    74     TTextParameters* param = NULL;
       
    75 	DrawText(aText,param,aBox,aBLOff,-1,aHrz,aMargin);
       
    76 	}
       
    77 
       
    78 /** Draws text clipped to the specified rectangle.
       
    79 
       
    80 @param  aText The text string to be drawn
       
    81 @param aBox The clipping rectangle. */	
       
    82 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,
       
    83 								  TInt aBLOff,TInt /*aTextWidth*/,
       
    84 								  TTextAlign aHrz,TInt aMargin)
       
    85     {
       
    86 // aTextWidth is not used here - try to abolish this - I think it is unneeded
       
    87 	TPoint p(aBox.iTl);
       
    88 	p.iY += aBLOff;
       
    89 	switch (aHrz)
       
    90 		{
       
    91 		case ELeft: p.iX += aMargin; break;
       
    92 		case ERight: p.iX = aBox.iBr.iX - aMargin; break;
       
    93 		case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
       
    94 		}
       
    95 	TTextParameters* param = NULL;
       
    96 	DrawText(aText,param,p,aHrz,CFont::EHorizontal,&aBox);
       
    97 	}
       
    98 
       
    99 
       
   100 /** The general DrawText routine that implements all the others.
       
   101 
       
   102 @param aText the text to be drawn
       
   103 @param aPosition the origin of the text
       
   104 @param aAlignment left, centred or right, around aPosition; not used if drawing vertically
       
   105 @param aDirection direction: left to right, right to left, or top to bottom
       
   106 @param aBox if non-null, filled before the text is drawn
       
   107 @param aTextBounds if non-null returns the bounding box of the text
       
   108 */ 
       
   109 void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TTextAlign aAlignment,
       
   110 						 CFont::TTextDirection aDirection,const TRect* aBox)
       
   111    {
       
   112 	// sanity checks
       
   113 	BG_ASSERT_ALWAYS(iDevice,EBitgdiPanicNoDevicePresent);
       
   114 	BG_ASSERT_ALWAYS(iFont.Handle() != 0,EBitgdiPanicNoFontSelected);
       
   115 	const CBitmapFont* bitmap_font = iFont.Address();
       
   116 	BG_ASSERT_ALWAYS(bitmap_font != 0,EBitgdiPanicNoFontSelected);
       
   117 
       
   118 	// anything to do?
       
   119 	if (!aBox && !aText.Length())
       
   120 		return;
       
   121 
       
   122 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   123 
       
   124 	TRect deviceRect;
       
   125 	drawDevice->GetDrawRect(deviceRect);
       
   126 
       
   127 	// measure the text
       
   128 	CFont::TMeasureTextInput measure_text_input;
       
   129 	measure_text_input.iCharJustNum = iCharJustNum;
       
   130 	measure_text_input.iCharJustExcess = iCharJustExcess;
       
   131 	measure_text_input.iWordJustNum = iWordJustNum;
       
   132 	measure_text_input.iWordJustExcess = iWordJustExcess;
       
   133 	measure_text_input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder;
       
   134 	if (aParam)
       
   135 		{
       
   136 		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
       
   137 		measure_text_input.iStartInputChar = aParam->iStart;
       
   138 		measure_text_input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
       
   139 		}
       
   140 	CFont::TMeasureTextOutput measure_text_output;
       
   141 	const int advance = iFont.MeasureText(aText,&measure_text_input,&measure_text_output);
       
   142 	TRect text_bounds = measure_text_output.iBounds;
       
   143 	TInt underlineStrikeoutOffset;
       
   144 	
       
   145 	//this call is only needed in the case of linked fonts
       
   146 	//should this pass by one structure?
       
   147 	underlineStrikeoutOffset= BaselineCorrection();
       
   148 	
       
   149 	if (iUnderline == EUnderlineOn)
       
   150 		{
       
   151 		TInt underline_top = 0, underline_bottom = 0;
       
   152 		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
       
   153 		underline_top+=underlineStrikeoutOffset;
       
   154 		underline_bottom+=underlineStrikeoutOffset;
       
   155 		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
       
   156 		text_bounds.iTl.iY = Min(text_bounds.iTl.iY,underline_top);
       
   157 		text_bounds.iBr.iY = Max(text_bounds.iBr.iY,underline_bottom);
       
   158 		}
       
   159 	if (iStrikethrough == EStrikethroughOn)
       
   160 		{
       
   161 		TInt strike_top = 0,strike_bottom = 0;
       
   162 		GetStrikethroughMetrics(strike_top,strike_bottom);
       
   163 		strike_top+=underlineStrikeoutOffset;
       
   164 		strike_bottom+=underlineStrikeoutOffset;
       
   165 		text_bounds.iTl.iY = Min(text_bounds.iTl.iY,strike_top);
       
   166 		text_bounds.iBr.iY = Max(text_bounds.iBr.iY,strike_bottom);
       
   167 		}
       
   168 	if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
       
   169 		{
       
   170 		if (aDirection == CFont::EHorizontal)
       
   171 			{
       
   172 			text_bounds.iTl.iX = Min(text_bounds.iTl.iX, 0);
       
   173 			text_bounds.iBr.iX = Max(text_bounds.iBr.iX, advance);
       
   174 			}
       
   175 		else
       
   176 			{
       
   177 			text_bounds.iTl.iY = Min(text_bounds.iTl.iY, 0);
       
   178 			text_bounds.iBr.iY = Max(text_bounds.iBr.iY, advance);
       
   179 			}
       
   180 		}
       
   181 
       
   182 	// work out the text origin and new drawing position
       
   183  	TPoint text_origin = aPosition;
       
   184  	if (aDirection != CFont::EVertical)
       
   185  		{
       
   186  		const TInt leftSideBearing = Min(text_bounds.iTl.iX, 0);
       
   187  		const TInt rightSideBearing = Max(text_bounds.iBr.iX, advance);
       
   188  		switch (aAlignment)
       
   189  			{
       
   190 			// We are forbidding side-bearings to leak over the sides here,
       
   191 			// but still keeping the start and end pen positions within bounds.
       
   192 			case ELeft:
       
   193 				text_origin.iX -= leftSideBearing;
       
   194 				break;
       
   195 			case ERight:
       
   196 				text_origin.iX -= rightSideBearing;
       
   197 				break;
       
   198 			case ECenter:
       
   199 				// Centre is the average of left and right
       
   200 				text_origin.iX -= (leftSideBearing + rightSideBearing) >> 1;
       
   201 				break;
       
   202 			default:
       
   203 				break;
       
   204  			}
       
   205 		}
       
   206 	iLastPrintPosition = text_origin;
       
   207 	if (aDirection == CFont::EHorizontal)
       
   208 		iLastPrintPosition.iX += advance;
       
   209 	else
       
   210 		iLastPrintPosition.iY += advance;
       
   211 	text_origin.iY += bitmap_font->iAlgStyle.iBaselineOffsetInPixels;
       
   212 	text_bounds.Move(text_origin);
       
   213 	text_origin += iOrigin;
       
   214 
       
   215 	// determine clipping rectangle
       
   216 	TRect clip_rect = aBox ? *aBox : text_bounds;
       
   217 	AddRect(clip_rect);
       
   218 	clip_rect.Move(iOrigin);
       
   219 
       
   220 	if (UserClipRect(clip_rect))
       
   221 		{
       
   222 		if (iAutoUpdateJustification)
       
   223 			UpdateJustification(aText,aParam);
       
   224 		return; // nothing to do
       
   225 		}
       
   226 
       
   227 	SetupDevice();
       
   228 	iDevice->DrawingBegin(&iBrushBitmap);
       
   229 	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
       
   230 
       
   231 	// fill the box if necessary
       
   232 	if (aBox)
       
   233 		{
       
   234 		TRect fill_box = *aBox;
       
   235 		fill_box.Move(iOrigin);
       
   236 		RectFill(fill_box);
       
   237 		}
       
   238 
       
   239 	// decide which drawing routine to call
       
   240 	const TBool bold = bitmap_font->iAlgStyle.IsBold();
       
   241 	const TBool italic = bitmap_font->iAlgStyle.IsItalic();
       
   242 	const TBool multiw = bitmap_font->iAlgStyle.WidthFactor() > 1;
       
   243 	const TBool multih = bitmap_font->iAlgStyle.HeightFactor() > 1;
       
   244 
       
   245 	TOpenFontMetrics metrics;
       
   246 	iFont.GetFontMetrics(metrics);
       
   247 	const TInt maxwidth = metrics.MaxWidth();
       
   248 	// extext will be TRUE, if font is bold/italic/underline/strikethrough/anti-aliased or it 
       
   249 	// has shadow/outline effects ON. Depending on these properties it will call the proper draw routine.
       
   250 	TBool extext = FALSE;
       
   251 	TBool normaltext = FALSE;
       
   252 	const TBool anti_aliased = (bitmap_font->GlyphBitmapType() == EAntiAliasedGlyphBitmap);
       
   253 	const TBool outlineAndShadow = (bitmap_font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
       
   254 	if (anti_aliased || outlineAndShadow)
       
   255 		{
       
   256 		if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
       
   257 			{
       
   258 			//For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used 
       
   259 			//when drawing outline and shadow fonts.
       
   260 			BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
       
   261 			}
       
   262 		extext = TRUE;
       
   263 		}
       
   264 	else if (maxwidth > 30 || text_bounds.Height() > 32 || multiw || multih)
       
   265 		{
       
   266 		}
       
   267 	else if (iUnderline == EUnderlineOn || bold || italic || iStrikethrough == EStrikethroughOn || 
       
   268 			 iCharJustNum > 0 || iWordJustNum > 0)
       
   269 		extext = TRUE;
       
   270 	else
       
   271 		normaltext = TRUE;
       
   272 
       
   273 	const TInt charjustexcess = iCharJustExcess;
       
   274 	const TInt charjustnum = iCharJustNum;
       
   275 	const TInt wordjustexcess = iWordJustExcess;
       
   276 	const TInt wordjustnum = iWordJustNum;
       
   277 
       
   278 	// draw the text to all clip rectangles in turn
       
   279 	int clip_rects = iDefaultRegionPtr->Count();
       
   280 	for (int i = 0; i < clip_rects; i++)
       
   281 		{
       
   282 		iClipRect = (*iDefaultRegionPtr)[i];
       
   283 		if (!iClipRect.Intersects(clip_rect))
       
   284 			continue;
       
   285 
       
   286 #ifdef _DEBUG
       
   287 		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
       
   288 		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
       
   289 		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
       
   290 		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
       
   291 #endif
       
   292 
       
   293 		iClipRect.Intersection(clip_rect);
       
   294 
       
   295 		// Set up the parameter block for character positioning.
       
   296 		CFont::TPositionParam param;
       
   297 		param.iDirection = static_cast<TInt16>(aDirection);
       
   298 		param.iText.Set(aText);
       
   299 		TInt endDraw = aText.Length();
       
   300 		if (aParam)
       
   301 			{
       
   302 			param.iPosInText = aParam->iStart;
       
   303 			endDraw = Min(aText.Length(),aParam->iEnd);
       
   304 			}
       
   305 		else
       
   306 			param.iPosInText = 0;
       
   307 		param.iPen = text_origin;
       
   308 
       
   309 		// Draw the text.
       
   310 		if (normaltext)
       
   311 			DoDrawText(param,endDraw);
       
   312 		else if (extext)
       
   313 			DoDrawTextEx(param,bitmap_font,endDraw,underlineStrikeoutOffset);
       
   314 		else
       
   315 			DoDrawTextLarge(param,bitmap_font,endDraw);
       
   316 		
       
   317 		/*
       
   318 		Reset the justification parameters to their original values.
       
   319 		These will be updated as required later in code.
       
   320 		*/
       
   321 		iCharJustExcess = charjustexcess;
       
   322 		iCharJustNum = charjustnum;
       
   323 		iWordJustExcess = wordjustexcess;
       
   324 		iWordJustNum = wordjustnum;
       
   325 
       
   326 		drawDevice->UpdateRegion(iClipRect);
       
   327 		}
       
   328 
       
   329 	if (brushRasterizer)
       
   330 		{
       
   331 		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   332 		}
       
   333 	iDevice->DrawingEnd(&iBrushBitmap);
       
   334 	if (iAutoUpdateJustification)
       
   335 		UpdateJustification(aText,aParam);
       
   336 	}
       
   337 
       
   338 void CFbsBitGc::DoDrawText(CFont::TPositionParam& aParam, const TInt aEnd)
       
   339 	{
       
   340 	//const int n = aParam.iText.Length();
       
   341 	RShapeInfo shapeInfo;
       
   342 	while (aParam.iPosInText < /*n*/aEnd)
       
   343 		{
       
   344 		if (iFont.GetCharacterPosition2(aParam, shapeInfo))
       
   345 			{
       
   346 			const CFont::TPositionParam::TOutput* output = aParam.iOutput;
       
   347 			for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
       
   348 				DoDrawCharacter(output->iBounds.iTl,output->iBitmapSize,output->iBitmap);
       
   349 			}
       
   350 		}
       
   351 	if (shapeInfo.IsOpen())
       
   352 		shapeInfo.Close();
       
   353 		
       
   354 	}
       
   355 
       
   356 void CFbsBitGc::DoDrawCharacter(const TPoint& aTopLeft,
       
   357 								const TSize& aDataSize,
       
   358 								const TUint8* aData)
       
   359 	{
       
   360 	/*
       
   361 	Divert if the character is larger than expected; the criterion
       
   362 	for choosing this function is only a heuristic, because it's perfectly legal for
       
   363 	a character's bitmap to be wider than its escapement.
       
   364 
       
   365 	Use a dummy value (0) for semi-ascent because this character is not italic and so semi-ascent
       
   366 	is irrelevant; it's used for pseudo-italic slanting.
       
   367 	*/
       
   368 	TInt dataheight = aDataSize.iHeight;
       
   369 	TInt datalength = aDataSize.iWidth;
       
   370 	if (datalength > 30 || dataheight > 32)
       
   371 		{
       
   372 		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,FALSE,FALSE,0,1,1);
       
   373 		return;
       
   374 		}
       
   375 	
       
   376 	TInt bitindex=0;
       
   377 	TInt16 repeatcount=0;
       
   378 	TUint32 binarydata[32];
       
   379 	TUint32* binarydataptr=binarydata;
       
   380 	TUint32* binarydataptrlimit;
       
   381 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
   382 		{
       
   383 		repeatcount=Load16(aData+(bitindex>>3));
       
   384 		repeatcount>>=bitindex&7;
       
   385 		TInt multilineflag=repeatcount&1;
       
   386 		repeatcount>>=1;
       
   387 		repeatcount&=0xf;
       
   388 		bitindex+=5;
       
   389 		binarydataptrlimit=binarydata+charline+repeatcount;
       
   390 		if(multilineflag)
       
   391 			{
       
   392 			while(binarydataptr<binarydataptrlimit)
       
   393 				{
       
   394 				TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
       
   395 				TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
       
   396 				TInt bitshift=bitindex&7;
       
   397 				bitshift+=(chardataoffsetptr&3)<<3;
       
   398 				*binarydataptr=(*chardataword++)>>bitshift;
       
   399 				if(bitshift) *binarydataptr|=(*chardataword<<(32-bitshift));
       
   400 				bitindex+=datalength;
       
   401 				binarydataptr++;
       
   402 				}
       
   403 			}
       
   404 		else
       
   405 			{
       
   406 			TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
       
   407 			TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
       
   408 			TInt bitshift=bitindex&7;
       
   409 			bitshift+=(chardataoffsetptr&3)<<3;
       
   410 			TUint32 data=(*chardataword++)>>bitshift;
       
   411 			if(bitshift) data|=(*chardataword<<(32-bitshift));
       
   412 			while(binarydataptr<binarydataptrlimit)
       
   413 				*binarydataptr++=data;
       
   414 			bitindex+=datalength;
       
   415 			}
       
   416 		}
       
   417 	TPoint topleft(aTopLeft);
       
   418 	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
       
   419 	if(datalength>0 && dataheight>0)
       
   420 		iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
       
   421 	}
       
   422 
       
   423 /** 
       
   424 @internalTechnology
       
   425 
       
   426 This function retrieves the baseline offset from the metrics of the text currently being drawn.
       
   427 This is used to alter the positioning of underline and strikethrough on a linked font
       
   428 
       
   429 @return The baseline correction associated with the currently used font.
       
   430 */	
       
   431 TInt CFbsBitGc::BaselineCorrection()
       
   432 	{
       
   433 	TOpenFontMetrics metrics;
       
   434 	if (iFont.GetFontMetrics(metrics))
       
   435 		return metrics.BaselineCorrection();
       
   436 	else
       
   437 		return 0;
       
   438 	}
       
   439 
       
   440 void CFbsBitGc::DoDrawTextEx(CFont::TPositionParam& aParam,const CBitmapFont* font, const TInt aEnd, const TInt aUnderlineStrikethroughOffset)
       
   441 	{
       
   442 	const TInt charclipping = iClipRect.iBr.iX;
       
   443 	TPoint start_pen = aParam.iPen;
       
   444 	const TBool bold = font->iAlgStyle.IsBold();
       
   445 	const TBool italic = font->iAlgStyle.IsItalic();
       
   446 	const TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
       
   447 	const TBool outlineShadowOrAntialiased = ((glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap) ||
       
   448 												(glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap));
       
   449 
       
   450 	TInt underline_top = 0, underline_bottom = 0;
       
   451 	if (iUnderline == EUnderlineOn)
       
   452 		{
       
   453 		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
       
   454 		underline_top+=aUnderlineStrikethroughOffset;
       
   455 		underline_bottom+=aUnderlineStrikethroughOffset;
       
   456 		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
       
   457 		}
       
   458 	TInt strike_top = 0, strike_bottom = 0;
       
   459 	if (italic || iStrikethrough == EStrikethroughOn)
       
   460 		{
       
   461 		GetStrikethroughMetrics(strike_top,strike_bottom);
       
   462 		strike_top+=aUnderlineStrikethroughOffset;
       
   463 		strike_bottom+=aUnderlineStrikethroughOffset;
       
   464 		}
       
   465 
       
   466 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   467 	RShapeInfo shapeInfo;
       
   468 	while (aParam.iPosInText < aEnd)
       
   469 		{
       
   470 		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
       
   471 			continue;
       
   472 		TInt adjustment = 0;
       
   473 		if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
       
   474 			{
       
   475 			adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
       
   476 			if(adjustment < 0)
       
   477 				iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
       
   478 			}
       
   479 
       
   480 		const CFont::TPositionParam::TOutput* output = aParam.iOutput;
       
   481 		int semi_ascent = start_pen.iY + strike_top;
       
   482 
       
   483 		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
       
   484 			{
       
   485 			//get the character metrics for the glyph type
       
   486 			TOpenFontCharMetrics characterParams;
       
   487 			const TUint8* bitmap;
       
   488 			TSize size;
       
   489 			//note may now be using a glyph code, and not a character
       
   490 			iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
       
   491 			TGlyphBitmapType glyphType = characterParams.GlyphType();
       
   492 			
       
   493 			switch (glyphType)
       
   494 				{
       
   495 				case EAntiAliasedGlyphBitmap:
       
   496 				case EFourColourBlendGlyphBitmap:
       
   497 					DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphType);
       
   498 					break;
       
   499 
       
   500 				case EDefaultGlyphBitmap:
       
   501 				case EMonochromeGlyphBitmap:
       
   502 					DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
       
   503 					break;
       
   504 
       
   505 				default:
       
   506 					//if the outline or shadow is not specified for the character, then use the font setting
       
   507 					if (outlineShadowOrAntialiased)
       
   508 						{
       
   509 						DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphBitmapTypeForFont);			
       
   510 						}
       
   511 					else
       
   512 						{
       
   513 						DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
       
   514 						}			 
       
   515 					break;
       
   516 				}
       
   517 			}
       
   518 
       
   519 		iClipRect.iBr.iX = charclipping;
       
   520 		if (adjustment)
       
   521 			aParam.iPen.iX += adjustment;
       
   522 		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
       
   523 			{
       
   524 			adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
       
   525 			aParam.iPen.iX += adjustment;
       
   526 			}
       
   527 		}
       
   528 	if (shapeInfo.IsOpen())
       
   529 		shapeInfo.Close();
       
   530 
       
   531 	if (iUnderline == EUnderlineOn)
       
   532 		{
       
   533 		TRect ul(start_pen.iX,start_pen.iY + underline_top,aParam.iPen.iX,start_pen.iY + underline_bottom);
       
   534 		if(ul.Intersects(iClipRect)) // checks for empty aRect as well
       
   535 			{
       
   536 			ul.Intersection(iClipRect);
       
   537 			drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
       
   538 			}
       
   539 		}
       
   540 
       
   541 	if (iStrikethrough == EStrikethroughOn)
       
   542 		{
       
   543 		TRect st(start_pen.iX,start_pen.iY + strike_top,aParam.iPen.iX,start_pen.iY + strike_bottom);
       
   544 		if(st.Intersects(iClipRect)) // checks for empty aRect as well
       
   545 			{
       
   546 			st.Intersection(iClipRect);
       
   547 			drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
       
   548 			}
       
   549 		}
       
   550 	}
       
   551 
       
   552 void CFbsBitGc::DoDrawCharacterEx(const TPoint& aTopLeft,
       
   553 								  const TSize& aDataSize,
       
   554 								  const TUint8* aData,
       
   555 								  TBool aBold,TBool aItalic,TInt aSemiAscent)
       
   556 	{
       
   557 	/*
       
   558 	Divert if the character is larger than expected; the criterion
       
   559 	for choosing this function is only a heuristic, because it's perfectly legal for
       
   560 	a character's bitmap to be wider than its escapement.
       
   561 	*/
       
   562 	TInt datalength = aDataSize.iWidth;
       
   563 	TInt dataheight = aDataSize.iHeight;
       
   564 	if (datalength > 30 || dataheight > 32)
       
   565 		{
       
   566 		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,1,1);
       
   567 		return;
       
   568 		}
       
   569 
       
   570 	TInt bitindex=0;
       
   571 	TInt16 repeatcount=0;
       
   572 	TUint32 binarydata[32];
       
   573 	TUint32* binarydataptr=binarydata;
       
   574 	TUint32* binarydataptrlimit;
       
   575 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
   576 		{
       
   577 		repeatcount=Load16(aData+(bitindex>>3));
       
   578 		repeatcount>>=bitindex&7;
       
   579 		TInt multilineflag=repeatcount&1;
       
   580 		repeatcount>>=1;
       
   581 		repeatcount&=0xf;
       
   582 		bitindex+=5;
       
   583 		binarydataptrlimit=binarydata+charline+repeatcount;
       
   584 		if(multilineflag)
       
   585 			{
       
   586 			while(binarydataptr<binarydataptrlimit)
       
   587 				{
       
   588 				CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
       
   589 				bitindex+=datalength;
       
   590 				binarydataptr++;
       
   591 				}
       
   592 			}
       
   593 		else
       
   594 			{
       
   595 			TUint32 data=0;
       
   596 			CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
       
   597 			while(binarydataptr<binarydataptrlimit)
       
   598 				*binarydataptr++=data;
       
   599 			bitindex+=datalength;
       
   600 			}
       
   601 		}
       
   602 	binarydataptr=binarydata;
       
   603 	binarydataptrlimit=binarydata+dataheight;
       
   604 	if(aBold)
       
   605 		{
       
   606 		TInt sparemask=(0xffffffff>>(32-datalength));
       
   607 		while(binarydataptr<binarydataptrlimit)
       
   608 			{
       
   609 			*binarydataptr&=sparemask;
       
   610 			*binarydataptr|=(*binarydataptr<<1);
       
   611 			++binarydataptr;
       
   612 			}
       
   613 		binarydataptr=binarydata;
       
   614 		datalength++;
       
   615 		}
       
   616 	if(aItalic)
       
   617 		{
       
   618 		TInt skewlevel=aSemiAscent-aTopLeft.iY;
       
   619 		TUint32 sparemask=(0xffffffff>>(32-datalength));
       
   620 		binarydataptrlimit=binarydata+skewlevel;
       
   621 		while(binarydataptr<binarydataptrlimit)
       
   622 			*binarydataptr++<<=1;
       
   623 		binarydataptrlimit=binarydata+dataheight;
       
   624 		while(binarydataptr<binarydataptrlimit)
       
   625 			*binarydataptr++&=sparemask;
       
   626 		binarydataptr=binarydata;
       
   627 		datalength++;
       
   628 		}
       
   629 	TPoint topleft(aTopLeft);
       
   630 	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
       
   631 	if(datalength>0 && dataheight>0)
       
   632 		iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
       
   633 	}
       
   634 
       
   635 /** 
       
   636 @internalTechnology
       
   637 
       
   638 This function draws an anti-aliased character.
       
   639 
       
   640 @param aTopLeft The position to output the character
       
   641 @param aDataSize The size of the bitmap
       
   642 @param aData the bitmap for outputt in their TOpenFontCharMetrics
       
   643 @param aGlyphType the glyph type for the character
       
   644 */
       
   645 void CFbsBitGc::DoDrawCharacterAntiAliased(const TPoint& aTopLeft,
       
   646 										   const TSize& aDataSize,
       
   647 										   const TUint8* aData,
       
   648 										   const TGlyphBitmapType aGlyphType)
       
   649 	{
       
   650 	const int top_row = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
       
   651 	const int bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iY - aTopLeft.iY);
       
   652 	const int left_col = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
       
   653 	const int right_col = Min(aDataSize.iWidth,iClipRect.iBr.iX - aTopLeft.iX);
       
   654 	const TUint8* p = aData + top_row * aDataSize.iWidth + left_col;
       
   655 	const int x = aTopLeft.iX + left_col;
       
   656 	int y = aTopLeft.iY + top_row;
       
   657 	const int cols = right_col - left_col;
       
   658 	const TUint32 penColor = iPenColor.Internal();
       
   659 	const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
       
   660 	const TUint32 brushColor = iBrushColor.Internal();
       
   661 
       
   662 	if (EFourColourBlendGlyphBitmap == aGlyphType)
       
   663 		{
       
   664 		MOutlineAndShadowBlend* outlineAndShadow = NULL;
       
   665 		const TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
       
   666 		if(err == KErrNone) 
       
   667 			{
       
   668 			//There is a support for the interface with KOutlineAndShadowInterface id.
       
   669 			for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
       
   670 				outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p);
       
   671 			}
       
   672 		else
       
   673 			{
       
   674 			// Assert if MOutlineAndShadowBlend interface is not implemented
       
   675 			BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
       
   676 			}
       
   677 		}
       
   678 	else
       
   679 		{
       
   680 		for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
       
   681 			iDevice->iDrawDevice->WriteRgbAlphaMulti(x,y,cols,iPenColor,p);
       
   682 		}
       
   683 	}
       
   684 
       
   685 void CFbsBitGc::DoDrawTextLarge(CFont::TPositionParam& aParam,const CBitmapFont* font,const TInt aEnd)
       
   686 	{
       
   687 	const TInt charclipping = iClipRect.iBr.iX;
       
   688 	TPoint start_pen = aParam.iPen;
       
   689 	const TInt strikeheight = start_pen.iY - (font->CBitmapFont::DoAscentInPixels() * 5/12) - 1;
       
   690 	const TBool bold = font->iAlgStyle.IsBold();
       
   691 	const TBool italic = font->iAlgStyle.IsItalic();
       
   692 	const TInt widthfactor=font->iAlgStyle.WidthFactor();
       
   693 	const TInt heightfactor=font->iAlgStyle.HeightFactor();
       
   694 
       
   695 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   696 
       
   697 	RShapeInfo shapeInfo;
       
   698 	while (aParam.iPosInText < aEnd)
       
   699 		{
       
   700 		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
       
   701 			continue;
       
   702 		TInt adjustment = 0;
       
   703 		if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
       
   704 			{
       
   705 			adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
       
   706 			if(adjustment < 0)
       
   707 				iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
       
   708 			}
       
   709 
       
   710 		const CFont::TPositionParam::TOutput* output = aParam.iOutput;
       
   711 		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
       
   712 			DoDrawCharacterLarge(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,strikeheight,
       
   713 								 widthfactor,heightfactor);
       
   714 
       
   715 		iClipRect.iBr.iX = charclipping;
       
   716 		if (adjustment)
       
   717 			aParam.iPen.iX += adjustment;
       
   718 		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
       
   719 			{
       
   720 			adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
       
   721 			aParam.iPen.iX += adjustment;
       
   722 			}
       
   723 		}
       
   724 	if (shapeInfo.IsOpen())
       
   725 		shapeInfo.Close();
       
   726 	const TInt ulwidth = Max(font->CBitmapFont::DoHeightInPixels() / 10, 1);
       
   727 	if (iUnderline == EUnderlineOn)
       
   728 		{
       
   729 		TInt ulstart = start_pen.iY + 1 + ulwidth / 2;
       
   730 		TRect ul(start_pen.iX,ulstart,aParam.iPen.iX,ulstart + ulwidth);
       
   731 		if(ul.Intersects(iClipRect)) // checks for empty aRect as well
       
   732 			{
       
   733 			ul.Intersection(iClipRect);
       
   734 			drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
       
   735 			}
       
   736 		}
       
   737 
       
   738 	if (iStrikethrough == EStrikethroughOn)
       
   739 		{
       
   740 		TRect st(start_pen.iX,strikeheight,aParam.iPen.iX,strikeheight + ulwidth);
       
   741 		if(st.Intersects(iClipRect)) // checks for empty aRect as well
       
   742 			{
       
   743 			st.Intersection(iClipRect);
       
   744 			drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
       
   745 			}
       
   746 		}
       
   747 	}
       
   748 
       
   749 void CFbsBitGc::DoDrawCharacterLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
       
   750 									 TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
       
   751 	{
       
   752 	TInt datalength = aDataSize.iWidth;
       
   753 	TInt dataheight = aDataSize.iHeight;
       
   754 	
       
   755 	if (aWidthFactor > 2 || aHeightFactor > 2)
       
   756 		{
       
   757 		DoDrawCharacterMultiplied(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
       
   758 		return;
       
   759 		}
       
   760 	
       
   761 	if (datalength > 30 || dataheight > 32 || (aWidthFactor == 2 && datalength > 14))
       
   762 		{
       
   763 		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
       
   764 		return;
       
   765 		}
       
   766 	
       
   767 	TInt italicheight=aSemiAscent-aTopLeft.iY;
       
   768 	if(aHeightFactor==2) italicheight>>=1;
       
   769 	TInt bitindex=0;
       
   770 	TInt16 repeatcount=0;
       
   771 	TUint32 binarydata[64];
       
   772 	TUint32* binarydataptr=binarydata;
       
   773 	TUint32* binarydataptrlimit;
       
   774 
       
   775 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
   776 		{
       
   777 		repeatcount=Load16(aData+(bitindex>>3));
       
   778 		repeatcount>>=bitindex&7;
       
   779 		TInt multilineflag=repeatcount&1;
       
   780 		repeatcount>>=1;
       
   781 		repeatcount&=0xf;
       
   782 		bitindex+=5;
       
   783 		binarydataptrlimit=binarydata+charline+repeatcount;
       
   784 		if(multilineflag)
       
   785 			{
       
   786 			while(binarydataptr<binarydataptrlimit)
       
   787 				{
       
   788 				CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
       
   789 				bitindex+=datalength;
       
   790 				binarydataptr++;
       
   791 				}
       
   792 			}
       
   793 		else
       
   794 			{
       
   795 			TUint32 data=0;
       
   796 			CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
       
   797 			while(binarydataptr<binarydataptrlimit)
       
   798 				*binarydataptr++=data;
       
   799 			bitindex+=datalength;
       
   800 			}
       
   801 		}
       
   802 	binarydataptr=binarydata;
       
   803 	binarydataptrlimit=binarydata+dataheight;
       
   804 	if(aBold)
       
   805 		{
       
   806 		TInt sparemask=(0xffffffff>>(32-datalength));
       
   807 		while(binarydataptr<binarydataptrlimit)
       
   808 			{
       
   809 			*binarydataptr&=sparemask;
       
   810 			*binarydataptr|=(*binarydataptr<<1);
       
   811 			++binarydataptr;
       
   812 			}
       
   813 		binarydataptr=binarydata;
       
   814 		datalength++;
       
   815 		}
       
   816 	if(aItalic)
       
   817 		{
       
   818 		TUint32 sparemask=(0xffffffff>>(32-datalength));
       
   819 		binarydataptrlimit=Min(binarydataptrlimit,binarydata+italicheight);
       
   820 		while(binarydataptr<binarydataptrlimit)
       
   821 			{
       
   822 			*binarydataptr<<=1;
       
   823 			*binarydataptr++&=0xfffffffe;
       
   824 			}
       
   825 		binarydataptrlimit=binarydata+dataheight;
       
   826 		while(binarydataptr<binarydataptrlimit)
       
   827 			*binarydataptr++&=sparemask;
       
   828 		binarydataptr=binarydata;
       
   829 		datalength++;
       
   830 		}
       
   831 	if(aWidthFactor==2)
       
   832 		{
       
   833 		BG_ASSERT_DEBUG(datalength<=16,EBitgdiPanicCharacterTooBig);
       
   834 		while(binarydataptr<binarydataptrlimit)
       
   835 			{
       
   836 			TUint32 singlemask=0x8000;
       
   837 			TUint32 doublemask=0xc0000000;
       
   838 			TUint32 newdata=0;
       
   839 			while(singlemask)
       
   840 				{
       
   841 				if(*binarydataptr&singlemask)
       
   842 					newdata|=doublemask;
       
   843 				singlemask>>=1;
       
   844 				doublemask>>=2;
       
   845 				}
       
   846 			*binarydataptr++=newdata;
       
   847 			}
       
   848 		datalength<<=1;
       
   849 		binarydataptr=binarydata;
       
   850 		}
       
   851 	if(aHeightFactor==2)
       
   852 		{
       
   853 		binarydataptr=binarydata+dataheight-1;
       
   854 		TUint32* tempptr=binarydataptr+dataheight;
       
   855 		while(binarydataptr>=binarydata)
       
   856 			{
       
   857 			*tempptr--=*binarydataptr;
       
   858 			*tempptr--=*binarydataptr--;
       
   859 			}
       
   860 		dataheight<<=1;
       
   861 		binarydataptr=binarydata;
       
   862 		}
       
   863 	TPoint startpos=aTopLeft;
       
   864 	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,startpos);
       
   865 	if(datalength>0 && dataheight>0)
       
   866 		iDevice->iDrawDevice->WriteBinary(startpos.iX,startpos.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
       
   867 	}
       
   868 
       
   869 void CFbsBitGc::DoDrawCharacterExLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
       
   870 									   TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
       
   871 	{
       
   872 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   873 	TPoint printpos(aTopLeft);
       
   874 	const TInt datalength = aDataSize.iWidth;
       
   875 	const TInt dataheight = aDataSize.iHeight;
       
   876 	TInt bitindex=0;
       
   877 	TInt16 repeatcount=0;
       
   878 	TUint32* slbuffer=drawDevice->ScanLineBuffer();
       
   879 	const TInt slwords=(drawDevice->ScanLineBytes())<<3;
       
   880 	if(aItalic && aTopLeft.iY<aSemiAscent)
       
   881 		printpos.iX++;
       
   882 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
   883 		{
       
   884 		repeatcount=Load16(aData+(bitindex>>3));
       
   885 		repeatcount>>=bitindex&7;
       
   886 		const TInt multilineflag=repeatcount&1;
       
   887 		repeatcount>>=1;
       
   888 		repeatcount&=0xf;
       
   889 		bitindex+=5;
       
   890 		if(multilineflag)
       
   891 			{
       
   892 			for(TInt currentline=0;currentline<repeatcount;currentline++)
       
   893 				{
       
   894 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   895 				OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
       
   896 				bitindex+=datalength;
       
   897 				printpos.iY++;
       
   898 				if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
       
   899 				if(aHeightFactor==2)
       
   900 					{
       
   901 					printpos.iY++;
       
   902 					if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
       
   903 					}
       
   904 				}
       
   905 			}
       
   906 		else
       
   907 			{
       
   908 			if(aItalic)
       
   909 				{
       
   910 				for(TInt currentline=0;currentline<repeatcount;currentline++)
       
   911 					{
       
   912 					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   913 					OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
       
   914 					printpos.iY++;
       
   915 					if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
       
   916 					if(aHeightFactor==2)
       
   917 						{
       
   918 						printpos.iY++;
       
   919 						if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
       
   920 						}
       
   921 					}
       
   922 				}
       
   923 			else
       
   924 				{
       
   925 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   926 				OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
       
   927 				printpos.iY+=repeatcount;
       
   928 				if(aHeightFactor==2) printpos.iY+=repeatcount;
       
   929 				}
       
   930 			bitindex+=datalength;
       
   931 			}
       
   932 		}
       
   933 	}
       
   934 
       
   935 void CFbsBitGc::DoDrawCharacterMultiplied(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
       
   936 										  TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
       
   937 	{
       
   938 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   939 	TPoint printpos(aTopLeft);
       
   940 	const TInt datalength = aDataSize.iWidth;
       
   941 	const TInt dataheight = aDataSize.iHeight;
       
   942 	TInt bitindex=0;
       
   943 	TInt16 repeatcount=0;
       
   944 	TUint32* slbuffer=drawDevice->ScanLineBuffer();
       
   945 	const TInt slwords=(drawDevice->ScanLineBytes())<<3;
       
   946 	if(aItalic && aTopLeft.iY<aSemiAscent)
       
   947 		printpos.iX++;
       
   948 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
   949 		{
       
   950 		repeatcount=Load16(aData+(bitindex>>3));
       
   951 		repeatcount>>=bitindex&7;
       
   952 		const TInt multilineflag=repeatcount&1;
       
   953 		repeatcount>>=1;
       
   954 		repeatcount&=0xf;
       
   955 		bitindex+=5;
       
   956 		if(multilineflag)
       
   957 			{
       
   958 			for(TInt currentline=0;currentline<repeatcount;currentline++)
       
   959 				{
       
   960 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   961 				OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
       
   962 				bitindex+=datalength;
       
   963 				TBool aboveitalicjump=EFalse;
       
   964 				if(aItalic && printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
       
   965 				printpos.iY+=aHeightFactor;
       
   966 				if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
       
   967 				}
       
   968 			}
       
   969 		else
       
   970 			{
       
   971 			if(aItalic)
       
   972 				{
       
   973 				for(TInt currentline=0;currentline<repeatcount;currentline++)
       
   974 					{
       
   975 					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   976 					OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
       
   977 					TBool aboveitalicjump=EFalse;
       
   978 					if(printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
       
   979 					printpos.iY+=aHeightFactor;
       
   980 					if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
       
   981 					}
       
   982 				}
       
   983 			else
       
   984 				{
       
   985 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   986 				OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
       
   987 				printpos.iY+=repeatcount*aHeightFactor;
       
   988 				}
       
   989 			bitindex+=datalength;
       
   990 			}
       
   991 		}
       
   992 	}
       
   993 
       
   994 void CFbsBitGc::OutputCharLineMultiplied(TPoint aPrintPos,TUint32* aBuffer,TInt aDataLength,TInt aNum,TBool aBold,TInt aWidthFactor,TInt aHeightFactor)
       
   995 	{
       
   996 	if(aDataLength<=0) return;
       
   997 	TInt bufferwords=(aDataLength+31)>>5;
       
   998 	TUint32* bufferlimit=aBuffer+bufferwords;
       
   999 	if(aBold)
       
  1000 		{
       
  1001 		TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
       
  1002 		if((aDataLength&0x1f)==0) sparemask=0xffffffff;
       
  1003 		*(bufferlimit-1)&=sparemask;
       
  1004 		TUint32* bufferptr=aBuffer;
       
  1005 		TUint32 extrabit=0;
       
  1006 		while(bufferptr<bufferlimit)
       
  1007 			{
       
  1008 			extrabit=*bufferptr>>31;
       
  1009 			*bufferptr|=(*bufferptr<<1);
       
  1010 			++bufferptr;
       
  1011 			if(bufferptr<bufferlimit)
       
  1012 				*bufferptr|=extrabit;
       
  1013 			}
       
  1014 		aDataLength++;
       
  1015 		if((aDataLength&0x1f)==1)
       
  1016 			{
       
  1017 			bufferwords++;
       
  1018 			*bufferlimit=extrabit;
       
  1019 			bufferlimit++;
       
  1020 			}
       
  1021 		}
       
  1022 	if(aWidthFactor>1)
       
  1023 		{
       
  1024 		BitMultiply(aBuffer,aDataLength,aWidthFactor);
       
  1025 		aDataLength*=aWidthFactor;
       
  1026 		bufferwords=(aDataLength+31)>>5;
       
  1027 		bufferlimit=aBuffer+bufferwords;
       
  1028 		}
       
  1029 	if(aPrintPos.iX<iClipRect.iTl.iX)
       
  1030 		{
       
  1031 		TInt pixelexcess=iClipRect.iTl.iX-aPrintPos.iX;
       
  1032 		while(pixelexcess>=32)
       
  1033 			{
       
  1034 			aBuffer++;
       
  1035 			bufferwords--;
       
  1036 			aDataLength-=32;
       
  1037 			pixelexcess-=32;
       
  1038 			}
       
  1039 		if(aDataLength<=0) return;
       
  1040 		if(pixelexcess>0)
       
  1041 			{
       
  1042 			TInt shiftup=32-pixelexcess;
       
  1043 			TUint32* bufferptr=aBuffer;
       
  1044 			while(bufferptr<bufferlimit)
       
  1045 				{
       
  1046 				*bufferptr>>=pixelexcess;
       
  1047 				if(bufferptr<bufferlimit-1)
       
  1048 					*bufferptr|=(*(bufferptr+1)<<shiftup);
       
  1049 				bufferptr++;
       
  1050 				}
       
  1051 			aDataLength-=pixelexcess;
       
  1052 			if(aDataLength<=0) return;
       
  1053 			}
       
  1054 		aPrintPos.iX=iClipRect.iTl.iX;
       
  1055 		}
       
  1056 	if(aPrintPos.iX+aDataLength>iClipRect.iBr.iX)
       
  1057 		{
       
  1058 		TInt pixelexcess=aPrintPos.iX+aDataLength-iClipRect.iBr.iX;
       
  1059 		aDataLength-=pixelexcess;
       
  1060 		if(aDataLength<=0) return;
       
  1061 		}
       
  1062 	aNum*=aHeightFactor;
       
  1063 	while(aNum>0)
       
  1064 		{
       
  1065 		if(aPrintPos.iY>=iClipRect.iTl.iY && aPrintPos.iY<iClipRect.iBr.iY)
       
  1066 			iDevice->iDrawDevice->WriteBinaryLine(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode);
       
  1067 		aPrintPos.iY++;
       
  1068 		aNum--;
       
  1069 		}
       
  1070 	}
       
  1071 
       
  1072 void CFbsBitGc::CopyCharWord(TUint32* aBinaryDataPtr,const TUint8* aData,TInt aBitShift)
       
  1073 	{
       
  1074 	const TUint32* dataword=(TUint32*)(TInt(aData)&~3);
       
  1075 	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
       
  1076 	*aBinaryDataPtr=*dataword++;
       
  1077 	if(aBitShift<32) *aBinaryDataPtr>>=aBitShift;
       
  1078 	if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
       
  1079 	}
       
  1080 	
       
  1081 void CFbsBitGc::CopyCharLine(TUint32* aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth)
       
  1082 	{
       
  1083 	aBitShift&=7;
       
  1084 	TInt wordstocopy=(aCharWidth+31)>>5;
       
  1085 	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
       
  1086 	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
       
  1087 	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
       
  1088 	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
       
  1089 	while(aBinaryDataPtr<ptrlimit)
       
  1090 		{
       
  1091 		*aBinaryDataPtr=*dataword++;
       
  1092 		*aBinaryDataPtr>>=aBitShift;
       
  1093 		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
       
  1094 		aBinaryDataPtr++;
       
  1095 		}
       
  1096 	}
       
  1097 	
       
  1098 TUint32* CFbsBitGc::ClipBinaryArray(TUint32* aArray,TUint32* aArrayLimit,TInt aArrayWordWd,TInt& aDataWd,TInt& aDataHt,TPoint& aPos)
       
  1099 	{
       
  1100 	TUint32* arrayptr=aArray;
       
  1101 	TInt clipdiff=iClipRect.iTl.iX-aPos.iX;
       
  1102 	if(aArrayWordWd==1)
       
  1103 		{
       
  1104 		if(clipdiff>0)
       
  1105 			{
       
  1106 			while(arrayptr<aArrayLimit)
       
  1107 				*arrayptr++>>=clipdiff;
       
  1108 			aDataWd-=clipdiff;
       
  1109 			aPos.iX=iClipRect.iTl.iX;
       
  1110 			arrayptr=aArray;
       
  1111 			}
       
  1112 		if(aPos.iX+aDataWd>iClipRect.iBr.iX && aDataWd>0)
       
  1113 			aDataWd=iClipRect.iBr.iX-aPos.iX;
       
  1114 		clipdiff=iClipRect.iTl.iY-aPos.iY;
       
  1115 		if(clipdiff>0)
       
  1116 			{
       
  1117 			aDataHt-=clipdiff;
       
  1118 			arrayptr+=clipdiff;
       
  1119 			aPos.iY=iClipRect.iTl.iY;
       
  1120 			}
       
  1121 		if(aPos.iY+aDataHt>iClipRect.iBr.iY && aDataHt>0)
       
  1122 			aDataHt=iClipRect.iBr.iY-aPos.iY;
       
  1123 		}
       
  1124 	return(arrayptr);
       
  1125 	}
       
  1126 
       
  1127 void CFbsBitGc::BitMultiply(TUint32* aBinaryDataPtr,TInt aBitLength,TInt aFactor)
       
  1128 	{
       
  1129 	TInt bitpos=aBitLength-1;
       
  1130 	TUint32* wordpos=aBinaryDataPtr+(bitpos>>5);
       
  1131 	TInt bitoffset=bitpos&0x1f;
       
  1132 	TInt multbitpos=(aBitLength*aFactor)-1;
       
  1133 	TUint32* multwordpos=aBinaryDataPtr+(multbitpos>>5);
       
  1134 	TInt multbitoffset=multbitpos&0x1f;
       
  1135 	while(bitpos>=0)
       
  1136 		{
       
  1137 		TUint32 bit=((*wordpos)>>bitoffset)&1;
       
  1138 		TInt next=multbitpos-aFactor;
       
  1139 		while(multbitpos>next)
       
  1140 			{
       
  1141 			if(bit) *multwordpos|=(1<<multbitoffset);
       
  1142 			else *multwordpos&=~(1<<multbitoffset);
       
  1143 			multbitpos--;
       
  1144 			multbitoffset--;
       
  1145 			if(multbitoffset<0)
       
  1146 				{
       
  1147 				multbitoffset=31;
       
  1148 				multwordpos--;
       
  1149 				}
       
  1150 			}
       
  1151 		bitpos--;
       
  1152 		bitoffset--;
       
  1153 		if(bitoffset<0)
       
  1154 			{
       
  1155 			bitoffset=31;
       
  1156 			wordpos--;
       
  1157 			}
       
  1158 		}
       
  1159 	}
       
  1160 
       
  1161 void CFbsBitGc::GetStrikethroughMetrics(TInt& aTop,TInt& aBottom)
       
  1162 /** Get the top and bottom of a strikethrough line for the current font, relative to the baseline.*/
       
  1163 	{
       
  1164 	aTop = -(iFont.AscentInPixels() * 5/12) - 1;
       
  1165 	aBottom = aTop + Max(iFont.HeightInPixels() / 10,1);
       
  1166 	}
       
  1167 
       
  1168 /** APIExtension can contain as many additional methods as is required by 
       
  1169 CGraphicsContext after its original conception. It takes 3 parameters.
       
  1170 Function is exported due to constrains of retaining BC with earlier versions.
       
  1171 This is not used directly by external methods, instead it is called by a named 
       
  1172 method in CGraphicsContext which passes the relivant arguements including an 
       
  1173 unique identifier for the required action.
       
  1174 @param aUid The unique identifier for the method that is required. Selected 
       
  1175 internally by a series of "if" statements. 
       
  1176 @see Valid Uid identifiers are listed in header gdi.h
       
  1177 @see CGraphicsContext
       
  1178 @param aOutput is a TAny pointer to a reference. Used to output data as the structure
       
  1179 does not need to be instantiated before the function call this adds greater 
       
  1180 flexibility.
       
  1181 @param aInput is a TAny pointer used to input data.
       
  1182 */	
       
  1183 EXPORT_C TInt CFbsBitGc::APIExtension(TUid aUid, TAny*& aOutput, TAny* aInput)
       
  1184 	{
       
  1185 	if (aUid == KGetUnderlineMetrics)
       
  1186 		{		
       
  1187 		APIExGetUnderlineMetrics(aOutput);
       
  1188 		return KErrNone;	
       
  1189 		}
       
  1190 	else if (aUid == KSetShadowColor)
       
  1191 		{
       
  1192 		return APIExSetShadowColor(aInput);
       
  1193 		}
       
  1194 	else if (aUid == KGetShadowColor)
       
  1195 		{
       
  1196 		return APIExGetShadowColor(aOutput);
       
  1197 		}
       
  1198 	else if (aUid == KDrawTextInContextUid)
       
  1199 		{
       
  1200 		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
       
  1201 		DrawText(contextParam->iText, &contextParam->iParam, contextParam->iPosition);
       
  1202 		return KErrNone;
       
  1203 		}
       
  1204 	else if (aUid == KDrawBoxTextInContextUid)
       
  1205 		{
       
  1206 		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
       
  1207 		DrawText(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iAlign,contextParam->iMargin);
       
  1208 		return KErrNone;
       
  1209 		}
       
  1210 	else if (aUid == KDrawTextInContextVerticalUid)
       
  1211 		{
       
  1212 		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
       
  1213 		DrawTextVertical(contextParam->iText, &contextParam->iParam, contextParam->iPosition,contextParam->iUp);
       
  1214 		return KErrNone;
       
  1215 		}
       
  1216 	else if (aUid == KDrawBoxTextInContextVerticalUid)
       
  1217 		{
       
  1218 		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
       
  1219 		DrawTextVertical(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iUp,contextParam->iAlign,contextParam->iMargin);
       
  1220 		return KErrNone;
       
  1221 		}
       
  1222 	else if (aUid == KUidIsFbsBitmapGc)
       
  1223 		{
       
  1224 		return APIExIsFbsBitGc(aOutput);
       
  1225 		}
       
  1226 	/* Future cases may be placed here later.*/
       
  1227 	else
       
  1228 		return CBitmapContext::APIExtension(aUid, aOutput, aInput);
       
  1229 	}
       
  1230 	
       
  1231 	
       
  1232 	
       
  1233 	
       
  1234 		
       
  1235 	
       
  1236 	
       
  1237 	
       
  1238 	
       
  1239 //The methods listed above in APIExtension follow here with the prefix APIEx.
       
  1240 void CFbsBitGc::APIExGetUnderlineMetrics(TAny*& aOutput)
       
  1241 	{
       
  1242 	const TInt width = Max(iFont.HeightInPixels() / 10,1);
       
  1243 	TTwoTInt* ptr = (TTwoTInt*)aOutput;
       
  1244 	ptr->iTop = 1 + width / 2;
       
  1245 	ptr->iBottom = (ptr->iTop) + width;
       
  1246 	}
       
  1247 
       
  1248 TInt CFbsBitGc::APIExSetShadowColor(TAny* aShadowColor)
       
  1249 	{
       
  1250 	iFbsBitGcExtraData->SetShadowColor(*(reinterpret_cast<TRgb*>(aShadowColor)));
       
  1251 	return KErrNone;
       
  1252 	}
       
  1253 
       
  1254 TInt CFbsBitGc::APIExGetShadowColor(TAny*& aShadowColor)
       
  1255 	{
       
  1256 	TRgb* output = reinterpret_cast<TRgb*>(aShadowColor);
       
  1257 	*output = iFbsBitGcExtraData->ShadowColor();
       
  1258 	return KErrNone;
       
  1259 	}
       
  1260 	
       
  1261 TInt CFbsBitGc::APIExIsFbsBitGc(TAny*& aIsCFbsBitGc)
       
  1262 	{
       
  1263 	TBool *output = reinterpret_cast<TBool*>(aIsCFbsBitGc);
       
  1264 	*output = ETrue;
       
  1265 	return KErrNone;
       
  1266 	}
       
  1267 
       
  1268 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam)
       
  1269 	{
       
  1270 	DrawText(aText,aParam,iLastPrintPosition,ELeft,CFont::EHorizontal);
       
  1271 	}
       
  1272 
       
  1273 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition)
       
  1274 	{
       
  1275 	DrawText(aText,aParam,aPosition,ELeft,CFont::EHorizontal);
       
  1276 	}
       
  1277 	
       
  1278 	
       
  1279 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox)
       
  1280 	{
       
  1281 	TRect boxcpy(aBox);
       
  1282 	boxcpy.Move(iOrigin);
       
  1283 	if(!iUserClipRect.Intersects(boxcpy)) return;
       
  1284 	TRect oldcliprect(iUserClipRect);
       
  1285 	iUserClipRect.Intersection(boxcpy);
       
  1286 	DrawText(aText,aParam);
       
  1287 	iUserClipRect=oldcliprect;
       
  1288 	}
       
  1289 	
       
  1290 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHrz,TInt aMargin)
       
  1291 	{
       
  1292 	DrawText(aText,aParam,aBox,aBaselineOffset,-1,aHrz,aMargin);
       
  1293 	}
       
  1294 	
       
  1295 EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt /*aTextWidth*/,TTextAlign aHrz,TInt aMargin)
       
  1296 	{
       
  1297 	// aTextWidth is not used here - try to abolish this - I think it is unneeded
       
  1298 	TPoint p(aBox.iTl);
       
  1299 	p.iY += aBaselineOffset;
       
  1300 	switch (aHrz)
       
  1301 		{
       
  1302 		case ELeft: p.iX += aMargin; break;
       
  1303 		case ERight: p.iX = aBox.iBr.iX - aMargin; break;
       
  1304 		case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
       
  1305 		}
       
  1306 	DrawText(aText,aParam,p,aHrz,CFont::EHorizontal,&aBox);
       
  1307 	}