graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1307 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <fntstore.h>
+#include <bitdraw.h>
+#include <bitstd.h>
+#include <bitdev.h>
+#include "BITPANIC.H"
+#include <shapeinfo.h>
+#include <bmalphablend.h>
+#include <bitdrawinterfaceid.h>
+#include <graphics/fbsrasterizer.h>
+#include "bitgcextradata.h"
+#include <graphics/gdi/gdiconsts.h>
+#include <graphics/gdi/gdistructs.h>
+
+
+/** Draws text at the last print position.
+
+@param aText The text string to be drawn. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText)
+	{
+	TTextParameters* param = NULL;
+	DrawText(aText,param,iLastPrintPosition,ELeft,CFont::EHorizontal);
+	}
+
+/** Draws text at the specified position and updates the print position.
+
+@param  aText The text string to be drawn
+@param aCoords Coordinates to draw the text at. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TPoint& aCoords)
+	{
+	TTextParameters* param = NULL;
+	DrawText(aText,param,aCoords,ELeft,CFont::EHorizontal);
+	}
+
+
+/** Draws text clipped to the specified rectangle.
+
+@param aText The text string to be drawn 
+@param aBox The clipping rectangle. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox)
+	{
+	TTextParameters* param = NULL;
+	DrawText(aText,param,aBox);
+	}
+
+
+/** Draws text clipped to the specified rectangle using a baseline offset,
+horizontal alignment and a margin.
+
+@param  aText The text string to be drawn
+@param aBox The clipping rectangle.
+@param  aBLOff An offset in pixels for the baseline from the normal position
+        (bottom of the rectangle minus the descent of the font).
+@param  aHrz Horizontal alignment option relative to the specified rectangle.
+@param aMargin Offset to add to the position as calculated using specified 
+		rectangle. */	
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,TInt aBLOff,
+								  TTextAlign aHrz,TInt aMargin)
+    {
+    TTextParameters* param = NULL;
+	DrawText(aText,param,aBox,aBLOff,-1,aHrz,aMargin);
+	}
+
+/** Draws text clipped to the specified rectangle.
+
+@param  aText The text string to be drawn
+@param aBox The clipping rectangle. */	
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,
+								  TInt aBLOff,TInt /*aTextWidth*/,
+								  TTextAlign aHrz,TInt aMargin)
+    {
+// aTextWidth is not used here - try to abolish this - I think it is unneeded
+	TPoint p(aBox.iTl);
+	p.iY += aBLOff;
+	switch (aHrz)
+		{
+		case ELeft: p.iX += aMargin; break;
+		case ERight: p.iX = aBox.iBr.iX - aMargin; break;
+		case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
+		}
+	TTextParameters* param = NULL;
+	DrawText(aText,param,p,aHrz,CFont::EHorizontal,&aBox);
+	}
+
+
+/** The general DrawText routine that implements all the others.
+
+@param aText the text to be drawn
+@param aPosition the origin of the text
+@param aAlignment left, centred or right, around aPosition; not used if drawing vertically
+@param aDirection direction: left to right, right to left, or top to bottom
+@param aBox if non-null, filled before the text is drawn
+@param aTextBounds if non-null returns the bounding box of the text
+*/ 
+void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TTextAlign aAlignment,
+						 CFont::TTextDirection aDirection,const TRect* aBox)
+   {
+	// sanity checks
+	BG_ASSERT_ALWAYS(iDevice,EBitgdiPanicNoDevicePresent);
+	BG_ASSERT_ALWAYS(iFont.Handle() != 0,EBitgdiPanicNoFontSelected);
+	const CBitmapFont* bitmap_font = iFont.Address();
+	BG_ASSERT_ALWAYS(bitmap_font != 0,EBitgdiPanicNoFontSelected);
+
+	// anything to do?
+	if (!aBox && !aText.Length())
+		return;
+
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+	TRect deviceRect;
+	drawDevice->GetDrawRect(deviceRect);
+
+	// measure the text
+	CFont::TMeasureTextInput measure_text_input;
+	measure_text_input.iCharJustNum = iCharJustNum;
+	measure_text_input.iCharJustExcess = iCharJustExcess;
+	measure_text_input.iWordJustNum = iWordJustNum;
+	measure_text_input.iWordJustExcess = iWordJustExcess;
+	measure_text_input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder;
+	if (aParam)
+		{
+		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
+		measure_text_input.iStartInputChar = aParam->iStart;
+		measure_text_input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
+		}
+	CFont::TMeasureTextOutput measure_text_output;
+	const int advance = iFont.MeasureText(aText,&measure_text_input,&measure_text_output);
+	TRect text_bounds = measure_text_output.iBounds;
+	TInt underlineStrikeoutOffset;
+	
+	//this call is only needed in the case of linked fonts
+	//should this pass by one structure?
+	underlineStrikeoutOffset= BaselineCorrection();
+	
+	if (iUnderline == EUnderlineOn)
+		{
+		TInt underline_top = 0, underline_bottom = 0;
+		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
+		underline_top+=underlineStrikeoutOffset;
+		underline_bottom+=underlineStrikeoutOffset;
+		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
+		text_bounds.iTl.iY = Min(text_bounds.iTl.iY,underline_top);
+		text_bounds.iBr.iY = Max(text_bounds.iBr.iY,underline_bottom);
+		}
+	if (iStrikethrough == EStrikethroughOn)
+		{
+		TInt strike_top = 0,strike_bottom = 0;
+		GetStrikethroughMetrics(strike_top,strike_bottom);
+		strike_top+=underlineStrikeoutOffset;
+		strike_bottom+=underlineStrikeoutOffset;
+		text_bounds.iTl.iY = Min(text_bounds.iTl.iY,strike_top);
+		text_bounds.iBr.iY = Max(text_bounds.iBr.iY,strike_bottom);
+		}
+	if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
+		{
+		if (aDirection == CFont::EHorizontal)
+			{
+			text_bounds.iTl.iX = Min(text_bounds.iTl.iX, 0);
+			text_bounds.iBr.iX = Max(text_bounds.iBr.iX, advance);
+			}
+		else
+			{
+			text_bounds.iTl.iY = Min(text_bounds.iTl.iY, 0);
+			text_bounds.iBr.iY = Max(text_bounds.iBr.iY, advance);
+			}
+		}
+
+	// work out the text origin and new drawing position
+ 	TPoint text_origin = aPosition;
+ 	if (aDirection != CFont::EVertical)
+ 		{
+ 		const TInt leftSideBearing = Min(text_bounds.iTl.iX, 0);
+ 		const TInt rightSideBearing = Max(text_bounds.iBr.iX, advance);
+ 		switch (aAlignment)
+ 			{
+			// We are forbidding side-bearings to leak over the sides here,
+			// but still keeping the start and end pen positions within bounds.
+			case ELeft:
+				text_origin.iX -= leftSideBearing;
+				break;
+			case ERight:
+				text_origin.iX -= rightSideBearing;
+				break;
+			case ECenter:
+				// Centre is the average of left and right
+				text_origin.iX -= (leftSideBearing + rightSideBearing) >> 1;
+				break;
+			default:
+				break;
+ 			}
+		}
+	iLastPrintPosition = text_origin;
+	if (aDirection == CFont::EHorizontal)
+		iLastPrintPosition.iX += advance;
+	else
+		iLastPrintPosition.iY += advance;
+	text_origin.iY += bitmap_font->iAlgStyle.iBaselineOffsetInPixels;
+	text_bounds.Move(text_origin);
+	text_origin += iOrigin;
+
+	// determine clipping rectangle
+	TRect clip_rect = aBox ? *aBox : text_bounds;
+	AddRect(clip_rect);
+	clip_rect.Move(iOrigin);
+
+	if (UserClipRect(clip_rect))
+		{
+		if (iAutoUpdateJustification)
+			UpdateJustification(aText,aParam);
+		return; // nothing to do
+		}
+
+	SetupDevice();
+	iDevice->DrawingBegin(&iBrushBitmap);
+	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+
+	// fill the box if necessary
+	if (aBox)
+		{
+		TRect fill_box = *aBox;
+		fill_box.Move(iOrigin);
+		RectFill(fill_box);
+		}
+
+	// decide which drawing routine to call
+	const TBool bold = bitmap_font->iAlgStyle.IsBold();
+	const TBool italic = bitmap_font->iAlgStyle.IsItalic();
+	const TBool multiw = bitmap_font->iAlgStyle.WidthFactor() > 1;
+	const TBool multih = bitmap_font->iAlgStyle.HeightFactor() > 1;
+
+	TOpenFontMetrics metrics;
+	iFont.GetFontMetrics(metrics);
+	const TInt maxwidth = metrics.MaxWidth();
+	// extext will be TRUE, if font is bold/italic/underline/strikethrough/anti-aliased or it 
+	// has shadow/outline effects ON. Depending on these properties it will call the proper draw routine.
+	TBool extext = FALSE;
+	TBool normaltext = FALSE;
+	const TBool anti_aliased = (bitmap_font->GlyphBitmapType() == EAntiAliasedGlyphBitmap);
+	const TBool outlineAndShadow = (bitmap_font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
+	if (anti_aliased || outlineAndShadow)
+		{
+		if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
+			{
+			//For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used 
+			//when drawing outline and shadow fonts.
+			BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
+			}
+		extext = TRUE;
+		}
+	else if (maxwidth > 30 || text_bounds.Height() > 32 || multiw || multih)
+		{
+		}
+	else if (iUnderline == EUnderlineOn || bold || italic || iStrikethrough == EStrikethroughOn || 
+			 iCharJustNum > 0 || iWordJustNum > 0)
+		extext = TRUE;
+	else
+		normaltext = TRUE;
+
+	const TInt charjustexcess = iCharJustExcess;
+	const TInt charjustnum = iCharJustNum;
+	const TInt wordjustexcess = iWordJustExcess;
+	const TInt wordjustnum = iWordJustNum;
+
+	// draw the text to all clip rectangles in turn
+	int clip_rects = iDefaultRegionPtr->Count();
+	for (int i = 0; i < clip_rects; i++)
+		{
+		iClipRect = (*iDefaultRegionPtr)[i];
+		if (!iClipRect.Intersects(clip_rect))
+			continue;
+
+#ifdef _DEBUG
+		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
+		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
+		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
+		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
+#endif
+
+		iClipRect.Intersection(clip_rect);
+
+		// Set up the parameter block for character positioning.
+		CFont::TPositionParam param;
+		param.iDirection = static_cast<TInt16>(aDirection);
+		param.iText.Set(aText);
+		TInt endDraw = aText.Length();
+		if (aParam)
+			{
+			param.iPosInText = aParam->iStart;
+			endDraw = Min(aText.Length(),aParam->iEnd);
+			}
+		else
+			param.iPosInText = 0;
+		param.iPen = text_origin;
+
+		// Draw the text.
+		if (normaltext)
+			DoDrawText(param,endDraw);
+		else if (extext)
+			DoDrawTextEx(param,bitmap_font,endDraw,underlineStrikeoutOffset);
+		else
+			DoDrawTextLarge(param,bitmap_font,endDraw);
+		
+		/*
+		Reset the justification parameters to their original values.
+		These will be updated as required later in code.
+		*/
+		iCharJustExcess = charjustexcess;
+		iCharJustNum = charjustnum;
+		iWordJustExcess = wordjustexcess;
+		iWordJustNum = wordjustnum;
+
+		drawDevice->UpdateRegion(iClipRect);
+		}
+
+	if (brushRasterizer)
+		{
+		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+		}
+	iDevice->DrawingEnd(&iBrushBitmap);
+	if (iAutoUpdateJustification)
+		UpdateJustification(aText,aParam);
+	}
+
+void CFbsBitGc::DoDrawText(CFont::TPositionParam& aParam, const TInt aEnd)
+	{
+	//const int n = aParam.iText.Length();
+	RShapeInfo shapeInfo;
+	while (aParam.iPosInText < /*n*/aEnd)
+		{
+		if (iFont.GetCharacterPosition2(aParam, shapeInfo))
+			{
+			const CFont::TPositionParam::TOutput* output = aParam.iOutput;
+			for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+				DoDrawCharacter(output->iBounds.iTl,output->iBitmapSize,output->iBitmap);
+			}
+		}
+	if (shapeInfo.IsOpen())
+		shapeInfo.Close();
+		
+	}
+
+void CFbsBitGc::DoDrawCharacter(const TPoint& aTopLeft,
+								const TSize& aDataSize,
+								const TUint8* aData)
+	{
+	/*
+	Divert if the character is larger than expected; the criterion
+	for choosing this function is only a heuristic, because it's perfectly legal for
+	a character's bitmap to be wider than its escapement.
+
+	Use a dummy value (0) for semi-ascent because this character is not italic and so semi-ascent
+	is irrelevant; it's used for pseudo-italic slanting.
+	*/
+	TInt dataheight = aDataSize.iHeight;
+	TInt datalength = aDataSize.iWidth;
+	if (datalength > 30 || dataheight > 32)
+		{
+		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,FALSE,FALSE,0,1,1);
+		return;
+		}
+	
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TUint32 binarydata[32];
+	TUint32* binarydataptr=binarydata;
+	TUint32* binarydataptrlimit;
+	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+		{
+		repeatcount=Load16(aData+(bitindex>>3));
+		repeatcount>>=bitindex&7;
+		TInt multilineflag=repeatcount&1;
+		repeatcount>>=1;
+		repeatcount&=0xf;
+		bitindex+=5;
+		binarydataptrlimit=binarydata+charline+repeatcount;
+		if(multilineflag)
+			{
+			while(binarydataptr<binarydataptrlimit)
+				{
+				TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
+				TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
+				TInt bitshift=bitindex&7;
+				bitshift+=(chardataoffsetptr&3)<<3;
+				*binarydataptr=(*chardataword++)>>bitshift;
+				if(bitshift) *binarydataptr|=(*chardataword<<(32-bitshift));
+				bitindex+=datalength;
+				binarydataptr++;
+				}
+			}
+		else
+			{
+			TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
+			TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
+			TInt bitshift=bitindex&7;
+			bitshift+=(chardataoffsetptr&3)<<3;
+			TUint32 data=(*chardataword++)>>bitshift;
+			if(bitshift) data|=(*chardataword<<(32-bitshift));
+			while(binarydataptr<binarydataptrlimit)
+				*binarydataptr++=data;
+			bitindex+=datalength;
+			}
+		}
+	TPoint topleft(aTopLeft);
+	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
+	if(datalength>0 && dataheight>0)
+		iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
+	}
+
+/** 
+@internalTechnology
+
+This function retrieves the baseline offset from the metrics of the text currently being drawn.
+This is used to alter the positioning of underline and strikethrough on a linked font
+
+@return The baseline correction associated with the currently used font.
+*/	
+TInt CFbsBitGc::BaselineCorrection()
+	{
+	TOpenFontMetrics metrics;
+	if (iFont.GetFontMetrics(metrics))
+		return metrics.BaselineCorrection();
+	else
+		return 0;
+	}
+
+void CFbsBitGc::DoDrawTextEx(CFont::TPositionParam& aParam,const CBitmapFont* font, const TInt aEnd, const TInt aUnderlineStrikethroughOffset)
+	{
+	const TInt charclipping = iClipRect.iBr.iX;
+	TPoint start_pen = aParam.iPen;
+	const TBool bold = font->iAlgStyle.IsBold();
+	const TBool italic = font->iAlgStyle.IsItalic();
+	const TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
+	const TBool outlineShadowOrAntialiased = ((glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap) ||
+												(glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap));
+
+	TInt underline_top = 0, underline_bottom = 0;
+	if (iUnderline == EUnderlineOn)
+		{
+		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
+		underline_top+=aUnderlineStrikethroughOffset;
+		underline_bottom+=aUnderlineStrikethroughOffset;
+		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
+		}
+	TInt strike_top = 0, strike_bottom = 0;
+	if (italic || iStrikethrough == EStrikethroughOn)
+		{
+		GetStrikethroughMetrics(strike_top,strike_bottom);
+		strike_top+=aUnderlineStrikethroughOffset;
+		strike_bottom+=aUnderlineStrikethroughOffset;
+		}
+
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	RShapeInfo shapeInfo;
+	while (aParam.iPosInText < aEnd)
+		{
+		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
+			continue;
+		TInt adjustment = 0;
+		if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
+			{
+			adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
+			if(adjustment < 0)
+				iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
+			}
+
+		const CFont::TPositionParam::TOutput* output = aParam.iOutput;
+		int semi_ascent = start_pen.iY + strike_top;
+
+		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+			{
+			//get the character metrics for the glyph type
+			TOpenFontCharMetrics characterParams;
+			const TUint8* bitmap;
+			TSize size;
+			//note may now be using a glyph code, and not a character
+			iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
+			TGlyphBitmapType glyphType = characterParams.GlyphType();
+			
+			switch (glyphType)
+				{
+				case EAntiAliasedGlyphBitmap:
+				case EFourColourBlendGlyphBitmap:
+					DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphType);
+					break;
+
+				case EDefaultGlyphBitmap:
+				case EMonochromeGlyphBitmap:
+					DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
+					break;
+
+				default:
+					//if the outline or shadow is not specified for the character, then use the font setting
+					if (outlineShadowOrAntialiased)
+						{
+						DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphBitmapTypeForFont);			
+						}
+					else
+						{
+						DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
+						}			 
+					break;
+				}
+			}
+
+		iClipRect.iBr.iX = charclipping;
+		if (adjustment)
+			aParam.iPen.iX += adjustment;
+		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
+			{
+			adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
+			aParam.iPen.iX += adjustment;
+			}
+		}
+	if (shapeInfo.IsOpen())
+		shapeInfo.Close();
+
+	if (iUnderline == EUnderlineOn)
+		{
+		TRect ul(start_pen.iX,start_pen.iY + underline_top,aParam.iPen.iX,start_pen.iY + underline_bottom);
+		if(ul.Intersects(iClipRect)) // checks for empty aRect as well
+			{
+			ul.Intersection(iClipRect);
+			drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
+			}
+		}
+
+	if (iStrikethrough == EStrikethroughOn)
+		{
+		TRect st(start_pen.iX,start_pen.iY + strike_top,aParam.iPen.iX,start_pen.iY + strike_bottom);
+		if(st.Intersects(iClipRect)) // checks for empty aRect as well
+			{
+			st.Intersection(iClipRect);
+			drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
+			}
+		}
+	}
+
+void CFbsBitGc::DoDrawCharacterEx(const TPoint& aTopLeft,
+								  const TSize& aDataSize,
+								  const TUint8* aData,
+								  TBool aBold,TBool aItalic,TInt aSemiAscent)
+	{
+	/*
+	Divert if the character is larger than expected; the criterion
+	for choosing this function is only a heuristic, because it's perfectly legal for
+	a character's bitmap to be wider than its escapement.
+	*/
+	TInt datalength = aDataSize.iWidth;
+	TInt dataheight = aDataSize.iHeight;
+	if (datalength > 30 || dataheight > 32)
+		{
+		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,1,1);
+		return;
+		}
+
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TUint32 binarydata[32];
+	TUint32* binarydataptr=binarydata;
+	TUint32* binarydataptrlimit;
+	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+		{
+		repeatcount=Load16(aData+(bitindex>>3));
+		repeatcount>>=bitindex&7;
+		TInt multilineflag=repeatcount&1;
+		repeatcount>>=1;
+		repeatcount&=0xf;
+		bitindex+=5;
+		binarydataptrlimit=binarydata+charline+repeatcount;
+		if(multilineflag)
+			{
+			while(binarydataptr<binarydataptrlimit)
+				{
+				CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
+				bitindex+=datalength;
+				binarydataptr++;
+				}
+			}
+		else
+			{
+			TUint32 data=0;
+			CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
+			while(binarydataptr<binarydataptrlimit)
+				*binarydataptr++=data;
+			bitindex+=datalength;
+			}
+		}
+	binarydataptr=binarydata;
+	binarydataptrlimit=binarydata+dataheight;
+	if(aBold)
+		{
+		TInt sparemask=(0xffffffff>>(32-datalength));
+		while(binarydataptr<binarydataptrlimit)
+			{
+			*binarydataptr&=sparemask;
+			*binarydataptr|=(*binarydataptr<<1);
+			++binarydataptr;
+			}
+		binarydataptr=binarydata;
+		datalength++;
+		}
+	if(aItalic)
+		{
+		TInt skewlevel=aSemiAscent-aTopLeft.iY;
+		TUint32 sparemask=(0xffffffff>>(32-datalength));
+		binarydataptrlimit=binarydata+skewlevel;
+		while(binarydataptr<binarydataptrlimit)
+			*binarydataptr++<<=1;
+		binarydataptrlimit=binarydata+dataheight;
+		while(binarydataptr<binarydataptrlimit)
+			*binarydataptr++&=sparemask;
+		binarydataptr=binarydata;
+		datalength++;
+		}
+	TPoint topleft(aTopLeft);
+	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
+	if(datalength>0 && dataheight>0)
+		iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
+	}
+
+/** 
+@internalTechnology
+
+This function draws an anti-aliased character.
+
+@param aTopLeft The position to output the character
+@param aDataSize The size of the bitmap
+@param aData the bitmap for outputt in their TOpenFontCharMetrics
+@param aGlyphType the glyph type for the character
+*/
+void CFbsBitGc::DoDrawCharacterAntiAliased(const TPoint& aTopLeft,
+										   const TSize& aDataSize,
+										   const TUint8* aData,
+										   const TGlyphBitmapType aGlyphType)
+	{
+	const int top_row = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
+	const int bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iY - aTopLeft.iY);
+	const int left_col = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
+	const int right_col = Min(aDataSize.iWidth,iClipRect.iBr.iX - aTopLeft.iX);
+	const TUint8* p = aData + top_row * aDataSize.iWidth + left_col;
+	const int x = aTopLeft.iX + left_col;
+	int y = aTopLeft.iY + top_row;
+	const int cols = right_col - left_col;
+	const TUint32 penColor = iPenColor.Internal();
+	const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
+	const TUint32 brushColor = iBrushColor.Internal();
+
+	if (EFourColourBlendGlyphBitmap == aGlyphType)
+		{
+		MOutlineAndShadowBlend* outlineAndShadow = NULL;
+		const TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
+		if(err == KErrNone) 
+			{
+			//There is a support for the interface with KOutlineAndShadowInterface id.
+			for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
+				outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p);
+			}
+		else
+			{
+			// Assert if MOutlineAndShadowBlend interface is not implemented
+			BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
+			}
+		}
+	else
+		{
+		for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
+			iDevice->iDrawDevice->WriteRgbAlphaMulti(x,y,cols,iPenColor,p);
+		}
+	}
+
+void CFbsBitGc::DoDrawTextLarge(CFont::TPositionParam& aParam,const CBitmapFont* font,const TInt aEnd)
+	{
+	const TInt charclipping = iClipRect.iBr.iX;
+	TPoint start_pen = aParam.iPen;
+	const TInt strikeheight = start_pen.iY - (font->CBitmapFont::DoAscentInPixels() * 5/12) - 1;
+	const TBool bold = font->iAlgStyle.IsBold();
+	const TBool italic = font->iAlgStyle.IsItalic();
+	const TInt widthfactor=font->iAlgStyle.WidthFactor();
+	const TInt heightfactor=font->iAlgStyle.HeightFactor();
+
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+	RShapeInfo shapeInfo;
+	while (aParam.iPosInText < aEnd)
+		{
+		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
+			continue;
+		TInt adjustment = 0;
+		if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
+			{
+			adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
+			if(adjustment < 0)
+				iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
+			}
+
+		const CFont::TPositionParam::TOutput* output = aParam.iOutput;
+		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+			DoDrawCharacterLarge(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,strikeheight,
+								 widthfactor,heightfactor);
+
+		iClipRect.iBr.iX = charclipping;
+		if (adjustment)
+			aParam.iPen.iX += adjustment;
+		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
+			{
+			adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
+			aParam.iPen.iX += adjustment;
+			}
+		}
+	if (shapeInfo.IsOpen())
+		shapeInfo.Close();
+	const TInt ulwidth = Max(font->CBitmapFont::DoHeightInPixels() / 10, 1);
+	if (iUnderline == EUnderlineOn)
+		{
+		TInt ulstart = start_pen.iY + 1 + ulwidth / 2;
+		TRect ul(start_pen.iX,ulstart,aParam.iPen.iX,ulstart + ulwidth);
+		if(ul.Intersects(iClipRect)) // checks for empty aRect as well
+			{
+			ul.Intersection(iClipRect);
+			drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
+			}
+		}
+
+	if (iStrikethrough == EStrikethroughOn)
+		{
+		TRect st(start_pen.iX,strikeheight,aParam.iPen.iX,strikeheight + ulwidth);
+		if(st.Intersects(iClipRect)) // checks for empty aRect as well
+			{
+			st.Intersection(iClipRect);
+			drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
+			}
+		}
+	}
+
+void CFbsBitGc::DoDrawCharacterLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
+									 TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
+	{
+	TInt datalength = aDataSize.iWidth;
+	TInt dataheight = aDataSize.iHeight;
+	
+	if (aWidthFactor > 2 || aHeightFactor > 2)
+		{
+		DoDrawCharacterMultiplied(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
+		return;
+		}
+	
+	if (datalength > 30 || dataheight > 32 || (aWidthFactor == 2 && datalength > 14))
+		{
+		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
+		return;
+		}
+	
+	TInt italicheight=aSemiAscent-aTopLeft.iY;
+	if(aHeightFactor==2) italicheight>>=1;
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TUint32 binarydata[64];
+	TUint32* binarydataptr=binarydata;
+	TUint32* binarydataptrlimit;
+
+	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+		{
+		repeatcount=Load16(aData+(bitindex>>3));
+		repeatcount>>=bitindex&7;
+		TInt multilineflag=repeatcount&1;
+		repeatcount>>=1;
+		repeatcount&=0xf;
+		bitindex+=5;
+		binarydataptrlimit=binarydata+charline+repeatcount;
+		if(multilineflag)
+			{
+			while(binarydataptr<binarydataptrlimit)
+				{
+				CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
+				bitindex+=datalength;
+				binarydataptr++;
+				}
+			}
+		else
+			{
+			TUint32 data=0;
+			CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
+			while(binarydataptr<binarydataptrlimit)
+				*binarydataptr++=data;
+			bitindex+=datalength;
+			}
+		}
+	binarydataptr=binarydata;
+	binarydataptrlimit=binarydata+dataheight;
+	if(aBold)
+		{
+		TInt sparemask=(0xffffffff>>(32-datalength));
+		while(binarydataptr<binarydataptrlimit)
+			{
+			*binarydataptr&=sparemask;
+			*binarydataptr|=(*binarydataptr<<1);
+			++binarydataptr;
+			}
+		binarydataptr=binarydata;
+		datalength++;
+		}
+	if(aItalic)
+		{
+		TUint32 sparemask=(0xffffffff>>(32-datalength));
+		binarydataptrlimit=Min(binarydataptrlimit,binarydata+italicheight);
+		while(binarydataptr<binarydataptrlimit)
+			{
+			*binarydataptr<<=1;
+			*binarydataptr++&=0xfffffffe;
+			}
+		binarydataptrlimit=binarydata+dataheight;
+		while(binarydataptr<binarydataptrlimit)
+			*binarydataptr++&=sparemask;
+		binarydataptr=binarydata;
+		datalength++;
+		}
+	if(aWidthFactor==2)
+		{
+		BG_ASSERT_DEBUG(datalength<=16,EBitgdiPanicCharacterTooBig);
+		while(binarydataptr<binarydataptrlimit)
+			{
+			TUint32 singlemask=0x8000;
+			TUint32 doublemask=0xc0000000;
+			TUint32 newdata=0;
+			while(singlemask)
+				{
+				if(*binarydataptr&singlemask)
+					newdata|=doublemask;
+				singlemask>>=1;
+				doublemask>>=2;
+				}
+			*binarydataptr++=newdata;
+			}
+		datalength<<=1;
+		binarydataptr=binarydata;
+		}
+	if(aHeightFactor==2)
+		{
+		binarydataptr=binarydata+dataheight-1;
+		TUint32* tempptr=binarydataptr+dataheight;
+		while(binarydataptr>=binarydata)
+			{
+			*tempptr--=*binarydataptr;
+			*tempptr--=*binarydataptr--;
+			}
+		dataheight<<=1;
+		binarydataptr=binarydata;
+		}
+	TPoint startpos=aTopLeft;
+	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,startpos);
+	if(datalength>0 && dataheight>0)
+		iDevice->iDrawDevice->WriteBinary(startpos.iX,startpos.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
+	}
+
+void CFbsBitGc::DoDrawCharacterExLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
+									   TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
+	{
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	TPoint printpos(aTopLeft);
+	const TInt datalength = aDataSize.iWidth;
+	const TInt dataheight = aDataSize.iHeight;
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TUint32* slbuffer=drawDevice->ScanLineBuffer();
+	const TInt slwords=(drawDevice->ScanLineBytes())<<3;
+	if(aItalic && aTopLeft.iY<aSemiAscent)
+		printpos.iX++;
+	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+		{
+		repeatcount=Load16(aData+(bitindex>>3));
+		repeatcount>>=bitindex&7;
+		const TInt multilineflag=repeatcount&1;
+		repeatcount>>=1;
+		repeatcount&=0xf;
+		bitindex+=5;
+		if(multilineflag)
+			{
+			for(TInt currentline=0;currentline<repeatcount;currentline++)
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+				OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+				bitindex+=datalength;
+				printpos.iY++;
+				if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+				if(aHeightFactor==2)
+					{
+					printpos.iY++;
+					if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+					}
+				}
+			}
+		else
+			{
+			if(aItalic)
+				{
+				for(TInt currentline=0;currentline<repeatcount;currentline++)
+					{
+					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+					OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+					printpos.iY++;
+					if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+					if(aHeightFactor==2)
+						{
+						printpos.iY++;
+						if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+						}
+					}
+				}
+			else
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+				OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
+				printpos.iY+=repeatcount;
+				if(aHeightFactor==2) printpos.iY+=repeatcount;
+				}
+			bitindex+=datalength;
+			}
+		}
+	}
+
+void CFbsBitGc::DoDrawCharacterMultiplied(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
+										  TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
+	{
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	TPoint printpos(aTopLeft);
+	const TInt datalength = aDataSize.iWidth;
+	const TInt dataheight = aDataSize.iHeight;
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TUint32* slbuffer=drawDevice->ScanLineBuffer();
+	const TInt slwords=(drawDevice->ScanLineBytes())<<3;
+	if(aItalic && aTopLeft.iY<aSemiAscent)
+		printpos.iX++;
+	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+		{
+		repeatcount=Load16(aData+(bitindex>>3));
+		repeatcount>>=bitindex&7;
+		const TInt multilineflag=repeatcount&1;
+		repeatcount>>=1;
+		repeatcount&=0xf;
+		bitindex+=5;
+		if(multilineflag)
+			{
+			for(TInt currentline=0;currentline<repeatcount;currentline++)
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+				OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+				bitindex+=datalength;
+				TBool aboveitalicjump=EFalse;
+				if(aItalic && printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
+				printpos.iY+=aHeightFactor;
+				if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
+				}
+			}
+		else
+			{
+			if(aItalic)
+				{
+				for(TInt currentline=0;currentline<repeatcount;currentline++)
+					{
+					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+					OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+					TBool aboveitalicjump=EFalse;
+					if(printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
+					printpos.iY+=aHeightFactor;
+					if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
+					}
+				}
+			else
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+				OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
+				printpos.iY+=repeatcount*aHeightFactor;
+				}
+			bitindex+=datalength;
+			}
+		}
+	}
+
+void CFbsBitGc::OutputCharLineMultiplied(TPoint aPrintPos,TUint32* aBuffer,TInt aDataLength,TInt aNum,TBool aBold,TInt aWidthFactor,TInt aHeightFactor)
+	{
+	if(aDataLength<=0) return;
+	TInt bufferwords=(aDataLength+31)>>5;
+	TUint32* bufferlimit=aBuffer+bufferwords;
+	if(aBold)
+		{
+		TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
+		if((aDataLength&0x1f)==0) sparemask=0xffffffff;
+		*(bufferlimit-1)&=sparemask;
+		TUint32* bufferptr=aBuffer;
+		TUint32 extrabit=0;
+		while(bufferptr<bufferlimit)
+			{
+			extrabit=*bufferptr>>31;
+			*bufferptr|=(*bufferptr<<1);
+			++bufferptr;
+			if(bufferptr<bufferlimit)
+				*bufferptr|=extrabit;
+			}
+		aDataLength++;
+		if((aDataLength&0x1f)==1)
+			{
+			bufferwords++;
+			*bufferlimit=extrabit;
+			bufferlimit++;
+			}
+		}
+	if(aWidthFactor>1)
+		{
+		BitMultiply(aBuffer,aDataLength,aWidthFactor);
+		aDataLength*=aWidthFactor;
+		bufferwords=(aDataLength+31)>>5;
+		bufferlimit=aBuffer+bufferwords;
+		}
+	if(aPrintPos.iX<iClipRect.iTl.iX)
+		{
+		TInt pixelexcess=iClipRect.iTl.iX-aPrintPos.iX;
+		while(pixelexcess>=32)
+			{
+			aBuffer++;
+			bufferwords--;
+			aDataLength-=32;
+			pixelexcess-=32;
+			}
+		if(aDataLength<=0) return;
+		if(pixelexcess>0)
+			{
+			TInt shiftup=32-pixelexcess;
+			TUint32* bufferptr=aBuffer;
+			while(bufferptr<bufferlimit)
+				{
+				*bufferptr>>=pixelexcess;
+				if(bufferptr<bufferlimit-1)
+					*bufferptr|=(*(bufferptr+1)<<shiftup);
+				bufferptr++;
+				}
+			aDataLength-=pixelexcess;
+			if(aDataLength<=0) return;
+			}
+		aPrintPos.iX=iClipRect.iTl.iX;
+		}
+	if(aPrintPos.iX+aDataLength>iClipRect.iBr.iX)
+		{
+		TInt pixelexcess=aPrintPos.iX+aDataLength-iClipRect.iBr.iX;
+		aDataLength-=pixelexcess;
+		if(aDataLength<=0) return;
+		}
+	aNum*=aHeightFactor;
+	while(aNum>0)
+		{
+		if(aPrintPos.iY>=iClipRect.iTl.iY && aPrintPos.iY<iClipRect.iBr.iY)
+			iDevice->iDrawDevice->WriteBinaryLine(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode);
+		aPrintPos.iY++;
+		aNum--;
+		}
+	}
+
+void CFbsBitGc::CopyCharWord(TUint32* aBinaryDataPtr,const TUint8* aData,TInt aBitShift)
+	{
+	const TUint32* dataword=(TUint32*)(TInt(aData)&~3);
+	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
+	*aBinaryDataPtr=*dataword++;
+	if(aBitShift<32) *aBinaryDataPtr>>=aBitShift;
+	if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
+	}
+	
+void CFbsBitGc::CopyCharLine(TUint32* aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth)
+	{
+	aBitShift&=7;
+	TInt wordstocopy=(aCharWidth+31)>>5;
+	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
+	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
+	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
+	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
+	while(aBinaryDataPtr<ptrlimit)
+		{
+		*aBinaryDataPtr=*dataword++;
+		*aBinaryDataPtr>>=aBitShift;
+		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
+		aBinaryDataPtr++;
+		}
+	}
+	
+TUint32* CFbsBitGc::ClipBinaryArray(TUint32* aArray,TUint32* aArrayLimit,TInt aArrayWordWd,TInt& aDataWd,TInt& aDataHt,TPoint& aPos)
+	{
+	TUint32* arrayptr=aArray;
+	TInt clipdiff=iClipRect.iTl.iX-aPos.iX;
+	if(aArrayWordWd==1)
+		{
+		if(clipdiff>0)
+			{
+			while(arrayptr<aArrayLimit)
+				*arrayptr++>>=clipdiff;
+			aDataWd-=clipdiff;
+			aPos.iX=iClipRect.iTl.iX;
+			arrayptr=aArray;
+			}
+		if(aPos.iX+aDataWd>iClipRect.iBr.iX && aDataWd>0)
+			aDataWd=iClipRect.iBr.iX-aPos.iX;
+		clipdiff=iClipRect.iTl.iY-aPos.iY;
+		if(clipdiff>0)
+			{
+			aDataHt-=clipdiff;
+			arrayptr+=clipdiff;
+			aPos.iY=iClipRect.iTl.iY;
+			}
+		if(aPos.iY+aDataHt>iClipRect.iBr.iY && aDataHt>0)
+			aDataHt=iClipRect.iBr.iY-aPos.iY;
+		}
+	return(arrayptr);
+	}
+
+void CFbsBitGc::BitMultiply(TUint32* aBinaryDataPtr,TInt aBitLength,TInt aFactor)
+	{
+	TInt bitpos=aBitLength-1;
+	TUint32* wordpos=aBinaryDataPtr+(bitpos>>5);
+	TInt bitoffset=bitpos&0x1f;
+	TInt multbitpos=(aBitLength*aFactor)-1;
+	TUint32* multwordpos=aBinaryDataPtr+(multbitpos>>5);
+	TInt multbitoffset=multbitpos&0x1f;
+	while(bitpos>=0)
+		{
+		TUint32 bit=((*wordpos)>>bitoffset)&1;
+		TInt next=multbitpos-aFactor;
+		while(multbitpos>next)
+			{
+			if(bit) *multwordpos|=(1<<multbitoffset);
+			else *multwordpos&=~(1<<multbitoffset);
+			multbitpos--;
+			multbitoffset--;
+			if(multbitoffset<0)
+				{
+				multbitoffset=31;
+				multwordpos--;
+				}
+			}
+		bitpos--;
+		bitoffset--;
+		if(bitoffset<0)
+			{
+			bitoffset=31;
+			wordpos--;
+			}
+		}
+	}
+
+void CFbsBitGc::GetStrikethroughMetrics(TInt& aTop,TInt& aBottom)
+/** Get the top and bottom of a strikethrough line for the current font, relative to the baseline.*/
+	{
+	aTop = -(iFont.AscentInPixels() * 5/12) - 1;
+	aBottom = aTop + Max(iFont.HeightInPixels() / 10,1);
+	}
+
+/** APIExtension can contain as many additional methods as is required by 
+CGraphicsContext after its original conception. It takes 3 parameters.
+Function is exported due to constrains of retaining BC with earlier versions.
+This is not used directly by external methods, instead it is called by a named 
+method in CGraphicsContext which passes the relivant arguements including an 
+unique identifier for the required action.
+@param aUid The unique identifier for the method that is required. Selected 
+internally by a series of "if" statements. 
+@see Valid Uid identifiers are listed in header gdi.h
+@see CGraphicsContext
+@param aOutput is a TAny pointer to a reference. Used to output data as the structure
+does not need to be instantiated before the function call this adds greater 
+flexibility.
+@param aInput is a TAny pointer used to input data.
+*/	
+EXPORT_C TInt CFbsBitGc::APIExtension(TUid aUid, TAny*& aOutput, TAny* aInput)
+	{
+	if (aUid == KGetUnderlineMetrics)
+		{		
+		APIExGetUnderlineMetrics(aOutput);
+		return KErrNone;	
+		}
+	else if (aUid == KSetShadowColor)
+		{
+		return APIExSetShadowColor(aInput);
+		}
+	else if (aUid == KGetShadowColor)
+		{
+		return APIExGetShadowColor(aOutput);
+		}
+	else if (aUid == KDrawTextInContextUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		DrawText(contextParam->iText, &contextParam->iParam, contextParam->iPosition);
+		return KErrNone;
+		}
+	else if (aUid == KDrawBoxTextInContextUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		DrawText(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iAlign,contextParam->iMargin);
+		return KErrNone;
+		}
+	else if (aUid == KDrawTextInContextVerticalUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		DrawTextVertical(contextParam->iText, &contextParam->iParam, contextParam->iPosition,contextParam->iUp);
+		return KErrNone;
+		}
+	else if (aUid == KDrawBoxTextInContextVerticalUid)
+		{
+		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+		DrawTextVertical(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iUp,contextParam->iAlign,contextParam->iMargin);
+		return KErrNone;
+		}
+	else if (aUid == KUidIsFbsBitmapGc)
+		{
+		return APIExIsFbsBitGc(aOutput);
+		}
+	/* Future cases may be placed here later.*/
+	else
+		return CBitmapContext::APIExtension(aUid, aOutput, aInput);
+	}
+	
+	
+	
+	
+		
+	
+	
+	
+	
+//The methods listed above in APIExtension follow here with the prefix APIEx.
+void CFbsBitGc::APIExGetUnderlineMetrics(TAny*& aOutput)
+	{
+	const TInt width = Max(iFont.HeightInPixels() / 10,1);
+	TTwoTInt* ptr = (TTwoTInt*)aOutput;
+	ptr->iTop = 1 + width / 2;
+	ptr->iBottom = (ptr->iTop) + width;
+	}
+
+TInt CFbsBitGc::APIExSetShadowColor(TAny* aShadowColor)
+	{
+	iFbsBitGcExtraData->SetShadowColor(*(reinterpret_cast<TRgb*>(aShadowColor)));
+	return KErrNone;
+	}
+
+TInt CFbsBitGc::APIExGetShadowColor(TAny*& aShadowColor)
+	{
+	TRgb* output = reinterpret_cast<TRgb*>(aShadowColor);
+	*output = iFbsBitGcExtraData->ShadowColor();
+	return KErrNone;
+	}
+	
+TInt CFbsBitGc::APIExIsFbsBitGc(TAny*& aIsCFbsBitGc)
+	{
+	TBool *output = reinterpret_cast<TBool*>(aIsCFbsBitGc);
+	*output = ETrue;
+	return KErrNone;
+	}
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam)
+	{
+	DrawText(aText,aParam,iLastPrintPosition,ELeft,CFont::EHorizontal);
+	}
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition)
+	{
+	DrawText(aText,aParam,aPosition,ELeft,CFont::EHorizontal);
+	}
+	
+	
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox)
+	{
+	TRect boxcpy(aBox);
+	boxcpy.Move(iOrigin);
+	if(!iUserClipRect.Intersects(boxcpy)) return;
+	TRect oldcliprect(iUserClipRect);
+	iUserClipRect.Intersection(boxcpy);
+	DrawText(aText,aParam);
+	iUserClipRect=oldcliprect;
+	}
+	
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHrz,TInt aMargin)
+	{
+	DrawText(aText,aParam,aBox,aBaselineOffset,-1,aHrz,aMargin);
+	}
+	
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt /*aTextWidth*/,TTextAlign aHrz,TInt aMargin)
+	{
+	// aTextWidth is not used here - try to abolish this - I think it is unneeded
+	TPoint p(aBox.iTl);
+	p.iY += aBaselineOffset;
+	switch (aHrz)
+		{
+		case ELeft: p.iX += aMargin; break;
+		case ERight: p.iX = aBox.iBr.iX - aMargin; break;
+		case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
+		}
+	DrawText(aText,aParam,p,aHrz,CFont::EHorizontal,&aBox);
+	}