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