os/graphics/graphicsdeviceinterface/bitgdi/sbit/VERTEXT.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicsdeviceinterface/bitgdi/sbit/VERTEXT.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1037 @@
     1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <fntstore.h>
    1.20 +#include <bitdraw.h>
    1.21 +#include <bitstd.h>
    1.22 +#include <bitdev.h>
    1.23 +#include "BITPANIC.H"
    1.24 +#include <shapeinfo.h>
    1.25 +#include <graphics/fbsrasterizer.h>
    1.26 +
    1.27 +#include <bmalphablend.h>
    1.28 +#include <bitdrawinterfaceid.h>
    1.29 +#include "bitgcextradata.h"
    1.30 +
    1.31 +/** Draws text at the last print position and then rotates it into a vertical position.
    1.32 +
    1.33 +@param aText The text string to be drawn.
    1.34 +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
    1.35 +rotated 90 degrees clockwise. */
    1.36 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,TBool aUp)
    1.37 +	{
    1.38 +	DrawTextVertical(aText,iLastPrintPosition,aUp);
    1.39 +	}
    1.40 +
    1.41 +/** Draws text vertically from the specified position.
    1.42 +
    1.43 +@param aText The text string to be drawn.
    1.44 +@param aPosition A point specifying the position of the left end of the text.
    1.45 +@param aUp  ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text 
    1.46 +is rotated 90 degrees clockwise. */
    1.47 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TPoint& aPosition,TBool aUp)
    1.48 +	{
    1.49 +	TBrushStyle brushstyle=iBrushStyle;
    1.50 +	iBrushStyle=CGraphicsContext::ENullBrush;
    1.51 +	TOpenFontMetrics metrics;
    1.52 +	iFont.GetFontMetrics(metrics);
    1.53 +	TInt ascent = metrics.MaxHeight();
    1.54 +	TInt height = ascent + metrics.MaxDepth();
    1.55 +	// The next few lines do much the same as TextWidthInPixels but pass
    1.56 +	// the text in visual order instead of logical order and also take
    1.57 +	// full account of left and right side bearings on the text
    1.58 +	CFont::TMeasureTextOutput output;
    1.59 +	CFont::TMeasureTextInput input;
    1.60 +	input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
    1.61 +	TInt advance = iFont.MeasureText(aText,&input,&output);
    1.62 +	
    1.63 +	/* expand the clipping rectangle to take account of any underline */
    1.64 +	if (iUnderline == EUnderlineOn)
    1.65 +		{
    1.66 +		TInt underline_top = 0, underline_bottom = 0;
    1.67 +		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
    1.68 +		TInt underlineStrikeoutOffset;
    1.69 +		underlineStrikeoutOffset= BaselineCorrection();
    1.70 +		underline_top+=underlineStrikeoutOffset;
    1.71 +		underline_bottom+=underlineStrikeoutOffset;
    1.72 +		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
    1.73 +		output.iBounds.iTl.iY = Min(output.iBounds.iTl.iY,underline_top);
    1.74 +		output.iBounds.iBr.iY = Max(output.iBounds.iBr.iY,underline_bottom);
    1.75 +		}
    1.76 +
    1.77 +	TInt leftBearing = output.iBounds.iTl.iX;
    1.78 +	TInt rightBearing = advance - output.iBounds.iBr.iX;
    1.79 +	TRect box;
    1.80 +	TInt margin=0;
    1.81 +	if(aUp)
    1.82 +		{
    1.83 +		box.iTl.iX=aPosition.iX-ascent;
    1.84 +		box.iTl.iY=aPosition.iY-advance;
    1.85 +		box.iBr.iX=aPosition.iX+output.iBounds.iBr.iY+1;//was +height-ascent+1;
    1.86 +		box.iBr.iY=aPosition.iY;
    1.87 +		if(leftBearing<0)
    1.88 +			{
    1.89 +			box.iBr.iY-=leftBearing;
    1.90 +			margin=-leftBearing;
    1.91 +			}
    1.92 +		if(rightBearing<0)
    1.93 +			{
    1.94 +			box.iTl.iY+=rightBearing;
    1.95 +			}
    1.96 +   		}
    1.97 +	else
    1.98 +		{
    1.99 +		box.iTl.iX=aPosition.iX-output.iBounds.iBr.iY;//was +ascent-height;
   1.100 +		box.iTl.iY=aPosition.iY;
   1.101 +		box.iBr.iX=aPosition.iX+ascent+1;
   1.102 +		box.iBr.iY=aPosition.iY+advance;
   1.103 +		if(leftBearing<0)
   1.104 +			{
   1.105 +			box.iTl.iY+=leftBearing;
   1.106 +			margin=-leftBearing;
   1.107 +			}
   1.108 +		if(rightBearing<0)
   1.109 +			{
   1.110 +			box.iBr.iY-=rightBearing;
   1.111 +			}
   1.112 +		}
   1.113 +	DrawTextVertical(aText,box,ascent,aUp,ELeft,margin);
   1.114 +	iBrushStyle=brushstyle;
   1.115 +	}
   1.116 +
   1.117 +
   1.118 +/** Draws text clipped to the specified rectangle and then rotates it into a vertical 
   1.119 +position.
   1.120 +
   1.121 +@param aText The text string to be drawn 
   1.122 +@param aBox The clipping rectangle.
   1.123 +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
   1.124 +rotated 90 degrees clockwise. */
   1.125 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TRect& aBox,TBool aUp)
   1.126 +	{
   1.127 +	TRect boxcpy(aBox);
   1.128 +	boxcpy.Move(iOrigin);
   1.129 +	TRect oldcliprect(iUserClipRect);
   1.130 +	iUserClipRect.Intersection(boxcpy);
   1.131 +	DrawTextVertical(aText,aUp);
   1.132 +	iUserClipRect=oldcliprect;
   1.133 +	}
   1.134 +
   1.135 +
   1.136 +/** Draws text vertically, clipped to a specified rectangle,
   1.137 +using a baseline offset, alignment and margin.
   1.138 +
   1.139 +@param aText The text string to be drawn.
   1.140 +@param aBox  A rectangle to clip the text to.
   1.141 +@param aBaselineOffset Number of pixels to offset the baseline by.
   1.142 +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is 
   1.143 +rotated 90 degrees clockwise.
   1.144 +@param aVert Verticaly alignment of the text relative to the specified 
   1.145 +rectangle.
   1.146 +@param aMargin Offset of the text from the position within the rectangle, 
   1.147 +using the specified alignment. */
   1.148 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
   1.149 +										  const TRect& aBox,
   1.150 +										  TInt aBaselineOffset,
   1.151 +										  TBool aUp,
   1.152 +										  TTextAlign aVert,
   1.153 +										  TInt aMargin)
   1.154 +    {
   1.155 +	DrawTextVertical(aText,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
   1.156 +	}
   1.157 +
   1.158 +
   1.159 +/** Draws text vertically, clipped to a specified rectangle, using a baseline 
   1.160 +offset, alignment and margin.
   1.161 +
   1.162 +@param aText The text string to be drawn.
   1.163 +@param aBox A rectangle to clip the text to.
   1.164 +@param aBaselineOffset Number of pixels to offset the baseline by.
   1.165 +@param aTextWidth Number of pixels to clip the text to.
   1.166 +@param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text 
   1.167 +is rotated 90 degrees clockwise.
   1.168 +@param aVert Verticaly alignment of the text relative to the specified 
   1.169 +rectangle.
   1.170 +@param aMargin Offset of the text from the position within the rectangle, 
   1.171 +using the specified alignment. */	
   1.172 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
   1.173 +										  const TRect& aBox,
   1.174 +										  TInt aBaselineOffset,
   1.175 +										  TInt aTextWidth,
   1.176 +										  TBool aUp,
   1.177 +										  TTextAlign aVert,
   1.178 +										  TInt aMargin)
   1.179 +    {
   1.180 +	CheckDevice();
   1.181 +	BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
   1.182 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.183 +	TRect boxcpy(aBox);
   1.184 +	boxcpy.Move(iOrigin);
   1.185 +	AddRect(boxcpy);
   1.186 +	if (boxcpy.Intersects(iUserClipRect))
   1.187 +		{
   1.188 +		boxcpy.Intersection(iUserClipRect);
   1.189 +		}
   1.190 +	SetupDevice();
   1.191 +	iDevice->DrawingBegin(&iBrushBitmap);
   1.192 +	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
   1.193 +	const CBitmapFont* fontaddress=iFont.Address();
   1.194 +	if(!fontaddress)
   1.195 +		{
   1.196 +		if (brushRasterizer)
   1.197 +			{
   1.198 +			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.199 +			}
   1.200 +		iDevice->DrawingEnd(&iBrushBitmap);
   1.201 +		BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
   1.202 +		}
   1.203 +
   1.204 +	TInt width = iFont.MeasureText(aText);
   1.205 +	TOpenFontMetrics metrics;
   1.206 +	iFont.GetFontMetrics(metrics);
   1.207 +	TInt textlength=aText.Length();
   1.208 +	if(aTextWidth<0) aTextWidth=width;
   1.209 +	TPoint coords;
   1.210 +	coords.iX=aBox.iTl.iX;
   1.211 +	TInt dirmult=aUp?-1:1;
   1.212 +	coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
   1.213 +	//
   1.214 +	// iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
   1.215 +	// pre: iX = 0
   1.216 +	//
   1.217 +	// hhhhhhhhhhhhhhhhhhhh
   1.218 +	// 01234567890123456789
   1.219 +	// aaaaaaaaaaaaaaaaaadd	aUp=ETrue
   1.220 +	//                   ^
   1.221 +	//                   iX = 18 (baseline)
   1.222 +	//
   1.223 +	// ddaaaaaaaaaaaaaaaaaa aUp=EFalse
   1.224 +	//  ^
   1.225 +	//  iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
   1.226 +	//
   1.227 +	coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
   1.228 +	switch(aVert)
   1.229 +		{
   1.230 +	case ELeft:
   1.231 +		coords.iY+=aMargin*dirmult;
   1.232 +		break;
   1.233 +	case ECenter:
   1.234 +		coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
   1.235 +		break;
   1.236 +	case ERight:
   1.237 +		coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
   1.238 +		break;
   1.239 +		}
   1.240 +	iLastPrintPosition=coords;
   1.241 +	coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
   1.242 +	coords+=iOrigin;
   1.243 +	TInt prewidth=width+iCharJustExcess+iWordJustExcess;
   1.244 +	iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
   1.245 +	if(boxcpy.IsEmpty())
   1.246 +		{
   1.247 +		if (brushRasterizer)
   1.248 +			{
   1.249 +			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.250 +			}
   1.251 +		iDevice->DrawingEnd(&iBrushBitmap);
   1.252 +		if (iAutoUpdateJustification)
   1.253 +			UpdateJustificationVertical(aText,aUp);
   1.254 +		return;
   1.255 +		}
   1.256 +	RectFill(boxcpy);
   1.257 +	TBool userintersect=boxcpy.Intersects(iUserClipRect);
   1.258 +	if(!userintersect || !textlength || !width)
   1.259 +		{
   1.260 +		if (brushRasterizer)
   1.261 +			{
   1.262 +			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.263 +			}
   1.264 +		iDevice->DrawingEnd(&iBrushBitmap);
   1.265 +		if (iAutoUpdateJustification)
   1.266 +			UpdateJustificationVertical(aText,aUp);
   1.267 +		return;
   1.268 +		}
   1.269 +	boxcpy.Intersection(iUserClipRect);
   1.270 +	TInt charjustexcess=iCharJustExcess;
   1.271 +	TInt charjustnum=iCharJustNum;
   1.272 +	TInt wordjustexcess=iWordJustExcess;
   1.273 +	TInt wordjustnum=iWordJustNum;
   1.274 +	TInt limit=iDefaultRegionPtr->Count();
   1.275 +	for(TInt count=0;count<limit;count++)
   1.276 +		{
   1.277 +		/*
   1.278 +		Initialise the justification parameters to the original values at the start of each pass.
   1.279 +		This means that any number of passes have exactly the same effect on the parameters as one pass;
   1.280 +		that is, to reduce them by the numbers of items and pixels consumed.
   1.281 +		*/
   1.282 +		iCharJustExcess = charjustexcess;
   1.283 +		iCharJustNum = charjustnum;
   1.284 +		iWordJustExcess = wordjustexcess;
   1.285 +		iWordJustNum = wordjustnum;
   1.286 +
   1.287 +		iClipRect=(*iDefaultRegionPtr)[count];
   1.288 +		if(!iClipRect.Intersects(boxcpy))
   1.289 +			continue;
   1.290 +#if defined(_DEBUG)
   1.291 +		TRect deviceRect;
   1.292 +		drawDevice->GetDrawRect(deviceRect);
   1.293 +		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
   1.294 +		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
   1.295 +		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
   1.296 +		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
   1.297 +#endif
   1.298 +		iClipRect.Intersection(boxcpy);
   1.299 +		/*
   1.300 +		Set up the parameter block for character positioning.
   1.301 +		Draw left to right, because although the text is being drawn vertically,
   1.302 +		it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
   1.303 +		the characters in their normal orientation but in a vertical column.
   1.304 +		*/
   1.305 +		CFont::TPositionParam param;
   1.306 +		param.iText.Set(aText);
   1.307 +		param.iPen = coords;
   1.308 +
   1.309 +		// Draw the text.
   1.310 +		DoDrawTextVertical(param,fontaddress,aUp,aText.Length());
   1.311 +
   1.312 +		drawDevice->UpdateRegion(iClipRect);
   1.313 +		}
   1.314 +	if (brushRasterizer)
   1.315 +		{
   1.316 +		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.317 +		}
   1.318 +	iDevice->DrawingEnd(&iBrushBitmap);
   1.319 +	if(iAutoUpdateJustification)
   1.320 +		UpdateJustificationVertical(aText,aUp);
   1.321 +	}
   1.322 +
   1.323 +// Transform a vector, defined by a point relative to an origin, from left-to-right to up or down.
   1.324 +static void Rotate(TPoint& aPoint,const TPoint aOrigin,TBool aUp)
   1.325 +	{
   1.326 +	int dx = aPoint.iX - aOrigin.iX;
   1.327 +	int dy = aPoint.iY - aOrigin.iY;
   1.328 +	if (aUp)
   1.329 +		{
   1.330 +		aPoint.iX = aOrigin.iX + dy;
   1.331 +		aPoint.iY = aOrigin.iY - dx;
   1.332 +		}
   1.333 +	else
   1.334 +		{
   1.335 +		aPoint.iX = aOrigin.iX - dy;
   1.336 +		aPoint.iY = aOrigin.iY + dx;
   1.337 +		}
   1.338 +	}
   1.339 +
   1.340 +void CFbsBitGc::DoDrawTextVertical(CFont::TPositionParam& aParam,
   1.341 +								   const CBitmapFont* font,
   1.342 +								   TBool aUp,const TInt aEnd)
   1.343 +	{
   1.344 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.345 +	TInt charclipping=iClipRect.iTl.iY;
   1.346 +	TPoint start_pen = aParam.iPen;
   1.347 +	TInt underline_top = 0, underline_bottom = 0;
   1.348 +	TInt underlineStrikeoutOffset;
   1.349 +
   1.350 +	//note using measured text here, but the full text string
   1.351 +	underlineStrikeoutOffset= BaselineCorrection();
   1.352 +
   1.353 +	if (iUnderline == EUnderlineOn)
   1.354 +		{
   1.355 +		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
   1.356 +		underline_top+=underlineStrikeoutOffset;
   1.357 +		underline_bottom+=underlineStrikeoutOffset;
   1.358 +		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
   1.359 +		}
   1.360 +
   1.361 +	const TBool outlineAndShadow = (font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
   1.362 +	if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
   1.363 +		{
   1.364 +		//For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used 
   1.365 +		//when drawing outline and shadow fonts.
   1.366 +		BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
   1.367 +		}
   1.368 +
   1.369 +	TInt strike_top = 0, strike_bottom = 0;
   1.370 +	TBool italic = font->iAlgStyle.IsItalic();
   1.371 +	if (italic || iStrikethrough == EStrikethroughOn)
   1.372 +		{
   1.373 +		GetStrikethroughMetrics(strike_top,strike_bottom);
   1.374 +		if (iStrikethrough == EStrikethroughOn) //not for italic only, mimimum change
   1.375 +			{
   1.376 +			strike_top+=underlineStrikeoutOffset;
   1.377 +			strike_bottom+=underlineStrikeoutOffset;
   1.378 +			}
   1.379 +		}
   1.380 +	TInt italicheight=start_pen.iX;
   1.381 +	italicheight += aUp ? -strike_top : strike_top;
   1.382 +	TBool bold = font->iAlgStyle.IsBold();
   1.383 +	TInt widthfactor = font->iAlgStyle.WidthFactor();
   1.384 +	TInt heightfactor = font->iAlgStyle.HeightFactor();
   1.385 +	TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
   1.386 +	TBool outlineShadowOrAntialiased = (glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap || 
   1.387 +			glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap);
   1.388 +
   1.389 +	RShapeInfo shapeInfo;
   1.390 +	while (aParam.iPosInText < aEnd)
   1.391 +		{
   1.392 +		TPoint start_pen = aParam.iPen;
   1.393 +	
   1.394 +		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
   1.395 +			continue;
   1.396 +		Rotate(aParam.iPen,start_pen,aUp);
   1.397 +		TInt adjustment = 0;
   1.398 +		if(iCharJustExcess && iCharJustNum>0) // character clipping/justification
   1.399 +			{
   1.400 +			adjustment=CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
   1.401 +			if (adjustment < 0)
   1.402 +				iClipRect.iTl.iY = aParam.iPen.iY + (aUp ? -adjustment : adjustment);
   1.403 +			}
   1.404 +
   1.405 +		
   1.406 +		
   1.407 +		CFont::TPositionParam::TOutput* output = aParam.iOutput;
   1.408 +		
   1.409 +		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
   1.410 +			{			
   1.411 +			TOpenFontCharMetrics characterParams;
   1.412 +			const TUint8* bitmap;
   1.413 +			TSize size;
   1.414 +			//note may now be using a glyph code, and not a character
   1.415 +			iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
   1.416 +			TGlyphBitmapType glyphType = characterParams.GlyphType();
   1.417 +			
   1.418 +			Rotate(output->iBounds.iTl,start_pen,aUp);
   1.419 +			Rotate(output->iBounds.iBr,start_pen,aUp);
   1.420 +			
   1.421 +			switch (glyphType)
   1.422 +				{
   1.423 +				//the glyphType from the character takes precidence over the glyphType from the fon
   1.424 +				case EAntiAliasedGlyphBitmap:
   1.425 +				case EFourColourBlendGlyphBitmap:
   1.426 +					DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphType);
   1.427 +					break;
   1.428 +
   1.429 +				case EDefaultGlyphBitmap:
   1.430 +				case EMonochromeGlyphBitmap:
   1.431 +					DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
   1.432 +							bold,italic,italicheight,widthfactor,heightfactor,aUp);
   1.433 +					break;
   1.434 +
   1.435 +				default:
   1.436 +					//if the outline or shadow is not specified for the character, then use the font setting
   1.437 +					if (outlineShadowOrAntialiased)
   1.438 +						{
   1.439 +						DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphBitmapTypeForFont);		
   1.440 +						}
   1.441 +					else
   1.442 +						{
   1.443 +						DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
   1.444 +								bold,italic,italicheight,widthfactor,heightfactor,aUp);
   1.445 +						}			 
   1.446 +					break;
   1.447 +				} 
   1.448 +			}
   1.449 +
   1.450 +		iClipRect.iTl.iY = charclipping;
   1.451 +		if (adjustment)
   1.452 +			aParam.iPen.iY += aUp ? -adjustment : adjustment;
   1.453 +		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
   1.454 +			{
   1.455 +			adjustment=CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
   1.456 +			aParam.iPen.iY += aUp ? -adjustment : adjustment;
   1.457 +			}
   1.458 +		}
   1.459 +	if (shapeInfo.IsOpen())
   1.460 +		shapeInfo.Close();
   1.461 +	if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
   1.462 +		{
   1.463 +		TRect ul; // underline
   1.464 +		TRect st; // strikethrough
   1.465 +		if (aUp)
   1.466 +			{
   1.467 +			ul.SetRect(start_pen.iX+underline_top,aParam.iPen.iY,start_pen.iX+underline_bottom,start_pen.iY+1);
   1.468 +			st.SetRect(start_pen.iX+strike_top,aParam.iPen.iY,start_pen.iX+strike_bottom,start_pen.iY+1);
   1.469 +			ul.iTl.iY= ul.iBr.iY-ul.Height()*widthfactor;
   1.470 + 			st.iTl.iY= st.iBr.iY-st.Height()*widthfactor;
   1.471 +			}
   1.472 +		else
   1.473 +			{
   1.474 +			ul.SetRect(start_pen.iX-underline_bottom,start_pen.iY,start_pen.iX-underline_top,aParam.iPen.iY);
   1.475 +			st.SetRect(start_pen.iX-strike_bottom,start_pen.iY,start_pen.iX-strike_top,aParam.iPen.iY);
   1.476 +			ul.iBr.iY=ul.iTl.iY+ul.Height()*widthfactor;
   1.477 +			st.iBr.iY=st.iTl.iY+st.Height()*widthfactor;
   1.478 +			ul.iTl.iX++; // adjust for rect not including last line
   1.479 +			ul.iBr.iX++;
   1.480 +			st.iTl.iX++;
   1.481 +			st.iBr.iX++;
   1.482 +			}
   1.483 +
   1.484 +		if (iUnderline == EUnderlineOn)
   1.485 +			if (ul.Intersects(iClipRect)) // checks for empty aRect as well
   1.486 +				{
   1.487 +				ul.Intersection(iClipRect);
   1.488 +				drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
   1.489 +				}
   1.490 +
   1.491 +		if (iStrikethrough == EStrikethroughOn)
   1.492 +			if(st.Intersects(iClipRect)) // checks for empty aRect as well
   1.493 +				{
   1.494 +				st.Intersection(iClipRect);
   1.495 +				drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
   1.496 +				}
   1.497 +		}
   1.498 +	}
   1.499 +
   1.500 +void CFbsBitGc::DoDrawCharacterVertical(const TPoint& aTopLeft,
   1.501 +										const TSize& aDataSize,
   1.502 +										const TUint8* aData,
   1.503 +										TBool aBold,
   1.504 +										TBool aItalic,
   1.505 +										TInt aItalicPos,
   1.506 +										TInt aWidthFactor,
   1.507 +										TInt aHeightFactor,
   1.508 +										TBool aUp)
   1.509 +	{
   1.510 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.511 +	TPoint printpos(aTopLeft);
   1.512 +	TInt datalength = aDataSize.iWidth;
   1.513 +	TInt dataheight = aDataSize.iHeight;
   1.514 +	TInt bitindex=0;
   1.515 +	TInt16 repeatcount=0;
   1.516 +	TInt xinc=aUp?1:-1,yinc=aUp?-1:1;
   1.517 +	TUint32* slbuffer=drawDevice->ScanLineBuffer();
   1.518 +	TInt slwords=(drawDevice->ScanLineBytes())<<3;
   1.519 +	if(aItalic && aTopLeft.iY<aItalicPos)
   1.520 +		printpos.iY+=yinc;
   1.521 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   1.522 +		{
   1.523 +		repeatcount=Load16(aData+(bitindex>>3));
   1.524 +		repeatcount>>=bitindex&7;
   1.525 +		TInt multilineflag=repeatcount&1;
   1.526 +		repeatcount>>=1;
   1.527 +		repeatcount&=0xf;
   1.528 +		bitindex+=5;
   1.529 +		TInt signedrepeatcount=aUp?repeatcount:-repeatcount;
   1.530 +		if(multilineflag)
   1.531 +			{
   1.532 +			for(TInt currentline=0;currentline<repeatcount;currentline++)
   1.533 +				{
   1.534 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.535 +				OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
   1.536 +				bitindex+=datalength;
   1.537 +				TBool aboveitalicjump=EFalse;
   1.538 +				if(aItalic && ((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos)))
   1.539 +					aboveitalicjump=ETrue;
   1.540 +				printpos.iX+=xinc*aHeightFactor;
   1.541 +				if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
   1.542 +					printpos.iY-=yinc*aWidthFactor;
   1.543 +				}
   1.544 +			}
   1.545 +		else
   1.546 +			{
   1.547 +			if(aItalic)
   1.548 +				{
   1.549 +				for(TInt currentline=0;currentline<repeatcount;currentline++)
   1.550 +					{
   1.551 +					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.552 +					OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
   1.553 +					TBool aboveitalicjump=EFalse;
   1.554 +					if((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos))
   1.555 +						aboveitalicjump=ETrue;
   1.556 +					printpos.iX+=xinc*aHeightFactor;
   1.557 +					if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
   1.558 +						printpos.iY-=yinc*aWidthFactor;
   1.559 +					}
   1.560 +				}
   1.561 +			else
   1.562 +				{
   1.563 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.564 +				OutputCharLineVertical(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor,aUp);
   1.565 +				printpos.iX+=signedrepeatcount*aHeightFactor;
   1.566 +				}
   1.567 +			bitindex+=datalength;
   1.568 +			}
   1.569 +		}
   1.570 +	}
   1.571 +
   1.572 +/** 
   1.573 +@internalTechnology
   1.574 +
   1.575 +This function draws an anti-aliased character.
   1.576 +
   1.577 +@param aTopLeft The position to output the character
   1.578 +@param aDataSize The size of the bitmap
   1.579 +@param aData the bitmap for outputt in their TOpenFontCharMetrics
   1.580 +@param aUp the direction of the text
   1.581 +@param aGlyphType the glyph type for the character
   1.582 +*/
   1.583 +void CFbsBitGc::DoDrawCharacterVerticalAntiAliased(const TPoint& aTopLeft,
   1.584 +												   const TSize& aDataSize,
   1.585 +												   const TUint8* aData,
   1.586 +												   TBool aUp,
   1.587 +												   TGlyphBitmapType aGlyphBitmapType)
   1.588 +	{
   1.589 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.590 +	const int KBufferSize = 32;
   1.591 +	TUint8 mask_buffer[KBufferSize];
   1.592 +	int top_row = 0;
   1.593 +	int bottom_row = 0;
   1.594 +	int left_col = 0;
   1.595 +	int right_col = 0;
   1.596 +	const TUint32 penColor = iPenColor.Internal();
   1.597 +	const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
   1.598 +	const TUint32 brushColor = iBrushColor.Internal();
   1.599 +	
   1.600 +	MOutlineAndShadowBlend* outlineAndShadow = NULL;
   1.601 +	if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
   1.602 +		{
   1.603 +		TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
   1.604 +		if(err != KErrNone)
   1.605 +			{
   1.606 +			// Assert if MOutlineAndShadowBlend interface is not implemented
   1.607 +			BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
   1.608 +			}
   1.609 +		}
   1.610 +	
   1.611 +	if (aUp)
   1.612 +		{
   1.613 +		top_row = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
   1.614 +		bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iX - aTopLeft.iX);
   1.615 +		left_col = Max(0,aTopLeft.iY - iClipRect.iBr.iY + 1);
   1.616 +		right_col = Min(aDataSize.iWidth,aTopLeft.iY - iClipRect.iTl.iY + 1);
   1.617 +		int y = aTopLeft.iY - (right_col - 1);
   1.618 +		for (int col = right_col - 1; col >= left_col; col--, y++)
   1.619 +			{
   1.620 +			int x = aTopLeft.iX + top_row;
   1.621 +			for (int row = top_row; row < bottom_row; row += KBufferSize, x += KBufferSize)
   1.622 +				{
   1.623 +				int length = KBufferSize;
   1.624 +				if (length > bottom_row - row)
   1.625 +					length = bottom_row - row;
   1.626 +				const TUint8* p = aData + row * aDataSize.iWidth + col;
   1.627 +				for (int i = 0; i < length; i++, p += aDataSize.iWidth)
   1.628 +					mask_buffer[i] = *p;
   1.629 +				if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
   1.630 +					{
   1.631 +					//There is a support for the interface with KOutlineAndShadowInterface id.
   1.632 +					outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, mask_buffer);
   1.633 +					}
   1.634 +				else
   1.635 +					{
   1.636 +					drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
   1.637 +					}
   1.638 +				}
   1.639 +			}
   1.640 +		}
   1.641 +	else
   1.642 +		{
   1.643 +		top_row = Max(0,aTopLeft.iX - iClipRect.iBr.iX + 1);
   1.644 +		bottom_row = Min(aDataSize.iHeight,aTopLeft.iX - iClipRect.iTl.iX + 1);
   1.645 +		left_col = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
   1.646 +		right_col = Min(aDataSize.iWidth,iClipRect.iBr.iY - aTopLeft.iY);
   1.647 +		int y = aTopLeft.iY + left_col;
   1.648 +		for (int col = left_col; col < right_col; col++, y++)
   1.649 +			{
   1.650 +			int x = aTopLeft.iX - (bottom_row - 1);
   1.651 +			for (int row = bottom_row; row > top_row; row -= KBufferSize, x += KBufferSize)
   1.652 +				{
   1.653 +				int length = KBufferSize;
   1.654 +				if (length > row - top_row)
   1.655 +					length = row - top_row;
   1.656 +				const TUint8* p = aData + (row - 1) * aDataSize.iWidth + col;
   1.657 +				for (int i = 0; i < length; i++, p -= aDataSize.iWidth)
   1.658 +					mask_buffer[i] = *p;
   1.659 +				if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
   1.660 +					{
   1.661 +					//There is a support for the interface with KOutlineAndShadowInterface id.
   1.662 +					outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor,	brushColor, mask_buffer);
   1.663 +					}
   1.664 +				else
   1.665 +					{
   1.666 +					drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
   1.667 +					}
   1.668 +				}
   1.669 +			}
   1.670 +		}
   1.671 +	}
   1.672 +
   1.673 +void CFbsBitGc::OutputCharLineVertical(TPoint aPrintPos,
   1.674 +									   TUint32* aBuffer,
   1.675 +									   TInt aDataLength,
   1.676 +									   TInt aNum,
   1.677 +									   TBool aBold,
   1.678 +									   TInt aWidthFactor,
   1.679 +									   TInt aHeightFactor,
   1.680 +									   TBool aUp)
   1.681 +	{
   1.682 +	TInt xinc=aUp?1:-1;
   1.683 +	if(aDataLength<=0) return;
   1.684 +	TInt bufferwords=(aDataLength+31)>>5;
   1.685 +	TUint32* bufferlimit=aBuffer+bufferwords;
   1.686 +	if(aBold)
   1.687 +		{
   1.688 +		TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
   1.689 +		if((aDataLength&0x1f)==0) sparemask=0xffffffff;
   1.690 +		*(bufferlimit-1)&=sparemask;
   1.691 +		TUint32* bufferptr=aBuffer;
   1.692 +		TUint32 extrabit=0;
   1.693 +		while(bufferptr<bufferlimit)
   1.694 +			{
   1.695 +			extrabit=*bufferptr>>31;
   1.696 +			*bufferptr|=(*bufferptr<<1);
   1.697 +			++bufferptr;
   1.698 +			if(bufferptr<bufferlimit)
   1.699 +				*bufferptr|=extrabit;
   1.700 +			}
   1.701 +		aDataLength++;
   1.702 +		if((aDataLength&0x1f)==1)
   1.703 +			{
   1.704 +			bufferwords++;
   1.705 +			*bufferlimit=extrabit;
   1.706 +			bufferlimit++;
   1.707 +			}
   1.708 +		}
   1.709 +	if(aWidthFactor>1)
   1.710 +		{
   1.711 +		BitMultiply(aBuffer,aDataLength,aWidthFactor);
   1.712 +		aDataLength*=aWidthFactor;
   1.713 +		bufferwords=(aDataLength+31)>>5;
   1.714 +		bufferlimit=aBuffer+bufferwords;
   1.715 +		}
   1.716 +	if(aUp)
   1.717 +		{
   1.718 +		if(aPrintPos.iY>=iClipRect.iBr.iY)
   1.719 +			{
   1.720 +			TInt pixelexcess=aPrintPos.iY-iClipRect.iBr.iY+1;
   1.721 +			while(pixelexcess>=32)
   1.722 +				{
   1.723 +				aBuffer++;
   1.724 +				bufferwords--;
   1.725 +				aDataLength-=32;
   1.726 +				pixelexcess-=32;
   1.727 +				}
   1.728 +			if(aDataLength<=0) return;
   1.729 +			if(pixelexcess>0)
   1.730 +				{
   1.731 +				TInt shiftup=32-pixelexcess;
   1.732 +				TUint32* bufferptr=aBuffer;
   1.733 +				while(bufferptr<bufferlimit)
   1.734 +					{
   1.735 +					*bufferptr>>=pixelexcess;
   1.736 +					if(bufferptr<bufferlimit-1)
   1.737 +						*bufferptr|=(*(bufferptr+1)<<shiftup);
   1.738 +					bufferptr++;
   1.739 +					}
   1.740 +				aDataLength-=pixelexcess;
   1.741 +				if(aDataLength<=0) return;
   1.742 +				}
   1.743 +			aPrintPos.iY=iClipRect.iBr.iY-1;
   1.744 +			}
   1.745 +		if(aPrintPos.iY-aDataLength<iClipRect.iTl.iY-1)
   1.746 +			{
   1.747 +			TInt pixelexcess=iClipRect.iTl.iY-1-aPrintPos.iY+aDataLength;
   1.748 +			aDataLength-=pixelexcess;
   1.749 +			if(aDataLength<=0) return;
   1.750 +			}
   1.751 +		}
   1.752 +	else
   1.753 +		{
   1.754 +		if(aPrintPos.iY<iClipRect.iTl.iY)
   1.755 +			{
   1.756 +			TInt pixelexcess=iClipRect.iTl.iY-aPrintPos.iY;
   1.757 +			while(pixelexcess>=32)
   1.758 +				{
   1.759 +				aBuffer++;
   1.760 +				bufferwords--;
   1.761 +				aDataLength-=32;
   1.762 +				pixelexcess-=32;
   1.763 +				}
   1.764 +			if(aDataLength<=0) return;
   1.765 +			if(pixelexcess>0)
   1.766 +				{
   1.767 +				TInt shiftup=32-pixelexcess;
   1.768 +				TUint32* bufferptr=aBuffer;
   1.769 +				while(bufferptr<bufferlimit)
   1.770 +					{
   1.771 +					*bufferptr>>=pixelexcess;
   1.772 +					if(bufferptr<bufferlimit-1)
   1.773 +						*bufferptr|=(*(bufferptr+1)<<shiftup);
   1.774 +					bufferptr++;
   1.775 +					}
   1.776 +				aDataLength-=pixelexcess;
   1.777 +				if(aDataLength<=0) return;
   1.778 +				}
   1.779 +			aPrintPos.iY=iClipRect.iTl.iY;
   1.780 +			}
   1.781 +		if(aPrintPos.iY+aDataLength>iClipRect.iBr.iY)
   1.782 +			{
   1.783 +			TInt pixelexcess=aPrintPos.iY+aDataLength-iClipRect.iBr.iY;
   1.784 +			aDataLength-=pixelexcess;
   1.785 +			if(aDataLength<=0) return;
   1.786 +			}
   1.787 +		}
   1.788 +	aNum*=aHeightFactor;
   1.789 +	while(aNum>0)
   1.790 +		{
   1.791 +		if(aPrintPos.iX>=iClipRect.iTl.iX && aPrintPos.iX<iClipRect.iBr.iX)
   1.792 +			iDevice->iDrawDevice->WriteBinaryLineVertical(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode,aUp);
   1.793 +		aPrintPos.iX+=xinc;
   1.794 +		aNum--;
   1.795 +		}
   1.796 +	}
   1.797 +
   1.798 +
   1.799 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,TBool aUp)
   1.800 +	{
   1.801 +	DrawTextVertical(aText,aParam,iLastPrintPosition,aUp);
   1.802 +	}
   1.803 +	
   1.804 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TBool aUp)
   1.805 +	{
   1.806 +	TBrushStyle brushstyle=iBrushStyle;
   1.807 +	iBrushStyle=CGraphicsContext::ENullBrush;
   1.808 +	TOpenFontMetrics metrics;
   1.809 +	iFont.GetFontMetrics(metrics);
   1.810 +	TInt ascent = metrics.MaxHeight();
   1.811 +	TInt height = ascent + metrics.MaxDepth();
   1.812 +	// The next few lines do much the same as TextWidthInPixels but pass
   1.813 +	// the text in visual order instead of logical order and also take
   1.814 +	// full account of left and right side bearings on the text
   1.815 +	CFont::TMeasureTextOutput output;
   1.816 +	CFont::TMeasureTextInput input;
   1.817 +	input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
   1.818 +	if (aParam)
   1.819 +		{
   1.820 +		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
   1.821 +		input.iStartInputChar = aParam->iStart;
   1.822 +		input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
   1.823 +		}
   1.824 +	TInt advance = iFont.MeasureText(aText,&input,&output);
   1.825 +	
   1.826 +	//the box is not expanded by the underline position, as it is for horizontal text.
   1.827 +	TInt leftBearing = output.iBounds.iTl.iX;
   1.828 +	TInt rightBearing = advance - output.iBounds.iBr.iX;
   1.829 +	TRect box;
   1.830 +	TInt margin=0;
   1.831 +	if(aUp)
   1.832 +		{
   1.833 +		box.iTl.iX=aPosition.iX-ascent;
   1.834 +		box.iTl.iY=aPosition.iY-advance;
   1.835 +		box.iBr.iX=aPosition.iX+height-ascent+1;
   1.836 +		box.iBr.iY=aPosition.iY;
   1.837 +		if(leftBearing<0)
   1.838 +			{
   1.839 +			box.iBr.iY-=leftBearing;
   1.840 +			margin=-leftBearing;
   1.841 +			}
   1.842 +		if(rightBearing<0)
   1.843 +			{
   1.844 +			box.iTl.iY+=rightBearing;
   1.845 +			}
   1.846 +   		}
   1.847 +	else
   1.848 +		{
   1.849 +		box.iTl.iX=aPosition.iX+ascent-height;
   1.850 +		box.iTl.iY=aPosition.iY;
   1.851 +		box.iBr.iX=aPosition.iX+ascent+1;
   1.852 +		box.iBr.iY=aPosition.iY+advance;
   1.853 +		if(leftBearing<0)
   1.854 +			{
   1.855 +			box.iTl.iY+=leftBearing;
   1.856 +			margin=-leftBearing;
   1.857 +			}
   1.858 +		if(rightBearing<0)
   1.859 +			{
   1.860 +			box.iBr.iY-=rightBearing;
   1.861 +			}
   1.862 +		}
   1.863 +	DrawTextVertical(aText,aParam,box,ascent,aUp,ELeft,margin);
   1.864 +	iBrushStyle=brushstyle;
   1.865 +	}
   1.866 +	
   1.867 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TBool aUp)
   1.868 +	{
   1.869 +	TRect boxcpy(aBox);
   1.870 +	boxcpy.Move(iOrigin);
   1.871 +	TRect oldcliprect(iUserClipRect);
   1.872 +	iUserClipRect.Intersection(boxcpy);
   1.873 +	DrawTextVertical(aText,aParam,aUp);
   1.874 +	iUserClipRect=oldcliprect;
   1.875 +	}
   1.876 +	
   1.877 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TBool aUp,TTextAlign aVert,TInt aMargin)
   1.878 +	{
   1.879 +	DrawTextVertical(aText,aParam,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
   1.880 +	}
   1.881 +
   1.882 +EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt aTextWidth,TBool aUp,TTextAlign aVert,TInt aMargin)
   1.883 +	{
   1.884 +	CheckDevice();
   1.885 +	BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
   1.886 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.887 +	TRect boxcpy(aBox);
   1.888 +	boxcpy.Move(iOrigin);
   1.889 +	AddRect(boxcpy);
   1.890 +	if (boxcpy.Intersects(iUserClipRect))
   1.891 +		{
   1.892 +		boxcpy.Intersection(iUserClipRect);
   1.893 +		}
   1.894 +	SetupDevice();
   1.895 +	iDevice->DrawingBegin(&iBrushBitmap);
   1.896 +	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
   1.897 +	const CBitmapFont* fontaddress=iFont.Address();
   1.898 +	if(!fontaddress)
   1.899 +		{
   1.900 +		if (brushRasterizer)
   1.901 +			{
   1.902 +			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.903 +			}
   1.904 +		iDevice->DrawingEnd(&iBrushBitmap);
   1.905 +		BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
   1.906 +		}
   1.907 +	CFont::TMeasureTextInput input;
   1.908 +	//CFont::TMeasureTextOutput
   1.909 +	if (aParam)
   1.910 +		{
   1.911 +		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
   1.912 +		input.iStartInputChar = aParam->iStart;
   1.913 +		input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
   1.914 +		}
   1.915 +	TInt width = iFont.MeasureText(aText,&input);
   1.916 +	TOpenFontMetrics metrics;
   1.917 +	iFont.GetFontMetrics(metrics);
   1.918 +	TInt textlength=aText.Length();
   1.919 +	if(aTextWidth<0) aTextWidth=width;
   1.920 +	TPoint coords;
   1.921 +	coords.iX=aBox.iTl.iX;
   1.922 +	TInt dirmult=aUp?-1:1;
   1.923 +	coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
   1.924 +	//
   1.925 +	// iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
   1.926 +	// pre: iX = 0
   1.927 +	//
   1.928 +	// hhhhhhhhhhhhhhhhhhhh
   1.929 +	// 01234567890123456789
   1.930 +	// aaaaaaaaaaaaaaaaaadd	aUp=ETrue
   1.931 +	//                   ^
   1.932 +	//                   iX = 18 (baseline)
   1.933 +	//
   1.934 +	// ddaaaaaaaaaaaaaaaaaa aUp=EFalse
   1.935 +	//  ^
   1.936 +	//  iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
   1.937 +	//
   1.938 +	coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
   1.939 +	switch(aVert)
   1.940 +		{
   1.941 +	case ELeft:
   1.942 +		coords.iY+=aMargin*dirmult;
   1.943 +		break;
   1.944 +	case ECenter:
   1.945 +		coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
   1.946 +		break;
   1.947 +	case ERight:
   1.948 +		coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
   1.949 +		break;
   1.950 +		}
   1.951 +	iLastPrintPosition=coords;
   1.952 +	coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
   1.953 +	coords+=iOrigin;
   1.954 +	TInt prewidth=width+iCharJustExcess+iWordJustExcess;
   1.955 +	iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
   1.956 +	if(boxcpy.IsEmpty())
   1.957 +		{
   1.958 +		if (brushRasterizer)
   1.959 +			{
   1.960 +			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.961 +			}
   1.962 +		iDevice->DrawingEnd(&iBrushBitmap);
   1.963 +		if (iAutoUpdateJustification)
   1.964 +			UpdateJustificationVertical(aText,aParam,aUp);
   1.965 +		return;
   1.966 +		}
   1.967 +	RectFill(boxcpy);
   1.968 +	TBool userintersect=boxcpy.Intersects(iUserClipRect);
   1.969 +	if(!userintersect || !textlength || !width)
   1.970 +		{
   1.971 +		if (brushRasterizer)
   1.972 +			{
   1.973 +			brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.974 +			}
   1.975 +		iDevice->DrawingEnd(&iBrushBitmap);
   1.976 +		if (iAutoUpdateJustification)
   1.977 +			UpdateJustificationVertical(aText,aParam,aUp);
   1.978 +		return;
   1.979 +		}
   1.980 +	boxcpy.Intersection(iUserClipRect);
   1.981 +	TInt charjustexcess=iCharJustExcess;
   1.982 +	TInt charjustnum=iCharJustNum;
   1.983 +	TInt wordjustexcess=iWordJustExcess;
   1.984 +	TInt wordjustnum=iWordJustNum;
   1.985 +	TInt limit=iDefaultRegionPtr->Count();
   1.986 +	for(TInt count=0;count<limit;count++)
   1.987 +		{
   1.988 +		/*
   1.989 +		Initialise the justification parameters to the original values at the start of each pass.
   1.990 +		This means that any number of passes have exactly the same effect on the parameters as one pass;
   1.991 +		that is, to reduce them by the numbers of items and pixels consumed.
   1.992 +		*/
   1.993 +		iCharJustExcess = charjustexcess;
   1.994 +		iCharJustNum = charjustnum;
   1.995 +		iWordJustExcess = wordjustexcess;
   1.996 +		iWordJustNum = wordjustnum;
   1.997 +
   1.998 +		iClipRect=(*iDefaultRegionPtr)[count];
   1.999 +		if(!iClipRect.Intersects(boxcpy))
  1.1000 +			continue;
  1.1001 +#if defined(_DEBUG)
  1.1002 +		TRect deviceRect;
  1.1003 +		drawDevice->GetDrawRect(deviceRect);
  1.1004 +		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
  1.1005 +		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
  1.1006 +		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
  1.1007 +		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
  1.1008 +#endif
  1.1009 +		iClipRect.Intersection(boxcpy);
  1.1010 +		/*
  1.1011 +		Set up the parameter block for character positioning.
  1.1012 +		Draw left to right, because although the text is being drawn vertically,
  1.1013 +		it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
  1.1014 +		the characters in their normal orientation but in a vertical column.
  1.1015 +		*/
  1.1016 +		CFont::TPositionParam param;
  1.1017 +		param.iText.Set(aText);
  1.1018 +		param.iPen = coords;
  1.1019 +		TInt endDraw = aText.Length();
  1.1020 +		if (aParam)
  1.1021 +			{
  1.1022 +			param.iPosInText = aParam->iStart;
  1.1023 +			endDraw = Min(aText.Length(),aParam->iEnd);
  1.1024 +			}
  1.1025 +		else
  1.1026 +			param.iPosInText = 0;
  1.1027 +
  1.1028 +		// Draw the text.
  1.1029 +		DoDrawTextVertical(param,fontaddress,aUp,endDraw);
  1.1030 +
  1.1031 +		drawDevice->UpdateRegion(iClipRect);
  1.1032 +		}
  1.1033 +	if (brushRasterizer)
  1.1034 +		{
  1.1035 +		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
  1.1036 +		}
  1.1037 +	iDevice->DrawingEnd(&iBrushBitmap);
  1.1038 +	if(iAutoUpdateJustification)
  1.1039 +		UpdateJustificationVertical(aText,aParam,aUp);
  1.1040 +	}