graphicsdeviceinterface/bitgdi/sbit/VERTEXT.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 <graphics/fbsrasterizer.h>
       
    23 
       
    24 #include <bmalphablend.h>
       
    25 #include <bitdrawinterfaceid.h>
       
    26 #include "bitgcextradata.h"
       
    27 
       
    28 /** Draws text at the last print position and then rotates it into a vertical position.
       
    29 
       
    30 @param aText The text string to be drawn.
       
    31 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
       
    32 rotated 90 degrees clockwise. */
       
    33 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,TBool aUp)
       
    34 	{
       
    35 	DrawTextVertical(aText,iLastPrintPosition,aUp);
       
    36 	}
       
    37 
       
    38 /** Draws text vertically from the specified position.
       
    39 
       
    40 @param aText The text string to be drawn.
       
    41 @param aPosition A point specifying the position of the left end of the text.
       
    42 @param aUp  ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text 
       
    43 is rotated 90 degrees clockwise. */
       
    44 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TPoint& aPosition,TBool aUp)
       
    45 	{
       
    46 	TBrushStyle brushstyle=iBrushStyle;
       
    47 	iBrushStyle=CGraphicsContext::ENullBrush;
       
    48 	TOpenFontMetrics metrics;
       
    49 	iFont.GetFontMetrics(metrics);
       
    50 	TInt ascent = metrics.MaxHeight();
       
    51 	TInt height = ascent + metrics.MaxDepth();
       
    52 	// The next few lines do much the same as TextWidthInPixels but pass
       
    53 	// the text in visual order instead of logical order and also take
       
    54 	// full account of left and right side bearings on the text
       
    55 	CFont::TMeasureTextOutput output;
       
    56 	CFont::TMeasureTextInput input;
       
    57 	input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
       
    58 	TInt advance = iFont.MeasureText(aText,&input,&output);
       
    59 	
       
    60 	/* expand the clipping rectangle to take account of any underline */
       
    61 	if (iUnderline == EUnderlineOn)
       
    62 		{
       
    63 		TInt underline_top = 0, underline_bottom = 0;
       
    64 		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
       
    65 		TInt underlineStrikeoutOffset;
       
    66 		underlineStrikeoutOffset= BaselineCorrection();
       
    67 		underline_top+=underlineStrikeoutOffset;
       
    68 		underline_bottom+=underlineStrikeoutOffset;
       
    69 		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
       
    70 		output.iBounds.iTl.iY = Min(output.iBounds.iTl.iY,underline_top);
       
    71 		output.iBounds.iBr.iY = Max(output.iBounds.iBr.iY,underline_bottom);
       
    72 		}
       
    73 
       
    74 	TInt leftBearing = output.iBounds.iTl.iX;
       
    75 	TInt rightBearing = advance - output.iBounds.iBr.iX;
       
    76 	TRect box;
       
    77 	TInt margin=0;
       
    78 	if(aUp)
       
    79 		{
       
    80 		box.iTl.iX=aPosition.iX-ascent;
       
    81 		box.iTl.iY=aPosition.iY-advance;
       
    82 		box.iBr.iX=aPosition.iX+output.iBounds.iBr.iY+1;//was +height-ascent+1;
       
    83 		box.iBr.iY=aPosition.iY;
       
    84 		if(leftBearing<0)
       
    85 			{
       
    86 			box.iBr.iY-=leftBearing;
       
    87 			margin=-leftBearing;
       
    88 			}
       
    89 		if(rightBearing<0)
       
    90 			{
       
    91 			box.iTl.iY+=rightBearing;
       
    92 			}
       
    93    		}
       
    94 	else
       
    95 		{
       
    96 		box.iTl.iX=aPosition.iX-output.iBounds.iBr.iY;//was +ascent-height;
       
    97 		box.iTl.iY=aPosition.iY;
       
    98 		box.iBr.iX=aPosition.iX+ascent+1;
       
    99 		box.iBr.iY=aPosition.iY+advance;
       
   100 		if(leftBearing<0)
       
   101 			{
       
   102 			box.iTl.iY+=leftBearing;
       
   103 			margin=-leftBearing;
       
   104 			}
       
   105 		if(rightBearing<0)
       
   106 			{
       
   107 			box.iBr.iY-=rightBearing;
       
   108 			}
       
   109 		}
       
   110 	DrawTextVertical(aText,box,ascent,aUp,ELeft,margin);
       
   111 	iBrushStyle=brushstyle;
       
   112 	}
       
   113 
       
   114 
       
   115 /** Draws text clipped to the specified rectangle and then rotates it into a vertical 
       
   116 position.
       
   117 
       
   118 @param aText The text string to be drawn 
       
   119 @param aBox The clipping rectangle.
       
   120 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
       
   121 rotated 90 degrees clockwise. */
       
   122 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TRect& aBox,TBool aUp)
       
   123 	{
       
   124 	TRect boxcpy(aBox);
       
   125 	boxcpy.Move(iOrigin);
       
   126 	TRect oldcliprect(iUserClipRect);
       
   127 	iUserClipRect.Intersection(boxcpy);
       
   128 	DrawTextVertical(aText,aUp);
       
   129 	iUserClipRect=oldcliprect;
       
   130 	}
       
   131 
       
   132 
       
   133 /** Draws text vertically, clipped to a specified rectangle,
       
   134 using a baseline offset, alignment and margin.
       
   135 
       
   136 @param aText The text string to be drawn.
       
   137 @param aBox  A rectangle to clip the text to.
       
   138 @param aBaselineOffset Number of pixels to offset the baseline by.
       
   139 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
       
   140 rotated 90 degrees clockwise.
       
   141 @param aVert Verticaly alignment of the text relative to the specified 
       
   142 rectangle.
       
   143 @param aMargin Offset of the text from the position within the rectangle, 
       
   144 using the specified alignment. */
       
   145 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
       
   146 										  const TRect& aBox,
       
   147 										  TInt aBaselineOffset,
       
   148 										  TBool aUp,
       
   149 										  TTextAlign aVert,
       
   150 										  TInt aMargin)
       
   151     {
       
   152 	DrawTextVertical(aText,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
       
   153 	}
       
   154 
       
   155 
       
   156 /** Draws text vertically, clipped to a specified rectangle, using a baseline 
       
   157 offset, alignment and margin.
       
   158 
       
   159 @param aText The text string to be drawn.
       
   160 @param aBox A rectangle to clip the text to.
       
   161 @param aBaselineOffset Number of pixels to offset the baseline by.
       
   162 @param aTextWidth Number of pixels to clip the text to.
       
   163 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text 
       
   164 is rotated 90 degrees clockwise.
       
   165 @param aVert Verticaly alignment of the text relative to the specified 
       
   166 rectangle.
       
   167 @param aMargin Offset of the text from the position within the rectangle, 
       
   168 using the specified alignment. */	
       
   169 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
       
   170 										  const TRect& aBox,
       
   171 										  TInt aBaselineOffset,
       
   172 										  TInt aTextWidth,
       
   173 										  TBool aUp,
       
   174 										  TTextAlign aVert,
       
   175 										  TInt aMargin)
       
   176     {
       
   177 	CheckDevice();
       
   178 	BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
       
   179 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   180 	TRect boxcpy(aBox);
       
   181 	boxcpy.Move(iOrigin);
       
   182 	AddRect(boxcpy);
       
   183 	if (boxcpy.Intersects(iUserClipRect))
       
   184 		{
       
   185 		boxcpy.Intersection(iUserClipRect);
       
   186 		}
       
   187 	SetupDevice();
       
   188 	iDevice->DrawingBegin(&iBrushBitmap);
       
   189 	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
       
   190 	const CBitmapFont* fontaddress=iFont.Address();
       
   191 	if(!fontaddress)
       
   192 		{
       
   193 		if (brushRasterizer)
       
   194 			{
       
   195 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   196 			}
       
   197 		iDevice->DrawingEnd(&iBrushBitmap);
       
   198 		BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
       
   199 		}
       
   200 
       
   201 	TInt width = iFont.MeasureText(aText);
       
   202 	TOpenFontMetrics metrics;
       
   203 	iFont.GetFontMetrics(metrics);
       
   204 	TInt textlength=aText.Length();
       
   205 	if(aTextWidth<0) aTextWidth=width;
       
   206 	TPoint coords;
       
   207 	coords.iX=aBox.iTl.iX;
       
   208 	TInt dirmult=aUp?-1:1;
       
   209 	coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
       
   210 	//
       
   211 	// iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
       
   212 	// pre: iX = 0
       
   213 	//
       
   214 	// hhhhhhhhhhhhhhhhhhhh
       
   215 	// 01234567890123456789
       
   216 	// aaaaaaaaaaaaaaaaaadd	aUp=ETrue
       
   217 	//                   ^
       
   218 	//                   iX = 18 (baseline)
       
   219 	//
       
   220 	// ddaaaaaaaaaaaaaaaaaa aUp=EFalse
       
   221 	//  ^
       
   222 	//  iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
       
   223 	//
       
   224 	coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
       
   225 	switch(aVert)
       
   226 		{
       
   227 	case ELeft:
       
   228 		coords.iY+=aMargin*dirmult;
       
   229 		break;
       
   230 	case ECenter:
       
   231 		coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
       
   232 		break;
       
   233 	case ERight:
       
   234 		coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
       
   235 		break;
       
   236 		}
       
   237 	iLastPrintPosition=coords;
       
   238 	coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
       
   239 	coords+=iOrigin;
       
   240 	TInt prewidth=width+iCharJustExcess+iWordJustExcess;
       
   241 	iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
       
   242 	if(boxcpy.IsEmpty())
       
   243 		{
       
   244 		if (brushRasterizer)
       
   245 			{
       
   246 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   247 			}
       
   248 		iDevice->DrawingEnd(&iBrushBitmap);
       
   249 		if (iAutoUpdateJustification)
       
   250 			UpdateJustificationVertical(aText,aUp);
       
   251 		return;
       
   252 		}
       
   253 	RectFill(boxcpy);
       
   254 	TBool userintersect=boxcpy.Intersects(iUserClipRect);
       
   255 	if(!userintersect || !textlength || !width)
       
   256 		{
       
   257 		if (brushRasterizer)
       
   258 			{
       
   259 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   260 			}
       
   261 		iDevice->DrawingEnd(&iBrushBitmap);
       
   262 		if (iAutoUpdateJustification)
       
   263 			UpdateJustificationVertical(aText,aUp);
       
   264 		return;
       
   265 		}
       
   266 	boxcpy.Intersection(iUserClipRect);
       
   267 	TInt charjustexcess=iCharJustExcess;
       
   268 	TInt charjustnum=iCharJustNum;
       
   269 	TInt wordjustexcess=iWordJustExcess;
       
   270 	TInt wordjustnum=iWordJustNum;
       
   271 	TInt limit=iDefaultRegionPtr->Count();
       
   272 	for(TInt count=0;count<limit;count++)
       
   273 		{
       
   274 		/*
       
   275 		Initialise the justification parameters to the original values at the start of each pass.
       
   276 		This means that any number of passes have exactly the same effect on the parameters as one pass;
       
   277 		that is, to reduce them by the numbers of items and pixels consumed.
       
   278 		*/
       
   279 		iCharJustExcess = charjustexcess;
       
   280 		iCharJustNum = charjustnum;
       
   281 		iWordJustExcess = wordjustexcess;
       
   282 		iWordJustNum = wordjustnum;
       
   283 
       
   284 		iClipRect=(*iDefaultRegionPtr)[count];
       
   285 		if(!iClipRect.Intersects(boxcpy))
       
   286 			continue;
       
   287 #if defined(_DEBUG)
       
   288 		TRect deviceRect;
       
   289 		drawDevice->GetDrawRect(deviceRect);
       
   290 		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
       
   291 		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
       
   292 		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
       
   293 		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
       
   294 #endif
       
   295 		iClipRect.Intersection(boxcpy);
       
   296 		/*
       
   297 		Set up the parameter block for character positioning.
       
   298 		Draw left to right, because although the text is being drawn vertically,
       
   299 		it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
       
   300 		the characters in their normal orientation but in a vertical column.
       
   301 		*/
       
   302 		CFont::TPositionParam param;
       
   303 		param.iText.Set(aText);
       
   304 		param.iPen = coords;
       
   305 
       
   306 		// Draw the text.
       
   307 		DoDrawTextVertical(param,fontaddress,aUp,aText.Length());
       
   308 
       
   309 		drawDevice->UpdateRegion(iClipRect);
       
   310 		}
       
   311 	if (brushRasterizer)
       
   312 		{
       
   313 		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   314 		}
       
   315 	iDevice->DrawingEnd(&iBrushBitmap);
       
   316 	if(iAutoUpdateJustification)
       
   317 		UpdateJustificationVertical(aText,aUp);
       
   318 	}
       
   319 
       
   320 // Transform a vector, defined by a point relative to an origin, from left-to-right to up or down.
       
   321 static void Rotate(TPoint& aPoint,const TPoint aOrigin,TBool aUp)
       
   322 	{
       
   323 	int dx = aPoint.iX - aOrigin.iX;
       
   324 	int dy = aPoint.iY - aOrigin.iY;
       
   325 	if (aUp)
       
   326 		{
       
   327 		aPoint.iX = aOrigin.iX + dy;
       
   328 		aPoint.iY = aOrigin.iY - dx;
       
   329 		}
       
   330 	else
       
   331 		{
       
   332 		aPoint.iX = aOrigin.iX - dy;
       
   333 		aPoint.iY = aOrigin.iY + dx;
       
   334 		}
       
   335 	}
       
   336 
       
   337 void CFbsBitGc::DoDrawTextVertical(CFont::TPositionParam& aParam,
       
   338 								   const CBitmapFont* font,
       
   339 								   TBool aUp,const TInt aEnd)
       
   340 	{
       
   341 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   342 	TInt charclipping=iClipRect.iTl.iY;
       
   343 	TPoint start_pen = aParam.iPen;
       
   344 	TInt underline_top = 0, underline_bottom = 0;
       
   345 	TInt underlineStrikeoutOffset;
       
   346 
       
   347 	//note using measured text here, but the full text string
       
   348 	underlineStrikeoutOffset= BaselineCorrection();
       
   349 
       
   350 	if (iUnderline == EUnderlineOn)
       
   351 		{
       
   352 		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
       
   353 		underline_top+=underlineStrikeoutOffset;
       
   354 		underline_bottom+=underlineStrikeoutOffset;
       
   355 		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
       
   356 		}
       
   357 
       
   358 	const TBool outlineAndShadow = (font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
       
   359 	if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
       
   360 		{
       
   361 		//For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used 
       
   362 		//when drawing outline and shadow fonts.
       
   363 		BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
       
   364 		}
       
   365 
       
   366 	TInt strike_top = 0, strike_bottom = 0;
       
   367 	TBool italic = font->iAlgStyle.IsItalic();
       
   368 	if (italic || iStrikethrough == EStrikethroughOn)
       
   369 		{
       
   370 		GetStrikethroughMetrics(strike_top,strike_bottom);
       
   371 		if (iStrikethrough == EStrikethroughOn) //not for italic only, mimimum change
       
   372 			{
       
   373 			strike_top+=underlineStrikeoutOffset;
       
   374 			strike_bottom+=underlineStrikeoutOffset;
       
   375 			}
       
   376 		}
       
   377 	TInt italicheight=start_pen.iX;
       
   378 	italicheight += aUp ? -strike_top : strike_top;
       
   379 	TBool bold = font->iAlgStyle.IsBold();
       
   380 	TInt widthfactor = font->iAlgStyle.WidthFactor();
       
   381 	TInt heightfactor = font->iAlgStyle.HeightFactor();
       
   382 	TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
       
   383 	TBool outlineShadowOrAntialiased = (glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap || 
       
   384 			glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap);
       
   385 
       
   386 	RShapeInfo shapeInfo;
       
   387 	while (aParam.iPosInText < aEnd)
       
   388 		{
       
   389 		TPoint start_pen = aParam.iPen;
       
   390 	
       
   391 		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
       
   392 			continue;
       
   393 		Rotate(aParam.iPen,start_pen,aUp);
       
   394 		TInt adjustment = 0;
       
   395 		if(iCharJustExcess && iCharJustNum>0) // character clipping/justification
       
   396 			{
       
   397 			adjustment=CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
       
   398 			if (adjustment < 0)
       
   399 				iClipRect.iTl.iY = aParam.iPen.iY + (aUp ? -adjustment : adjustment);
       
   400 			}
       
   401 
       
   402 		
       
   403 		
       
   404 		CFont::TPositionParam::TOutput* output = aParam.iOutput;
       
   405 		
       
   406 		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
       
   407 			{			
       
   408 			TOpenFontCharMetrics characterParams;
       
   409 			const TUint8* bitmap;
       
   410 			TSize size;
       
   411 			//note may now be using a glyph code, and not a character
       
   412 			iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
       
   413 			TGlyphBitmapType glyphType = characterParams.GlyphType();
       
   414 			
       
   415 			Rotate(output->iBounds.iTl,start_pen,aUp);
       
   416 			Rotate(output->iBounds.iBr,start_pen,aUp);
       
   417 			
       
   418 			switch (glyphType)
       
   419 				{
       
   420 				//the glyphType from the character takes precidence over the glyphType from the fon
       
   421 				case EAntiAliasedGlyphBitmap:
       
   422 				case EFourColourBlendGlyphBitmap:
       
   423 					DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphType);
       
   424 					break;
       
   425 
       
   426 				case EDefaultGlyphBitmap:
       
   427 				case EMonochromeGlyphBitmap:
       
   428 					DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
       
   429 							bold,italic,italicheight,widthfactor,heightfactor,aUp);
       
   430 					break;
       
   431 
       
   432 				default:
       
   433 					//if the outline or shadow is not specified for the character, then use the font setting
       
   434 					if (outlineShadowOrAntialiased)
       
   435 						{
       
   436 						DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphBitmapTypeForFont);		
       
   437 						}
       
   438 					else
       
   439 						{
       
   440 						DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
       
   441 								bold,italic,italicheight,widthfactor,heightfactor,aUp);
       
   442 						}			 
       
   443 					break;
       
   444 				} 
       
   445 			}
       
   446 
       
   447 		iClipRect.iTl.iY = charclipping;
       
   448 		if (adjustment)
       
   449 			aParam.iPen.iY += aUp ? -adjustment : adjustment;
       
   450 		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
       
   451 			{
       
   452 			adjustment=CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
       
   453 			aParam.iPen.iY += aUp ? -adjustment : adjustment;
       
   454 			}
       
   455 		}
       
   456 	if (shapeInfo.IsOpen())
       
   457 		shapeInfo.Close();
       
   458 	if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
       
   459 		{
       
   460 		TRect ul; // underline
       
   461 		TRect st; // strikethrough
       
   462 		if (aUp)
       
   463 			{
       
   464 			ul.SetRect(start_pen.iX+underline_top,aParam.iPen.iY,start_pen.iX+underline_bottom,start_pen.iY+1);
       
   465 			st.SetRect(start_pen.iX+strike_top,aParam.iPen.iY,start_pen.iX+strike_bottom,start_pen.iY+1);
       
   466 			ul.iTl.iY= ul.iBr.iY-ul.Height()*widthfactor;
       
   467  			st.iTl.iY= st.iBr.iY-st.Height()*widthfactor;
       
   468 			}
       
   469 		else
       
   470 			{
       
   471 			ul.SetRect(start_pen.iX-underline_bottom,start_pen.iY,start_pen.iX-underline_top,aParam.iPen.iY);
       
   472 			st.SetRect(start_pen.iX-strike_bottom,start_pen.iY,start_pen.iX-strike_top,aParam.iPen.iY);
       
   473 			ul.iBr.iY=ul.iTl.iY+ul.Height()*widthfactor;
       
   474 			st.iBr.iY=st.iTl.iY+st.Height()*widthfactor;
       
   475 			ul.iTl.iX++; // adjust for rect not including last line
       
   476 			ul.iBr.iX++;
       
   477 			st.iTl.iX++;
       
   478 			st.iBr.iX++;
       
   479 			}
       
   480 
       
   481 		if (iUnderline == EUnderlineOn)
       
   482 			if (ul.Intersects(iClipRect)) // checks for empty aRect as well
       
   483 				{
       
   484 				ul.Intersection(iClipRect);
       
   485 				drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
       
   486 				}
       
   487 
       
   488 		if (iStrikethrough == EStrikethroughOn)
       
   489 			if(st.Intersects(iClipRect)) // checks for empty aRect as well
       
   490 				{
       
   491 				st.Intersection(iClipRect);
       
   492 				drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
       
   493 				}
       
   494 		}
       
   495 	}
       
   496 
       
   497 void CFbsBitGc::DoDrawCharacterVertical(const TPoint& aTopLeft,
       
   498 										const TSize& aDataSize,
       
   499 										const TUint8* aData,
       
   500 										TBool aBold,
       
   501 										TBool aItalic,
       
   502 										TInt aItalicPos,
       
   503 										TInt aWidthFactor,
       
   504 										TInt aHeightFactor,
       
   505 										TBool aUp)
       
   506 	{
       
   507 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   508 	TPoint printpos(aTopLeft);
       
   509 	TInt datalength = aDataSize.iWidth;
       
   510 	TInt dataheight = aDataSize.iHeight;
       
   511 	TInt bitindex=0;
       
   512 	TInt16 repeatcount=0;
       
   513 	TInt xinc=aUp?1:-1,yinc=aUp?-1:1;
       
   514 	TUint32* slbuffer=drawDevice->ScanLineBuffer();
       
   515 	TInt slwords=(drawDevice->ScanLineBytes())<<3;
       
   516 	if(aItalic && aTopLeft.iY<aItalicPos)
       
   517 		printpos.iY+=yinc;
       
   518 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
       
   519 		{
       
   520 		repeatcount=Load16(aData+(bitindex>>3));
       
   521 		repeatcount>>=bitindex&7;
       
   522 		TInt multilineflag=repeatcount&1;
       
   523 		repeatcount>>=1;
       
   524 		repeatcount&=0xf;
       
   525 		bitindex+=5;
       
   526 		TInt signedrepeatcount=aUp?repeatcount:-repeatcount;
       
   527 		if(multilineflag)
       
   528 			{
       
   529 			for(TInt currentline=0;currentline<repeatcount;currentline++)
       
   530 				{
       
   531 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   532 				OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
       
   533 				bitindex+=datalength;
       
   534 				TBool aboveitalicjump=EFalse;
       
   535 				if(aItalic && ((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos)))
       
   536 					aboveitalicjump=ETrue;
       
   537 				printpos.iX+=xinc*aHeightFactor;
       
   538 				if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
       
   539 					printpos.iY-=yinc*aWidthFactor;
       
   540 				}
       
   541 			}
       
   542 		else
       
   543 			{
       
   544 			if(aItalic)
       
   545 				{
       
   546 				for(TInt currentline=0;currentline<repeatcount;currentline++)
       
   547 					{
       
   548 					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   549 					OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
       
   550 					TBool aboveitalicjump=EFalse;
       
   551 					if((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos))
       
   552 						aboveitalicjump=ETrue;
       
   553 					printpos.iX+=xinc*aHeightFactor;
       
   554 					if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
       
   555 						printpos.iY-=yinc*aWidthFactor;
       
   556 					}
       
   557 				}
       
   558 			else
       
   559 				{
       
   560 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
       
   561 				OutputCharLineVertical(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor,aUp);
       
   562 				printpos.iX+=signedrepeatcount*aHeightFactor;
       
   563 				}
       
   564 			bitindex+=datalength;
       
   565 			}
       
   566 		}
       
   567 	}
       
   568 
       
   569 /** 
       
   570 @internalTechnology
       
   571 
       
   572 This function draws an anti-aliased character.
       
   573 
       
   574 @param aTopLeft The position to output the character
       
   575 @param aDataSize The size of the bitmap
       
   576 @param aData the bitmap for outputt in their TOpenFontCharMetrics
       
   577 @param aUp the direction of the text
       
   578 @param aGlyphType the glyph type for the character
       
   579 */
       
   580 void CFbsBitGc::DoDrawCharacterVerticalAntiAliased(const TPoint& aTopLeft,
       
   581 												   const TSize& aDataSize,
       
   582 												   const TUint8* aData,
       
   583 												   TBool aUp,
       
   584 												   TGlyphBitmapType aGlyphBitmapType)
       
   585 	{
       
   586 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   587 	const int KBufferSize = 32;
       
   588 	TUint8 mask_buffer[KBufferSize];
       
   589 	int top_row = 0;
       
   590 	int bottom_row = 0;
       
   591 	int left_col = 0;
       
   592 	int right_col = 0;
       
   593 	const TUint32 penColor = iPenColor.Internal();
       
   594 	const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
       
   595 	const TUint32 brushColor = iBrushColor.Internal();
       
   596 	
       
   597 	MOutlineAndShadowBlend* outlineAndShadow = NULL;
       
   598 	if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
       
   599 		{
       
   600 		TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
       
   601 		if(err != KErrNone)
       
   602 			{
       
   603 			// Assert if MOutlineAndShadowBlend interface is not implemented
       
   604 			BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
       
   605 			}
       
   606 		}
       
   607 	
       
   608 	if (aUp)
       
   609 		{
       
   610 		top_row = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
       
   611 		bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iX - aTopLeft.iX);
       
   612 		left_col = Max(0,aTopLeft.iY - iClipRect.iBr.iY + 1);
       
   613 		right_col = Min(aDataSize.iWidth,aTopLeft.iY - iClipRect.iTl.iY + 1);
       
   614 		int y = aTopLeft.iY - (right_col - 1);
       
   615 		for (int col = right_col - 1; col >= left_col; col--, y++)
       
   616 			{
       
   617 			int x = aTopLeft.iX + top_row;
       
   618 			for (int row = top_row; row < bottom_row; row += KBufferSize, x += KBufferSize)
       
   619 				{
       
   620 				int length = KBufferSize;
       
   621 				if (length > bottom_row - row)
       
   622 					length = bottom_row - row;
       
   623 				const TUint8* p = aData + row * aDataSize.iWidth + col;
       
   624 				for (int i = 0; i < length; i++, p += aDataSize.iWidth)
       
   625 					mask_buffer[i] = *p;
       
   626 				if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
       
   627 					{
       
   628 					//There is a support for the interface with KOutlineAndShadowInterface id.
       
   629 					outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, mask_buffer);
       
   630 					}
       
   631 				else
       
   632 					{
       
   633 					drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
       
   634 					}
       
   635 				}
       
   636 			}
       
   637 		}
       
   638 	else
       
   639 		{
       
   640 		top_row = Max(0,aTopLeft.iX - iClipRect.iBr.iX + 1);
       
   641 		bottom_row = Min(aDataSize.iHeight,aTopLeft.iX - iClipRect.iTl.iX + 1);
       
   642 		left_col = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
       
   643 		right_col = Min(aDataSize.iWidth,iClipRect.iBr.iY - aTopLeft.iY);
       
   644 		int y = aTopLeft.iY + left_col;
       
   645 		for (int col = left_col; col < right_col; col++, y++)
       
   646 			{
       
   647 			int x = aTopLeft.iX - (bottom_row - 1);
       
   648 			for (int row = bottom_row; row > top_row; row -= KBufferSize, x += KBufferSize)
       
   649 				{
       
   650 				int length = KBufferSize;
       
   651 				if (length > row - top_row)
       
   652 					length = row - top_row;
       
   653 				const TUint8* p = aData + (row - 1) * aDataSize.iWidth + col;
       
   654 				for (int i = 0; i < length; i++, p -= aDataSize.iWidth)
       
   655 					mask_buffer[i] = *p;
       
   656 				if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
       
   657 					{
       
   658 					//There is a support for the interface with KOutlineAndShadowInterface id.
       
   659 					outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, mask_buffer);
       
   660 					}
       
   661 				else
       
   662 					{
       
   663 					drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
       
   664 					}
       
   665 				}
       
   666 			}
       
   667 		}
       
   668 	}
       
   669 
       
   670 void CFbsBitGc::OutputCharLineVertical(TPoint aPrintPos,
       
   671 									   TUint32* aBuffer,
       
   672 									   TInt aDataLength,
       
   673 									   TInt aNum,
       
   674 									   TBool aBold,
       
   675 									   TInt aWidthFactor,
       
   676 									   TInt aHeightFactor,
       
   677 									   TBool aUp)
       
   678 	{
       
   679 	TInt xinc=aUp?1:-1;
       
   680 	if(aDataLength<=0) return;
       
   681 	TInt bufferwords=(aDataLength+31)>>5;
       
   682 	TUint32* bufferlimit=aBuffer+bufferwords;
       
   683 	if(aBold)
       
   684 		{
       
   685 		TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
       
   686 		if((aDataLength&0x1f)==0) sparemask=0xffffffff;
       
   687 		*(bufferlimit-1)&=sparemask;
       
   688 		TUint32* bufferptr=aBuffer;
       
   689 		TUint32 extrabit=0;
       
   690 		while(bufferptr<bufferlimit)
       
   691 			{
       
   692 			extrabit=*bufferptr>>31;
       
   693 			*bufferptr|=(*bufferptr<<1);
       
   694 			++bufferptr;
       
   695 			if(bufferptr<bufferlimit)
       
   696 				*bufferptr|=extrabit;
       
   697 			}
       
   698 		aDataLength++;
       
   699 		if((aDataLength&0x1f)==1)
       
   700 			{
       
   701 			bufferwords++;
       
   702 			*bufferlimit=extrabit;
       
   703 			bufferlimit++;
       
   704 			}
       
   705 		}
       
   706 	if(aWidthFactor>1)
       
   707 		{
       
   708 		BitMultiply(aBuffer,aDataLength,aWidthFactor);
       
   709 		aDataLength*=aWidthFactor;
       
   710 		bufferwords=(aDataLength+31)>>5;
       
   711 		bufferlimit=aBuffer+bufferwords;
       
   712 		}
       
   713 	if(aUp)
       
   714 		{
       
   715 		if(aPrintPos.iY>=iClipRect.iBr.iY)
       
   716 			{
       
   717 			TInt pixelexcess=aPrintPos.iY-iClipRect.iBr.iY+1;
       
   718 			while(pixelexcess>=32)
       
   719 				{
       
   720 				aBuffer++;
       
   721 				bufferwords--;
       
   722 				aDataLength-=32;
       
   723 				pixelexcess-=32;
       
   724 				}
       
   725 			if(aDataLength<=0) return;
       
   726 			if(pixelexcess>0)
       
   727 				{
       
   728 				TInt shiftup=32-pixelexcess;
       
   729 				TUint32* bufferptr=aBuffer;
       
   730 				while(bufferptr<bufferlimit)
       
   731 					{
       
   732 					*bufferptr>>=pixelexcess;
       
   733 					if(bufferptr<bufferlimit-1)
       
   734 						*bufferptr|=(*(bufferptr+1)<<shiftup);
       
   735 					bufferptr++;
       
   736 					}
       
   737 				aDataLength-=pixelexcess;
       
   738 				if(aDataLength<=0) return;
       
   739 				}
       
   740 			aPrintPos.iY=iClipRect.iBr.iY-1;
       
   741 			}
       
   742 		if(aPrintPos.iY-aDataLength<iClipRect.iTl.iY-1)
       
   743 			{
       
   744 			TInt pixelexcess=iClipRect.iTl.iY-1-aPrintPos.iY+aDataLength;
       
   745 			aDataLength-=pixelexcess;
       
   746 			if(aDataLength<=0) return;
       
   747 			}
       
   748 		}
       
   749 	else
       
   750 		{
       
   751 		if(aPrintPos.iY<iClipRect.iTl.iY)
       
   752 			{
       
   753 			TInt pixelexcess=iClipRect.iTl.iY-aPrintPos.iY;
       
   754 			while(pixelexcess>=32)
       
   755 				{
       
   756 				aBuffer++;
       
   757 				bufferwords--;
       
   758 				aDataLength-=32;
       
   759 				pixelexcess-=32;
       
   760 				}
       
   761 			if(aDataLength<=0) return;
       
   762 			if(pixelexcess>0)
       
   763 				{
       
   764 				TInt shiftup=32-pixelexcess;
       
   765 				TUint32* bufferptr=aBuffer;
       
   766 				while(bufferptr<bufferlimit)
       
   767 					{
       
   768 					*bufferptr>>=pixelexcess;
       
   769 					if(bufferptr<bufferlimit-1)
       
   770 						*bufferptr|=(*(bufferptr+1)<<shiftup);
       
   771 					bufferptr++;
       
   772 					}
       
   773 				aDataLength-=pixelexcess;
       
   774 				if(aDataLength<=0) return;
       
   775 				}
       
   776 			aPrintPos.iY=iClipRect.iTl.iY;
       
   777 			}
       
   778 		if(aPrintPos.iY+aDataLength>iClipRect.iBr.iY)
       
   779 			{
       
   780 			TInt pixelexcess=aPrintPos.iY+aDataLength-iClipRect.iBr.iY;
       
   781 			aDataLength-=pixelexcess;
       
   782 			if(aDataLength<=0) return;
       
   783 			}
       
   784 		}
       
   785 	aNum*=aHeightFactor;
       
   786 	while(aNum>0)
       
   787 		{
       
   788 		if(aPrintPos.iX>=iClipRect.iTl.iX && aPrintPos.iX<iClipRect.iBr.iX)
       
   789 			iDevice->iDrawDevice->WriteBinaryLineVertical(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode,aUp);
       
   790 		aPrintPos.iX+=xinc;
       
   791 		aNum--;
       
   792 		}
       
   793 	}
       
   794 
       
   795 
       
   796 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,TBool aUp)
       
   797 	{
       
   798 	DrawTextVertical(aText,aParam,iLastPrintPosition,aUp);
       
   799 	}
       
   800 	
       
   801 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TBool aUp)
       
   802 	{
       
   803 	TBrushStyle brushstyle=iBrushStyle;
       
   804 	iBrushStyle=CGraphicsContext::ENullBrush;
       
   805 	TOpenFontMetrics metrics;
       
   806 	iFont.GetFontMetrics(metrics);
       
   807 	TInt ascent = metrics.MaxHeight();
       
   808 	TInt height = ascent + metrics.MaxDepth();
       
   809 	// The next few lines do much the same as TextWidthInPixels but pass
       
   810 	// the text in visual order instead of logical order and also take
       
   811 	// full account of left and right side bearings on the text
       
   812 	CFont::TMeasureTextOutput output;
       
   813 	CFont::TMeasureTextInput input;
       
   814 	input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
       
   815 	if (aParam)
       
   816 		{
       
   817 		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
       
   818 		input.iStartInputChar = aParam->iStart;
       
   819 		input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
       
   820 		}
       
   821 	TInt advance = iFont.MeasureText(aText,&input,&output);
       
   822 	
       
   823 	//the box is not expanded by the underline position, as it is for horizontal text.
       
   824 	TInt leftBearing = output.iBounds.iTl.iX;
       
   825 	TInt rightBearing = advance - output.iBounds.iBr.iX;
       
   826 	TRect box;
       
   827 	TInt margin=0;
       
   828 	if(aUp)
       
   829 		{
       
   830 		box.iTl.iX=aPosition.iX-ascent;
       
   831 		box.iTl.iY=aPosition.iY-advance;
       
   832 		box.iBr.iX=aPosition.iX+height-ascent+1;
       
   833 		box.iBr.iY=aPosition.iY;
       
   834 		if(leftBearing<0)
       
   835 			{
       
   836 			box.iBr.iY-=leftBearing;
       
   837 			margin=-leftBearing;
       
   838 			}
       
   839 		if(rightBearing<0)
       
   840 			{
       
   841 			box.iTl.iY+=rightBearing;
       
   842 			}
       
   843    		}
       
   844 	else
       
   845 		{
       
   846 		box.iTl.iX=aPosition.iX+ascent-height;
       
   847 		box.iTl.iY=aPosition.iY;
       
   848 		box.iBr.iX=aPosition.iX+ascent+1;
       
   849 		box.iBr.iY=aPosition.iY+advance;
       
   850 		if(leftBearing<0)
       
   851 			{
       
   852 			box.iTl.iY+=leftBearing;
       
   853 			margin=-leftBearing;
       
   854 			}
       
   855 		if(rightBearing<0)
       
   856 			{
       
   857 			box.iBr.iY-=rightBearing;
       
   858 			}
       
   859 		}
       
   860 	DrawTextVertical(aText,aParam,box,ascent,aUp,ELeft,margin);
       
   861 	iBrushStyle=brushstyle;
       
   862 	}
       
   863 	
       
   864 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TBool aUp)
       
   865 	{
       
   866 	TRect boxcpy(aBox);
       
   867 	boxcpy.Move(iOrigin);
       
   868 	TRect oldcliprect(iUserClipRect);
       
   869 	iUserClipRect.Intersection(boxcpy);
       
   870 	DrawTextVertical(aText,aParam,aUp);
       
   871 	iUserClipRect=oldcliprect;
       
   872 	}
       
   873 	
       
   874 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TBool aUp,TTextAlign aVert,TInt aMargin)
       
   875 	{
       
   876 	DrawTextVertical(aText,aParam,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
       
   877 	}
       
   878 
       
   879 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt aTextWidth,TBool aUp,TTextAlign aVert,TInt aMargin)
       
   880 	{
       
   881 	CheckDevice();
       
   882 	BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
       
   883 	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
       
   884 	TRect boxcpy(aBox);
       
   885 	boxcpy.Move(iOrigin);
       
   886 	AddRect(boxcpy);
       
   887 	if (boxcpy.Intersects(iUserClipRect))
       
   888 		{
       
   889 		boxcpy.Intersection(iUserClipRect);
       
   890 		}
       
   891 	SetupDevice();
       
   892 	iDevice->DrawingBegin(&iBrushBitmap);
       
   893 	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
       
   894 	const CBitmapFont* fontaddress=iFont.Address();
       
   895 	if(!fontaddress)
       
   896 		{
       
   897 		if (brushRasterizer)
       
   898 			{
       
   899 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   900 			}
       
   901 		iDevice->DrawingEnd(&iBrushBitmap);
       
   902 		BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
       
   903 		}
       
   904 	CFont::TMeasureTextInput input;
       
   905 	//CFont::TMeasureTextOutput
       
   906 	if (aParam)
       
   907 		{
       
   908 		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
       
   909 		input.iStartInputChar = aParam->iStart;
       
   910 		input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
       
   911 		}
       
   912 	TInt width = iFont.MeasureText(aText,&input);
       
   913 	TOpenFontMetrics metrics;
       
   914 	iFont.GetFontMetrics(metrics);
       
   915 	TInt textlength=aText.Length();
       
   916 	if(aTextWidth<0) aTextWidth=width;
       
   917 	TPoint coords;
       
   918 	coords.iX=aBox.iTl.iX;
       
   919 	TInt dirmult=aUp?-1:1;
       
   920 	coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
       
   921 	//
       
   922 	// iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
       
   923 	// pre: iX = 0
       
   924 	//
       
   925 	// hhhhhhhhhhhhhhhhhhhh
       
   926 	// 01234567890123456789
       
   927 	// aaaaaaaaaaaaaaaaaadd	aUp=ETrue
       
   928 	//                   ^
       
   929 	//                   iX = 18 (baseline)
       
   930 	//
       
   931 	// ddaaaaaaaaaaaaaaaaaa aUp=EFalse
       
   932 	//  ^
       
   933 	//  iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
       
   934 	//
       
   935 	coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
       
   936 	switch(aVert)
       
   937 		{
       
   938 	case ELeft:
       
   939 		coords.iY+=aMargin*dirmult;
       
   940 		break;
       
   941 	case ECenter:
       
   942 		coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
       
   943 		break;
       
   944 	case ERight:
       
   945 		coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
       
   946 		break;
       
   947 		}
       
   948 	iLastPrintPosition=coords;
       
   949 	coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
       
   950 	coords+=iOrigin;
       
   951 	TInt prewidth=width+iCharJustExcess+iWordJustExcess;
       
   952 	iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
       
   953 	if(boxcpy.IsEmpty())
       
   954 		{
       
   955 		if (brushRasterizer)
       
   956 			{
       
   957 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   958 			}
       
   959 		iDevice->DrawingEnd(&iBrushBitmap);
       
   960 		if (iAutoUpdateJustification)
       
   961 			UpdateJustificationVertical(aText,aParam,aUp);
       
   962 		return;
       
   963 		}
       
   964 	RectFill(boxcpy);
       
   965 	TBool userintersect=boxcpy.Intersects(iUserClipRect);
       
   966 	if(!userintersect || !textlength || !width)
       
   967 		{
       
   968 		if (brushRasterizer)
       
   969 			{
       
   970 			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
   971 			}
       
   972 		iDevice->DrawingEnd(&iBrushBitmap);
       
   973 		if (iAutoUpdateJustification)
       
   974 			UpdateJustificationVertical(aText,aParam,aUp);
       
   975 		return;
       
   976 		}
       
   977 	boxcpy.Intersection(iUserClipRect);
       
   978 	TInt charjustexcess=iCharJustExcess;
       
   979 	TInt charjustnum=iCharJustNum;
       
   980 	TInt wordjustexcess=iWordJustExcess;
       
   981 	TInt wordjustnum=iWordJustNum;
       
   982 	TInt limit=iDefaultRegionPtr->Count();
       
   983 	for(TInt count=0;count<limit;count++)
       
   984 		{
       
   985 		/*
       
   986 		Initialise the justification parameters to the original values at the start of each pass.
       
   987 		This means that any number of passes have exactly the same effect on the parameters as one pass;
       
   988 		that is, to reduce them by the numbers of items and pixels consumed.
       
   989 		*/
       
   990 		iCharJustExcess = charjustexcess;
       
   991 		iCharJustNum = charjustnum;
       
   992 		iWordJustExcess = wordjustexcess;
       
   993 		iWordJustNum = wordjustnum;
       
   994 
       
   995 		iClipRect=(*iDefaultRegionPtr)[count];
       
   996 		if(!iClipRect.Intersects(boxcpy))
       
   997 			continue;
       
   998 #if defined(_DEBUG)
       
   999 		TRect deviceRect;
       
  1000 		drawDevice->GetDrawRect(deviceRect);
       
  1001 		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
       
  1002 		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
       
  1003 		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
       
  1004 		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
       
  1005 #endif
       
  1006 		iClipRect.Intersection(boxcpy);
       
  1007 		/*
       
  1008 		Set up the parameter block for character positioning.
       
  1009 		Draw left to right, because although the text is being drawn vertically,
       
  1010 		it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
       
  1011 		the characters in their normal orientation but in a vertical column.
       
  1012 		*/
       
  1013 		CFont::TPositionParam param;
       
  1014 		param.iText.Set(aText);
       
  1015 		param.iPen = coords;
       
  1016 		TInt endDraw = aText.Length();
       
  1017 		if (aParam)
       
  1018 			{
       
  1019 			param.iPosInText = aParam->iStart;
       
  1020 			endDraw = Min(aText.Length(),aParam->iEnd);
       
  1021 			}
       
  1022 		else
       
  1023 			param.iPosInText = 0;
       
  1024 
       
  1025 		// Draw the text.
       
  1026 		DoDrawTextVertical(param,fontaddress,aUp,endDraw);
       
  1027 
       
  1028 		drawDevice->UpdateRegion(iClipRect);
       
  1029 		}
       
  1030 	if (brushRasterizer)
       
  1031 		{
       
  1032 		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
       
  1033 		}
       
  1034 	iDevice->DrawingEnd(&iBrushBitmap);
       
  1035 	if(iAutoUpdateJustification)
       
  1036 		UpdateJustificationVertical(aText,aParam,aUp);
       
  1037 	}