graphicsdeviceinterface/bitgdi/sbit/VERTEXT.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/bitgdi/sbit/VERTEXT.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1037 @@
+// 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 <graphics/fbsrasterizer.h>
+
+#include <bmalphablend.h>
+#include <bitdrawinterfaceid.h>
+#include "bitgcextradata.h"
+
+/** Draws text at the last print position and then rotates it into a vertical position.
+
+@param aText The text string to be drawn.
+@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
+rotated 90 degrees clockwise. */
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,TBool aUp)
+	{
+	DrawTextVertical(aText,iLastPrintPosition,aUp);
+	}
+
+/** Draws text vertically from the specified position.
+
+@param aText The text string to be drawn.
+@param aPosition A point specifying the position of the left end of the text.
+@param aUp  ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text 
+is rotated 90 degrees clockwise. */
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TPoint& aPosition,TBool aUp)
+	{
+	TBrushStyle brushstyle=iBrushStyle;
+	iBrushStyle=CGraphicsContext::ENullBrush;
+	TOpenFontMetrics metrics;
+	iFont.GetFontMetrics(metrics);
+	TInt ascent = metrics.MaxHeight();
+	TInt height = ascent + metrics.MaxDepth();
+	// The next few lines do much the same as TextWidthInPixels but pass
+	// the text in visual order instead of logical order and also take
+	// full account of left and right side bearings on the text
+	CFont::TMeasureTextOutput output;
+	CFont::TMeasureTextInput input;
+	input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
+	TInt advance = iFont.MeasureText(aText,&input,&output);
+	
+	/* expand the clipping rectangle to take account of any underline */
+	if (iUnderline == EUnderlineOn)
+		{
+		TInt underline_top = 0, underline_bottom = 0;
+		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
+		TInt underlineStrikeoutOffset;
+		underlineStrikeoutOffset= BaselineCorrection();
+		underline_top+=underlineStrikeoutOffset;
+		underline_bottom+=underlineStrikeoutOffset;
+		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
+		output.iBounds.iTl.iY = Min(output.iBounds.iTl.iY,underline_top);
+		output.iBounds.iBr.iY = Max(output.iBounds.iBr.iY,underline_bottom);
+		}
+
+	TInt leftBearing = output.iBounds.iTl.iX;
+	TInt rightBearing = advance - output.iBounds.iBr.iX;
+	TRect box;
+	TInt margin=0;
+	if(aUp)
+		{
+		box.iTl.iX=aPosition.iX-ascent;
+		box.iTl.iY=aPosition.iY-advance;
+		box.iBr.iX=aPosition.iX+output.iBounds.iBr.iY+1;//was +height-ascent+1;
+		box.iBr.iY=aPosition.iY;
+		if(leftBearing<0)
+			{
+			box.iBr.iY-=leftBearing;
+			margin=-leftBearing;
+			}
+		if(rightBearing<0)
+			{
+			box.iTl.iY+=rightBearing;
+			}
+   		}
+	else
+		{
+		box.iTl.iX=aPosition.iX-output.iBounds.iBr.iY;//was +ascent-height;
+		box.iTl.iY=aPosition.iY;
+		box.iBr.iX=aPosition.iX+ascent+1;
+		box.iBr.iY=aPosition.iY+advance;
+		if(leftBearing<0)
+			{
+			box.iTl.iY+=leftBearing;
+			margin=-leftBearing;
+			}
+		if(rightBearing<0)
+			{
+			box.iBr.iY-=rightBearing;
+			}
+		}
+	DrawTextVertical(aText,box,ascent,aUp,ELeft,margin);
+	iBrushStyle=brushstyle;
+	}
+
+
+/** Draws text clipped to the specified rectangle and then rotates it into a vertical 
+position.
+
+@param aText The text string to be drawn 
+@param aBox The clipping rectangle.
+@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
+rotated 90 degrees clockwise. */
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TRect& aBox,TBool aUp)
+	{
+	TRect boxcpy(aBox);
+	boxcpy.Move(iOrigin);
+	TRect oldcliprect(iUserClipRect);
+	iUserClipRect.Intersection(boxcpy);
+	DrawTextVertical(aText,aUp);
+	iUserClipRect=oldcliprect;
+	}
+
+
+/** Draws text vertically, clipped to a specified rectangle,
+using a baseline offset, alignment and margin.
+
+@param aText The text string to be drawn.
+@param aBox  A rectangle to clip the text to.
+@param aBaselineOffset Number of pixels to offset the baseline by.
+@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
+rotated 90 degrees clockwise.
+@param aVert Verticaly alignment of the text relative to the specified 
+rectangle.
+@param aMargin Offset of the text from the position within the rectangle, 
+using the specified alignment. */
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
+										  const TRect& aBox,
+										  TInt aBaselineOffset,
+										  TBool aUp,
+										  TTextAlign aVert,
+										  TInt aMargin)
+    {
+	DrawTextVertical(aText,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
+	}
+
+
+/** Draws text vertically, clipped to a specified rectangle, using a baseline 
+offset, alignment and margin.
+
+@param aText The text string to be drawn.
+@param aBox A rectangle to clip the text to.
+@param aBaselineOffset Number of pixels to offset the baseline by.
+@param aTextWidth Number of pixels to clip the text to.
+@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text 
+is rotated 90 degrees clockwise.
+@param aVert Verticaly alignment of the text relative to the specified 
+rectangle.
+@param aMargin Offset of the text from the position within the rectangle, 
+using the specified alignment. */	
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
+										  const TRect& aBox,
+										  TInt aBaselineOffset,
+										  TInt aTextWidth,
+										  TBool aUp,
+										  TTextAlign aVert,
+										  TInt aMargin)
+    {
+	CheckDevice();
+	BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	TRect boxcpy(aBox);
+	boxcpy.Move(iOrigin);
+	AddRect(boxcpy);
+	if (boxcpy.Intersects(iUserClipRect))
+		{
+		boxcpy.Intersection(iUserClipRect);
+		}
+	SetupDevice();
+	iDevice->DrawingBegin(&iBrushBitmap);
+	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+	const CBitmapFont* fontaddress=iFont.Address();
+	if(!fontaddress)
+		{
+		if (brushRasterizer)
+			{
+			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+			}
+		iDevice->DrawingEnd(&iBrushBitmap);
+		BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
+		}
+
+	TInt width = iFont.MeasureText(aText);
+	TOpenFontMetrics metrics;
+	iFont.GetFontMetrics(metrics);
+	TInt textlength=aText.Length();
+	if(aTextWidth<0) aTextWidth=width;
+	TPoint coords;
+	coords.iX=aBox.iTl.iX;
+	TInt dirmult=aUp?-1:1;
+	coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
+	//
+	// iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
+	// pre: iX = 0
+	//
+	// hhhhhhhhhhhhhhhhhhhh
+	// 01234567890123456789
+	// aaaaaaaaaaaaaaaaaadd	aUp=ETrue
+	//                   ^
+	//                   iX = 18 (baseline)
+	//
+	// ddaaaaaaaaaaaaaaaaaa aUp=EFalse
+	//  ^
+	//  iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
+	//
+	coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
+	switch(aVert)
+		{
+	case ELeft:
+		coords.iY+=aMargin*dirmult;
+		break;
+	case ECenter:
+		coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
+		break;
+	case ERight:
+		coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
+		break;
+		}
+	iLastPrintPosition=coords;
+	coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
+	coords+=iOrigin;
+	TInt prewidth=width+iCharJustExcess+iWordJustExcess;
+	iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
+	if(boxcpy.IsEmpty())
+		{
+		if (brushRasterizer)
+			{
+			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+			}
+		iDevice->DrawingEnd(&iBrushBitmap);
+		if (iAutoUpdateJustification)
+			UpdateJustificationVertical(aText,aUp);
+		return;
+		}
+	RectFill(boxcpy);
+	TBool userintersect=boxcpy.Intersects(iUserClipRect);
+	if(!userintersect || !textlength || !width)
+		{
+		if (brushRasterizer)
+			{
+			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+			}
+		iDevice->DrawingEnd(&iBrushBitmap);
+		if (iAutoUpdateJustification)
+			UpdateJustificationVertical(aText,aUp);
+		return;
+		}
+	boxcpy.Intersection(iUserClipRect);
+	TInt charjustexcess=iCharJustExcess;
+	TInt charjustnum=iCharJustNum;
+	TInt wordjustexcess=iWordJustExcess;
+	TInt wordjustnum=iWordJustNum;
+	TInt limit=iDefaultRegionPtr->Count();
+	for(TInt count=0;count<limit;count++)
+		{
+		/*
+		Initialise the justification parameters to the original values at the start of each pass.
+		This means that any number of passes have exactly the same effect on the parameters as one pass;
+		that is, to reduce them by the numbers of items and pixels consumed.
+		*/
+		iCharJustExcess = charjustexcess;
+		iCharJustNum = charjustnum;
+		iWordJustExcess = wordjustexcess;
+		iWordJustNum = wordjustnum;
+
+		iClipRect=(*iDefaultRegionPtr)[count];
+		if(!iClipRect.Intersects(boxcpy))
+			continue;
+#if defined(_DEBUG)
+		TRect deviceRect;
+		drawDevice->GetDrawRect(deviceRect);
+		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(boxcpy);
+		/*
+		Set up the parameter block for character positioning.
+		Draw left to right, because although the text is being drawn vertically,
+		it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
+		the characters in their normal orientation but in a vertical column.
+		*/
+		CFont::TPositionParam param;
+		param.iText.Set(aText);
+		param.iPen = coords;
+
+		// Draw the text.
+		DoDrawTextVertical(param,fontaddress,aUp,aText.Length());
+
+		drawDevice->UpdateRegion(iClipRect);
+		}
+	if (brushRasterizer)
+		{
+		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+		}
+	iDevice->DrawingEnd(&iBrushBitmap);
+	if(iAutoUpdateJustification)
+		UpdateJustificationVertical(aText,aUp);
+	}
+
+// Transform a vector, defined by a point relative to an origin, from left-to-right to up or down.
+static void Rotate(TPoint& aPoint,const TPoint aOrigin,TBool aUp)
+	{
+	int dx = aPoint.iX - aOrigin.iX;
+	int dy = aPoint.iY - aOrigin.iY;
+	if (aUp)
+		{
+		aPoint.iX = aOrigin.iX + dy;
+		aPoint.iY = aOrigin.iY - dx;
+		}
+	else
+		{
+		aPoint.iX = aOrigin.iX - dy;
+		aPoint.iY = aOrigin.iY + dx;
+		}
+	}
+
+void CFbsBitGc::DoDrawTextVertical(CFont::TPositionParam& aParam,
+								   const CBitmapFont* font,
+								   TBool aUp,const TInt aEnd)
+	{
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	TInt charclipping=iClipRect.iTl.iY;
+	TPoint start_pen = aParam.iPen;
+	TInt underline_top = 0, underline_bottom = 0;
+	TInt underlineStrikeoutOffset;
+
+	//note using measured text here, but the full text string
+	underlineStrikeoutOffset= BaselineCorrection();
+
+	if (iUnderline == EUnderlineOn)
+		{
+		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
+		underline_top+=underlineStrikeoutOffset;
+		underline_bottom+=underlineStrikeoutOffset;
+		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
+		}
+
+	const TBool outlineAndShadow = (font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
+	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);
+		}
+
+	TInt strike_top = 0, strike_bottom = 0;
+	TBool italic = font->iAlgStyle.IsItalic();
+	if (italic || iStrikethrough == EStrikethroughOn)
+		{
+		GetStrikethroughMetrics(strike_top,strike_bottom);
+		if (iStrikethrough == EStrikethroughOn) //not for italic only, mimimum change
+			{
+			strike_top+=underlineStrikeoutOffset;
+			strike_bottom+=underlineStrikeoutOffset;
+			}
+		}
+	TInt italicheight=start_pen.iX;
+	italicheight += aUp ? -strike_top : strike_top;
+	TBool bold = font->iAlgStyle.IsBold();
+	TInt widthfactor = font->iAlgStyle.WidthFactor();
+	TInt heightfactor = font->iAlgStyle.HeightFactor();
+	TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
+	TBool outlineShadowOrAntialiased = (glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap || 
+			glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap);
+
+	RShapeInfo shapeInfo;
+	while (aParam.iPosInText < aEnd)
+		{
+		TPoint start_pen = aParam.iPen;
+	
+		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
+			continue;
+		Rotate(aParam.iPen,start_pen,aUp);
+		TInt adjustment = 0;
+		if(iCharJustExcess && iCharJustNum>0) // character clipping/justification
+			{
+			adjustment=CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
+			if (adjustment < 0)
+				iClipRect.iTl.iY = aParam.iPen.iY + (aUp ? -adjustment : adjustment);
+			}
+
+		
+		
+		CFont::TPositionParam::TOutput* output = aParam.iOutput;
+		
+		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+			{			
+			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();
+			
+			Rotate(output->iBounds.iTl,start_pen,aUp);
+			Rotate(output->iBounds.iBr,start_pen,aUp);
+			
+			switch (glyphType)
+				{
+				//the glyphType from the character takes precidence over the glyphType from the fon
+				case EAntiAliasedGlyphBitmap:
+				case EFourColourBlendGlyphBitmap:
+					DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphType);
+					break;
+
+				case EDefaultGlyphBitmap:
+				case EMonochromeGlyphBitmap:
+					DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
+							bold,italic,italicheight,widthfactor,heightfactor,aUp);
+					break;
+
+				default:
+					//if the outline or shadow is not specified for the character, then use the font setting
+					if (outlineShadowOrAntialiased)
+						{
+						DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphBitmapTypeForFont);		
+						}
+					else
+						{
+						DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
+								bold,italic,italicheight,widthfactor,heightfactor,aUp);
+						}			 
+					break;
+				} 
+			}
+
+		iClipRect.iTl.iY = charclipping;
+		if (adjustment)
+			aParam.iPen.iY += aUp ? -adjustment : adjustment;
+		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
+			{
+			adjustment=CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
+			aParam.iPen.iY += aUp ? -adjustment : adjustment;
+			}
+		}
+	if (shapeInfo.IsOpen())
+		shapeInfo.Close();
+	if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
+		{
+		TRect ul; // underline
+		TRect st; // strikethrough
+		if (aUp)
+			{
+			ul.SetRect(start_pen.iX+underline_top,aParam.iPen.iY,start_pen.iX+underline_bottom,start_pen.iY+1);
+			st.SetRect(start_pen.iX+strike_top,aParam.iPen.iY,start_pen.iX+strike_bottom,start_pen.iY+1);
+			ul.iTl.iY= ul.iBr.iY-ul.Height()*widthfactor;
+ 			st.iTl.iY= st.iBr.iY-st.Height()*widthfactor;
+			}
+		else
+			{
+			ul.SetRect(start_pen.iX-underline_bottom,start_pen.iY,start_pen.iX-underline_top,aParam.iPen.iY);
+			st.SetRect(start_pen.iX-strike_bottom,start_pen.iY,start_pen.iX-strike_top,aParam.iPen.iY);
+			ul.iBr.iY=ul.iTl.iY+ul.Height()*widthfactor;
+			st.iBr.iY=st.iTl.iY+st.Height()*widthfactor;
+			ul.iTl.iX++; // adjust for rect not including last line
+			ul.iBr.iX++;
+			st.iTl.iX++;
+			st.iBr.iX++;
+			}
+
+		if (iUnderline == EUnderlineOn)
+			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)
+			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::DoDrawCharacterVertical(const TPoint& aTopLeft,
+										const TSize& aDataSize,
+										const TUint8* aData,
+										TBool aBold,
+										TBool aItalic,
+										TInt aItalicPos,
+										TInt aWidthFactor,
+										TInt aHeightFactor,
+										TBool aUp)
+	{
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	TPoint printpos(aTopLeft);
+	TInt datalength = aDataSize.iWidth;
+	TInt dataheight = aDataSize.iHeight;
+	TInt bitindex=0;
+	TInt16 repeatcount=0;
+	TInt xinc=aUp?1:-1,yinc=aUp?-1:1;
+	TUint32* slbuffer=drawDevice->ScanLineBuffer();
+	TInt slwords=(drawDevice->ScanLineBytes())<<3;
+	if(aItalic && aTopLeft.iY<aItalicPos)
+		printpos.iY+=yinc;
+	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;
+		TInt signedrepeatcount=aUp?repeatcount:-repeatcount;
+		if(multilineflag)
+			{
+			for(TInt currentline=0;currentline<repeatcount;currentline++)
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+				OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
+				bitindex+=datalength;
+				TBool aboveitalicjump=EFalse;
+				if(aItalic && ((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos)))
+					aboveitalicjump=ETrue;
+				printpos.iX+=xinc*aHeightFactor;
+				if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
+					printpos.iY-=yinc*aWidthFactor;
+				}
+			}
+		else
+			{
+			if(aItalic)
+				{
+				for(TInt currentline=0;currentline<repeatcount;currentline++)
+					{
+					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+					OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
+					TBool aboveitalicjump=EFalse;
+					if((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos))
+						aboveitalicjump=ETrue;
+					printpos.iX+=xinc*aHeightFactor;
+					if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
+						printpos.iY-=yinc*aWidthFactor;
+					}
+				}
+			else
+				{
+				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+				OutputCharLineVertical(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor,aUp);
+				printpos.iX+=signedrepeatcount*aHeightFactor;
+				}
+			bitindex+=datalength;
+			}
+		}
+	}
+
+/** 
+@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 aUp the direction of the text
+@param aGlyphType the glyph type for the character
+*/
+void CFbsBitGc::DoDrawCharacterVerticalAntiAliased(const TPoint& aTopLeft,
+												   const TSize& aDataSize,
+												   const TUint8* aData,
+												   TBool aUp,
+												   TGlyphBitmapType aGlyphBitmapType)
+	{
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	const int KBufferSize = 32;
+	TUint8 mask_buffer[KBufferSize];
+	int top_row = 0;
+	int bottom_row = 0;
+	int left_col = 0;
+	int right_col = 0;
+	const TUint32 penColor = iPenColor.Internal();
+	const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
+	const TUint32 brushColor = iBrushColor.Internal();
+	
+	MOutlineAndShadowBlend* outlineAndShadow = NULL;
+	if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
+		{
+		TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
+		if(err != KErrNone)
+			{
+			// Assert if MOutlineAndShadowBlend interface is not implemented
+			BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
+			}
+		}
+	
+	if (aUp)
+		{
+		top_row = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
+		bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iX - aTopLeft.iX);
+		left_col = Max(0,aTopLeft.iY - iClipRect.iBr.iY + 1);
+		right_col = Min(aDataSize.iWidth,aTopLeft.iY - iClipRect.iTl.iY + 1);
+		int y = aTopLeft.iY - (right_col - 1);
+		for (int col = right_col - 1; col >= left_col; col--, y++)
+			{
+			int x = aTopLeft.iX + top_row;
+			for (int row = top_row; row < bottom_row; row += KBufferSize, x += KBufferSize)
+				{
+				int length = KBufferSize;
+				if (length > bottom_row - row)
+					length = bottom_row - row;
+				const TUint8* p = aData + row * aDataSize.iWidth + col;
+				for (int i = 0; i < length; i++, p += aDataSize.iWidth)
+					mask_buffer[i] = *p;
+				if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
+					{
+					//There is a support for the interface with KOutlineAndShadowInterface id.
+					outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, mask_buffer);
+					}
+				else
+					{
+					drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
+					}
+				}
+			}
+		}
+	else
+		{
+		top_row = Max(0,aTopLeft.iX - iClipRect.iBr.iX + 1);
+		bottom_row = Min(aDataSize.iHeight,aTopLeft.iX - iClipRect.iTl.iX + 1);
+		left_col = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
+		right_col = Min(aDataSize.iWidth,iClipRect.iBr.iY - aTopLeft.iY);
+		int y = aTopLeft.iY + left_col;
+		for (int col = left_col; col < right_col; col++, y++)
+			{
+			int x = aTopLeft.iX - (bottom_row - 1);
+			for (int row = bottom_row; row > top_row; row -= KBufferSize, x += KBufferSize)
+				{
+				int length = KBufferSize;
+				if (length > row - top_row)
+					length = row - top_row;
+				const TUint8* p = aData + (row - 1) * aDataSize.iWidth + col;
+				for (int i = 0; i < length; i++, p -= aDataSize.iWidth)
+					mask_buffer[i] = *p;
+				if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
+					{
+					//There is a support for the interface with KOutlineAndShadowInterface id.
+					outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, mask_buffer);
+					}
+				else
+					{
+					drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
+					}
+				}
+			}
+		}
+	}
+
+void CFbsBitGc::OutputCharLineVertical(TPoint aPrintPos,
+									   TUint32* aBuffer,
+									   TInt aDataLength,
+									   TInt aNum,
+									   TBool aBold,
+									   TInt aWidthFactor,
+									   TInt aHeightFactor,
+									   TBool aUp)
+	{
+	TInt xinc=aUp?1:-1;
+	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(aUp)
+		{
+		if(aPrintPos.iY>=iClipRect.iBr.iY)
+			{
+			TInt pixelexcess=aPrintPos.iY-iClipRect.iBr.iY+1;
+			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.iY=iClipRect.iBr.iY-1;
+			}
+		if(aPrintPos.iY-aDataLength<iClipRect.iTl.iY-1)
+			{
+			TInt pixelexcess=iClipRect.iTl.iY-1-aPrintPos.iY+aDataLength;
+			aDataLength-=pixelexcess;
+			if(aDataLength<=0) return;
+			}
+		}
+	else
+		{
+		if(aPrintPos.iY<iClipRect.iTl.iY)
+			{
+			TInt pixelexcess=iClipRect.iTl.iY-aPrintPos.iY;
+			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.iY=iClipRect.iTl.iY;
+			}
+		if(aPrintPos.iY+aDataLength>iClipRect.iBr.iY)
+			{
+			TInt pixelexcess=aPrintPos.iY+aDataLength-iClipRect.iBr.iY;
+			aDataLength-=pixelexcess;
+			if(aDataLength<=0) return;
+			}
+		}
+	aNum*=aHeightFactor;
+	while(aNum>0)
+		{
+		if(aPrintPos.iX>=iClipRect.iTl.iX && aPrintPos.iX<iClipRect.iBr.iX)
+			iDevice->iDrawDevice->WriteBinaryLineVertical(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode,aUp);
+		aPrintPos.iX+=xinc;
+		aNum--;
+		}
+	}
+
+
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,TBool aUp)
+	{
+	DrawTextVertical(aText,aParam,iLastPrintPosition,aUp);
+	}
+	
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TBool aUp)
+	{
+	TBrushStyle brushstyle=iBrushStyle;
+	iBrushStyle=CGraphicsContext::ENullBrush;
+	TOpenFontMetrics metrics;
+	iFont.GetFontMetrics(metrics);
+	TInt ascent = metrics.MaxHeight();
+	TInt height = ascent + metrics.MaxDepth();
+	// The next few lines do much the same as TextWidthInPixels but pass
+	// the text in visual order instead of logical order and also take
+	// full account of left and right side bearings on the text
+	CFont::TMeasureTextOutput output;
+	CFont::TMeasureTextInput input;
+	input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
+	if (aParam)
+		{
+		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
+		input.iStartInputChar = aParam->iStart;
+		input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
+		}
+	TInt advance = iFont.MeasureText(aText,&input,&output);
+	
+	//the box is not expanded by the underline position, as it is for horizontal text.
+	TInt leftBearing = output.iBounds.iTl.iX;
+	TInt rightBearing = advance - output.iBounds.iBr.iX;
+	TRect box;
+	TInt margin=0;
+	if(aUp)
+		{
+		box.iTl.iX=aPosition.iX-ascent;
+		box.iTl.iY=aPosition.iY-advance;
+		box.iBr.iX=aPosition.iX+height-ascent+1;
+		box.iBr.iY=aPosition.iY;
+		if(leftBearing<0)
+			{
+			box.iBr.iY-=leftBearing;
+			margin=-leftBearing;
+			}
+		if(rightBearing<0)
+			{
+			box.iTl.iY+=rightBearing;
+			}
+   		}
+	else
+		{
+		box.iTl.iX=aPosition.iX+ascent-height;
+		box.iTl.iY=aPosition.iY;
+		box.iBr.iX=aPosition.iX+ascent+1;
+		box.iBr.iY=aPosition.iY+advance;
+		if(leftBearing<0)
+			{
+			box.iTl.iY+=leftBearing;
+			margin=-leftBearing;
+			}
+		if(rightBearing<0)
+			{
+			box.iBr.iY-=rightBearing;
+			}
+		}
+	DrawTextVertical(aText,aParam,box,ascent,aUp,ELeft,margin);
+	iBrushStyle=brushstyle;
+	}
+	
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TBool aUp)
+	{
+	TRect boxcpy(aBox);
+	boxcpy.Move(iOrigin);
+	TRect oldcliprect(iUserClipRect);
+	iUserClipRect.Intersection(boxcpy);
+	DrawTextVertical(aText,aParam,aUp);
+	iUserClipRect=oldcliprect;
+	}
+	
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TBool aUp,TTextAlign aVert,TInt aMargin)
+	{
+	DrawTextVertical(aText,aParam,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
+	}
+
+EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt aTextWidth,TBool aUp,TTextAlign aVert,TInt aMargin)
+	{
+	CheckDevice();
+	BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
+	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+	TRect boxcpy(aBox);
+	boxcpy.Move(iOrigin);
+	AddRect(boxcpy);
+	if (boxcpy.Intersects(iUserClipRect))
+		{
+		boxcpy.Intersection(iUserClipRect);
+		}
+	SetupDevice();
+	iDevice->DrawingBegin(&iBrushBitmap);
+	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+	const CBitmapFont* fontaddress=iFont.Address();
+	if(!fontaddress)
+		{
+		if (brushRasterizer)
+			{
+			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+			}
+		iDevice->DrawingEnd(&iBrushBitmap);
+		BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
+		}
+	CFont::TMeasureTextInput input;
+	//CFont::TMeasureTextOutput
+	if (aParam)
+		{
+		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
+		input.iStartInputChar = aParam->iStart;
+		input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
+		}
+	TInt width = iFont.MeasureText(aText,&input);
+	TOpenFontMetrics metrics;
+	iFont.GetFontMetrics(metrics);
+	TInt textlength=aText.Length();
+	if(aTextWidth<0) aTextWidth=width;
+	TPoint coords;
+	coords.iX=aBox.iTl.iX;
+	TInt dirmult=aUp?-1:1;
+	coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
+	//
+	// iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
+	// pre: iX = 0
+	//
+	// hhhhhhhhhhhhhhhhhhhh
+	// 01234567890123456789
+	// aaaaaaaaaaaaaaaaaadd	aUp=ETrue
+	//                   ^
+	//                   iX = 18 (baseline)
+	//
+	// ddaaaaaaaaaaaaaaaaaa aUp=EFalse
+	//  ^
+	//  iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
+	//
+	coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
+	switch(aVert)
+		{
+	case ELeft:
+		coords.iY+=aMargin*dirmult;
+		break;
+	case ECenter:
+		coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
+		break;
+	case ERight:
+		coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
+		break;
+		}
+	iLastPrintPosition=coords;
+	coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
+	coords+=iOrigin;
+	TInt prewidth=width+iCharJustExcess+iWordJustExcess;
+	iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
+	if(boxcpy.IsEmpty())
+		{
+		if (brushRasterizer)
+			{
+			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+			}
+		iDevice->DrawingEnd(&iBrushBitmap);
+		if (iAutoUpdateJustification)
+			UpdateJustificationVertical(aText,aParam,aUp);
+		return;
+		}
+	RectFill(boxcpy);
+	TBool userintersect=boxcpy.Intersects(iUserClipRect);
+	if(!userintersect || !textlength || !width)
+		{
+		if (brushRasterizer)
+			{
+			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+			}
+		iDevice->DrawingEnd(&iBrushBitmap);
+		if (iAutoUpdateJustification)
+			UpdateJustificationVertical(aText,aParam,aUp);
+		return;
+		}
+	boxcpy.Intersection(iUserClipRect);
+	TInt charjustexcess=iCharJustExcess;
+	TInt charjustnum=iCharJustNum;
+	TInt wordjustexcess=iWordJustExcess;
+	TInt wordjustnum=iWordJustNum;
+	TInt limit=iDefaultRegionPtr->Count();
+	for(TInt count=0;count<limit;count++)
+		{
+		/*
+		Initialise the justification parameters to the original values at the start of each pass.
+		This means that any number of passes have exactly the same effect on the parameters as one pass;
+		that is, to reduce them by the numbers of items and pixels consumed.
+		*/
+		iCharJustExcess = charjustexcess;
+		iCharJustNum = charjustnum;
+		iWordJustExcess = wordjustexcess;
+		iWordJustNum = wordjustnum;
+
+		iClipRect=(*iDefaultRegionPtr)[count];
+		if(!iClipRect.Intersects(boxcpy))
+			continue;
+#if defined(_DEBUG)
+		TRect deviceRect;
+		drawDevice->GetDrawRect(deviceRect);
+		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(boxcpy);
+		/*
+		Set up the parameter block for character positioning.
+		Draw left to right, because although the text is being drawn vertically,
+		it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
+		the characters in their normal orientation but in a vertical column.
+		*/
+		CFont::TPositionParam param;
+		param.iText.Set(aText);
+		param.iPen = coords;
+		TInt endDraw = aText.Length();
+		if (aParam)
+			{
+			param.iPosInText = aParam->iStart;
+			endDraw = Min(aText.Length(),aParam->iEnd);
+			}
+		else
+			param.iPosInText = 0;
+
+		// Draw the text.
+		DoDrawTextVertical(param,fontaddress,aUp,endDraw);
+
+		drawDevice->UpdateRegion(iClipRect);
+		}
+	if (brushRasterizer)
+		{
+		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+		}
+	iDevice->DrawingEnd(&iBrushBitmap);
+	if(iAutoUpdateJustification)
+		UpdateJustificationVertical(aText,aParam,aUp);
+	}