os/graphics/graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1307 @@
     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 <bmalphablend.h>
    1.26 +#include <bitdrawinterfaceid.h>
    1.27 +#include <graphics/fbsrasterizer.h>
    1.28 +#include "bitgcextradata.h"
    1.29 +#include <graphics/gdi/gdiconsts.h>
    1.30 +#include <graphics/gdi/gdistructs.h>
    1.31 +
    1.32 +
    1.33 +/** Draws text at the last print position.
    1.34 +
    1.35 +@param aText The text string to be drawn. */
    1.36 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText)
    1.37 +	{
    1.38 +	TTextParameters* param = NULL;
    1.39 +	DrawText(aText,param,iLastPrintPosition,ELeft,CFont::EHorizontal);
    1.40 +	}
    1.41 +
    1.42 +/** Draws text at the specified position and updates the print position.
    1.43 +
    1.44 +@param  aText The text string to be drawn
    1.45 +@param aCoords Coordinates to draw the text at. */
    1.46 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TPoint& aCoords)
    1.47 +	{
    1.48 +	TTextParameters* param = NULL;
    1.49 +	DrawText(aText,param,aCoords,ELeft,CFont::EHorizontal);
    1.50 +	}
    1.51 +
    1.52 +
    1.53 +/** Draws text clipped to the specified rectangle.
    1.54 +
    1.55 +@param aText The text string to be drawn 
    1.56 +@param aBox The clipping rectangle. */
    1.57 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox)
    1.58 +	{
    1.59 +	TTextParameters* param = NULL;
    1.60 +	DrawText(aText,param,aBox);
    1.61 +	}
    1.62 +
    1.63 +
    1.64 +/** Draws text clipped to the specified rectangle using a baseline offset,
    1.65 +horizontal alignment and a margin.
    1.66 +
    1.67 +@param  aText The text string to be drawn
    1.68 +@param aBox The clipping rectangle.
    1.69 +@param  aBLOff An offset in pixels for the baseline from the normal position
    1.70 +        (bottom of the rectangle minus the descent of the font).
    1.71 +@param  aHrz Horizontal alignment option relative to the specified rectangle.
    1.72 +@param aMargin Offset to add to the position as calculated using specified 
    1.73 +		rectangle. */	
    1.74 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,TInt aBLOff,
    1.75 +								  TTextAlign aHrz,TInt aMargin)
    1.76 +    {
    1.77 +    TTextParameters* param = NULL;
    1.78 +	DrawText(aText,param,aBox,aBLOff,-1,aHrz,aMargin);
    1.79 +	}
    1.80 +
    1.81 +/** Draws text clipped to the specified rectangle.
    1.82 +
    1.83 +@param  aText The text string to be drawn
    1.84 +@param aBox The clipping rectangle. */	
    1.85 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,
    1.86 +								  TInt aBLOff,TInt /*aTextWidth*/,
    1.87 +								  TTextAlign aHrz,TInt aMargin)
    1.88 +    {
    1.89 +// aTextWidth is not used here - try to abolish this - I think it is unneeded
    1.90 +	TPoint p(aBox.iTl);
    1.91 +	p.iY += aBLOff;
    1.92 +	switch (aHrz)
    1.93 +		{
    1.94 +		case ELeft: p.iX += aMargin; break;
    1.95 +		case ERight: p.iX = aBox.iBr.iX - aMargin; break;
    1.96 +		case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
    1.97 +		}
    1.98 +	TTextParameters* param = NULL;
    1.99 +	DrawText(aText,param,p,aHrz,CFont::EHorizontal,&aBox);
   1.100 +	}
   1.101 +
   1.102 +
   1.103 +/** The general DrawText routine that implements all the others.
   1.104 +
   1.105 +@param aText the text to be drawn
   1.106 +@param aPosition the origin of the text
   1.107 +@param aAlignment left, centred or right, around aPosition; not used if drawing vertically
   1.108 +@param aDirection direction: left to right, right to left, or top to bottom
   1.109 +@param aBox if non-null, filled before the text is drawn
   1.110 +@param aTextBounds if non-null returns the bounding box of the text
   1.111 +*/ 
   1.112 +void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TTextAlign aAlignment,
   1.113 +						 CFont::TTextDirection aDirection,const TRect* aBox)
   1.114 +   {
   1.115 +	// sanity checks
   1.116 +	BG_ASSERT_ALWAYS(iDevice,EBitgdiPanicNoDevicePresent);
   1.117 +	BG_ASSERT_ALWAYS(iFont.Handle() != 0,EBitgdiPanicNoFontSelected);
   1.118 +	const CBitmapFont* bitmap_font = iFont.Address();
   1.119 +	BG_ASSERT_ALWAYS(bitmap_font != 0,EBitgdiPanicNoFontSelected);
   1.120 +
   1.121 +	// anything to do?
   1.122 +	if (!aBox && !aText.Length())
   1.123 +		return;
   1.124 +
   1.125 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.126 +
   1.127 +	TRect deviceRect;
   1.128 +	drawDevice->GetDrawRect(deviceRect);
   1.129 +
   1.130 +	// measure the text
   1.131 +	CFont::TMeasureTextInput measure_text_input;
   1.132 +	measure_text_input.iCharJustNum = iCharJustNum;
   1.133 +	measure_text_input.iCharJustExcess = iCharJustExcess;
   1.134 +	measure_text_input.iWordJustNum = iWordJustNum;
   1.135 +	measure_text_input.iWordJustExcess = iWordJustExcess;
   1.136 +	measure_text_input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder;
   1.137 +	if (aParam)
   1.138 +		{
   1.139 +		BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
   1.140 +		measure_text_input.iStartInputChar = aParam->iStart;
   1.141 +		measure_text_input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
   1.142 +		}
   1.143 +	CFont::TMeasureTextOutput measure_text_output;
   1.144 +	const int advance = iFont.MeasureText(aText,&measure_text_input,&measure_text_output);
   1.145 +	TRect text_bounds = measure_text_output.iBounds;
   1.146 +	TInt underlineStrikeoutOffset;
   1.147 +	
   1.148 +	//this call is only needed in the case of linked fonts
   1.149 +	//should this pass by one structure?
   1.150 +	underlineStrikeoutOffset= BaselineCorrection();
   1.151 +	
   1.152 +	if (iUnderline == EUnderlineOn)
   1.153 +		{
   1.154 +		TInt underline_top = 0, underline_bottom = 0;
   1.155 +		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
   1.156 +		underline_top+=underlineStrikeoutOffset;
   1.157 +		underline_bottom+=underlineStrikeoutOffset;
   1.158 +		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
   1.159 +		text_bounds.iTl.iY = Min(text_bounds.iTl.iY,underline_top);
   1.160 +		text_bounds.iBr.iY = Max(text_bounds.iBr.iY,underline_bottom);
   1.161 +		}
   1.162 +	if (iStrikethrough == EStrikethroughOn)
   1.163 +		{
   1.164 +		TInt strike_top = 0,strike_bottom = 0;
   1.165 +		GetStrikethroughMetrics(strike_top,strike_bottom);
   1.166 +		strike_top+=underlineStrikeoutOffset;
   1.167 +		strike_bottom+=underlineStrikeoutOffset;
   1.168 +		text_bounds.iTl.iY = Min(text_bounds.iTl.iY,strike_top);
   1.169 +		text_bounds.iBr.iY = Max(text_bounds.iBr.iY,strike_bottom);
   1.170 +		}
   1.171 +	if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
   1.172 +		{
   1.173 +		if (aDirection == CFont::EHorizontal)
   1.174 +			{
   1.175 +			text_bounds.iTl.iX = Min(text_bounds.iTl.iX, 0);
   1.176 +			text_bounds.iBr.iX = Max(text_bounds.iBr.iX, advance);
   1.177 +			}
   1.178 +		else
   1.179 +			{
   1.180 +			text_bounds.iTl.iY = Min(text_bounds.iTl.iY, 0);
   1.181 +			text_bounds.iBr.iY = Max(text_bounds.iBr.iY, advance);
   1.182 +			}
   1.183 +		}
   1.184 +
   1.185 +	// work out the text origin and new drawing position
   1.186 + 	TPoint text_origin = aPosition;
   1.187 + 	if (aDirection != CFont::EVertical)
   1.188 + 		{
   1.189 + 		const TInt leftSideBearing = Min(text_bounds.iTl.iX, 0);
   1.190 + 		const TInt rightSideBearing = Max(text_bounds.iBr.iX, advance);
   1.191 + 		switch (aAlignment)
   1.192 + 			{
   1.193 +			// We are forbidding side-bearings to leak over the sides here,
   1.194 +			// but still keeping the start and end pen positions within bounds.
   1.195 +			case ELeft:
   1.196 +				text_origin.iX -= leftSideBearing;
   1.197 +				break;
   1.198 +			case ERight:
   1.199 +				text_origin.iX -= rightSideBearing;
   1.200 +				break;
   1.201 +			case ECenter:
   1.202 +				// Centre is the average of left and right
   1.203 +				text_origin.iX -= (leftSideBearing + rightSideBearing) >> 1;
   1.204 +				break;
   1.205 +			default:
   1.206 +				break;
   1.207 + 			}
   1.208 +		}
   1.209 +	iLastPrintPosition = text_origin;
   1.210 +	if (aDirection == CFont::EHorizontal)
   1.211 +		iLastPrintPosition.iX += advance;
   1.212 +	else
   1.213 +		iLastPrintPosition.iY += advance;
   1.214 +	text_origin.iY += bitmap_font->iAlgStyle.iBaselineOffsetInPixels;
   1.215 +	text_bounds.Move(text_origin);
   1.216 +	text_origin += iOrigin;
   1.217 +
   1.218 +	// determine clipping rectangle
   1.219 +	TRect clip_rect = aBox ? *aBox : text_bounds;
   1.220 +	AddRect(clip_rect);
   1.221 +	clip_rect.Move(iOrigin);
   1.222 +
   1.223 +	if (UserClipRect(clip_rect))
   1.224 +		{
   1.225 +		if (iAutoUpdateJustification)
   1.226 +			UpdateJustification(aText,aParam);
   1.227 +		return; // nothing to do
   1.228 +		}
   1.229 +
   1.230 +	SetupDevice();
   1.231 +	iDevice->DrawingBegin(&iBrushBitmap);
   1.232 +	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
   1.233 +
   1.234 +	// fill the box if necessary
   1.235 +	if (aBox)
   1.236 +		{
   1.237 +		TRect fill_box = *aBox;
   1.238 +		fill_box.Move(iOrigin);
   1.239 +		RectFill(fill_box);
   1.240 +		}
   1.241 +
   1.242 +	// decide which drawing routine to call
   1.243 +	const TBool bold = bitmap_font->iAlgStyle.IsBold();
   1.244 +	const TBool italic = bitmap_font->iAlgStyle.IsItalic();
   1.245 +	const TBool multiw = bitmap_font->iAlgStyle.WidthFactor() > 1;
   1.246 +	const TBool multih = bitmap_font->iAlgStyle.HeightFactor() > 1;
   1.247 +
   1.248 +	TOpenFontMetrics metrics;
   1.249 +	iFont.GetFontMetrics(metrics);
   1.250 +	const TInt maxwidth = metrics.MaxWidth();
   1.251 +	// extext will be TRUE, if font is bold/italic/underline/strikethrough/anti-aliased or it 
   1.252 +	// has shadow/outline effects ON. Depending on these properties it will call the proper draw routine.
   1.253 +	TBool extext = FALSE;
   1.254 +	TBool normaltext = FALSE;
   1.255 +	const TBool anti_aliased = (bitmap_font->GlyphBitmapType() == EAntiAliasedGlyphBitmap);
   1.256 +	const TBool outlineAndShadow = (bitmap_font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
   1.257 +	if (anti_aliased || outlineAndShadow)
   1.258 +		{
   1.259 +		if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
   1.260 +			{
   1.261 +			//For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used 
   1.262 +			//when drawing outline and shadow fonts.
   1.263 +			BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
   1.264 +			}
   1.265 +		extext = TRUE;
   1.266 +		}
   1.267 +	else if (maxwidth > 30 || text_bounds.Height() > 32 || multiw || multih)
   1.268 +		{
   1.269 +		}
   1.270 +	else if (iUnderline == EUnderlineOn || bold || italic || iStrikethrough == EStrikethroughOn || 
   1.271 +			 iCharJustNum > 0 || iWordJustNum > 0)
   1.272 +		extext = TRUE;
   1.273 +	else
   1.274 +		normaltext = TRUE;
   1.275 +
   1.276 +	const TInt charjustexcess = iCharJustExcess;
   1.277 +	const TInt charjustnum = iCharJustNum;
   1.278 +	const TInt wordjustexcess = iWordJustExcess;
   1.279 +	const TInt wordjustnum = iWordJustNum;
   1.280 +
   1.281 +	// draw the text to all clip rectangles in turn
   1.282 +	int clip_rects = iDefaultRegionPtr->Count();
   1.283 +	for (int i = 0; i < clip_rects; i++)
   1.284 +		{
   1.285 +		iClipRect = (*iDefaultRegionPtr)[i];
   1.286 +		if (!iClipRect.Intersects(clip_rect))
   1.287 +			continue;
   1.288 +
   1.289 +#ifdef _DEBUG
   1.290 +		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
   1.291 +		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
   1.292 +		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
   1.293 +		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
   1.294 +#endif
   1.295 +
   1.296 +		iClipRect.Intersection(clip_rect);
   1.297 +
   1.298 +		// Set up the parameter block for character positioning.
   1.299 +		CFont::TPositionParam param;
   1.300 +		param.iDirection = static_cast<TInt16>(aDirection);
   1.301 +		param.iText.Set(aText);
   1.302 +		TInt endDraw = aText.Length();
   1.303 +		if (aParam)
   1.304 +			{
   1.305 +			param.iPosInText = aParam->iStart;
   1.306 +			endDraw = Min(aText.Length(),aParam->iEnd);
   1.307 +			}
   1.308 +		else
   1.309 +			param.iPosInText = 0;
   1.310 +		param.iPen = text_origin;
   1.311 +
   1.312 +		// Draw the text.
   1.313 +		if (normaltext)
   1.314 +			DoDrawText(param,endDraw);
   1.315 +		else if (extext)
   1.316 +			DoDrawTextEx(param,bitmap_font,endDraw,underlineStrikeoutOffset);
   1.317 +		else
   1.318 +			DoDrawTextLarge(param,bitmap_font,endDraw);
   1.319 +		
   1.320 +		/*
   1.321 +		Reset the justification parameters to their original values.
   1.322 +		These will be updated as required later in code.
   1.323 +		*/
   1.324 +		iCharJustExcess = charjustexcess;
   1.325 +		iCharJustNum = charjustnum;
   1.326 +		iWordJustExcess = wordjustexcess;
   1.327 +		iWordJustNum = wordjustnum;
   1.328 +
   1.329 +		drawDevice->UpdateRegion(iClipRect);
   1.330 +		}
   1.331 +
   1.332 +	if (brushRasterizer)
   1.333 +		{
   1.334 +		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.335 +		}
   1.336 +	iDevice->DrawingEnd(&iBrushBitmap);
   1.337 +	if (iAutoUpdateJustification)
   1.338 +		UpdateJustification(aText,aParam);
   1.339 +	}
   1.340 +
   1.341 +void CFbsBitGc::DoDrawText(CFont::TPositionParam& aParam, const TInt aEnd)
   1.342 +	{
   1.343 +	//const int n = aParam.iText.Length();
   1.344 +	RShapeInfo shapeInfo;
   1.345 +	while (aParam.iPosInText < /*n*/aEnd)
   1.346 +		{
   1.347 +		if (iFont.GetCharacterPosition2(aParam, shapeInfo))
   1.348 +			{
   1.349 +			const CFont::TPositionParam::TOutput* output = aParam.iOutput;
   1.350 +			for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
   1.351 +				DoDrawCharacter(output->iBounds.iTl,output->iBitmapSize,output->iBitmap);
   1.352 +			}
   1.353 +		}
   1.354 +	if (shapeInfo.IsOpen())
   1.355 +		shapeInfo.Close();
   1.356 +		
   1.357 +	}
   1.358 +
   1.359 +void CFbsBitGc::DoDrawCharacter(const TPoint& aTopLeft,
   1.360 +								const TSize& aDataSize,
   1.361 +								const TUint8* aData)
   1.362 +	{
   1.363 +	/*
   1.364 +	Divert if the character is larger than expected; the criterion
   1.365 +	for choosing this function is only a heuristic, because it's perfectly legal for
   1.366 +	a character's bitmap to be wider than its escapement.
   1.367 +
   1.368 +	Use a dummy value (0) for semi-ascent because this character is not italic and so semi-ascent
   1.369 +	is irrelevant; it's used for pseudo-italic slanting.
   1.370 +	*/
   1.371 +	TInt dataheight = aDataSize.iHeight;
   1.372 +	TInt datalength = aDataSize.iWidth;
   1.373 +	if (datalength > 30 || dataheight > 32)
   1.374 +		{
   1.375 +		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,FALSE,FALSE,0,1,1);
   1.376 +		return;
   1.377 +		}
   1.378 +	
   1.379 +	TInt bitindex=0;
   1.380 +	TInt16 repeatcount=0;
   1.381 +	TUint32 binarydata[32];
   1.382 +	TUint32* binarydataptr=binarydata;
   1.383 +	TUint32* binarydataptrlimit;
   1.384 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   1.385 +		{
   1.386 +		repeatcount=Load16(aData+(bitindex>>3));
   1.387 +		repeatcount>>=bitindex&7;
   1.388 +		TInt multilineflag=repeatcount&1;
   1.389 +		repeatcount>>=1;
   1.390 +		repeatcount&=0xf;
   1.391 +		bitindex+=5;
   1.392 +		binarydataptrlimit=binarydata+charline+repeatcount;
   1.393 +		if(multilineflag)
   1.394 +			{
   1.395 +			while(binarydataptr<binarydataptrlimit)
   1.396 +				{
   1.397 +				TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
   1.398 +				TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
   1.399 +				TInt bitshift=bitindex&7;
   1.400 +				bitshift+=(chardataoffsetptr&3)<<3;
   1.401 +				*binarydataptr=(*chardataword++)>>bitshift;
   1.402 +				if(bitshift) *binarydataptr|=(*chardataword<<(32-bitshift));
   1.403 +				bitindex+=datalength;
   1.404 +				binarydataptr++;
   1.405 +				}
   1.406 +			}
   1.407 +		else
   1.408 +			{
   1.409 +			TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
   1.410 +			TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
   1.411 +			TInt bitshift=bitindex&7;
   1.412 +			bitshift+=(chardataoffsetptr&3)<<3;
   1.413 +			TUint32 data=(*chardataword++)>>bitshift;
   1.414 +			if(bitshift) data|=(*chardataword<<(32-bitshift));
   1.415 +			while(binarydataptr<binarydataptrlimit)
   1.416 +				*binarydataptr++=data;
   1.417 +			bitindex+=datalength;
   1.418 +			}
   1.419 +		}
   1.420 +	TPoint topleft(aTopLeft);
   1.421 +	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
   1.422 +	if(datalength>0 && dataheight>0)
   1.423 +		iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
   1.424 +	}
   1.425 +
   1.426 +/** 
   1.427 +@internalTechnology
   1.428 +
   1.429 +This function retrieves the baseline offset from the metrics of the text currently being drawn.
   1.430 +This is used to alter the positioning of underline and strikethrough on a linked font
   1.431 +
   1.432 +@return The baseline correction associated with the currently used font.
   1.433 +*/	
   1.434 +TInt CFbsBitGc::BaselineCorrection()
   1.435 +	{
   1.436 +	TOpenFontMetrics metrics;
   1.437 +	if (iFont.GetFontMetrics(metrics))
   1.438 +		return metrics.BaselineCorrection();
   1.439 +	else
   1.440 +		return 0;
   1.441 +	}
   1.442 +
   1.443 +void CFbsBitGc::DoDrawTextEx(CFont::TPositionParam& aParam,const CBitmapFont* font, const TInt aEnd, const TInt aUnderlineStrikethroughOffset)
   1.444 +	{
   1.445 +	const TInt charclipping = iClipRect.iBr.iX;
   1.446 +	TPoint start_pen = aParam.iPen;
   1.447 +	const TBool bold = font->iAlgStyle.IsBold();
   1.448 +	const TBool italic = font->iAlgStyle.IsItalic();
   1.449 +	const TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
   1.450 +	const TBool outlineShadowOrAntialiased = ((glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap) ||
   1.451 +												(glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap));
   1.452 +
   1.453 +	TInt underline_top = 0, underline_bottom = 0;
   1.454 +	if (iUnderline == EUnderlineOn)
   1.455 +		{
   1.456 +		TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
   1.457 +		underline_top+=aUnderlineStrikethroughOffset;
   1.458 +		underline_bottom+=aUnderlineStrikethroughOffset;
   1.459 +		BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
   1.460 +		}
   1.461 +	TInt strike_top = 0, strike_bottom = 0;
   1.462 +	if (italic || iStrikethrough == EStrikethroughOn)
   1.463 +		{
   1.464 +		GetStrikethroughMetrics(strike_top,strike_bottom);
   1.465 +		strike_top+=aUnderlineStrikethroughOffset;
   1.466 +		strike_bottom+=aUnderlineStrikethroughOffset;
   1.467 +		}
   1.468 +
   1.469 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.470 +	RShapeInfo shapeInfo;
   1.471 +	while (aParam.iPosInText < aEnd)
   1.472 +		{
   1.473 +		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
   1.474 +			continue;
   1.475 +		TInt adjustment = 0;
   1.476 +		if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
   1.477 +			{
   1.478 +			adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
   1.479 +			if(adjustment < 0)
   1.480 +				iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
   1.481 +			}
   1.482 +
   1.483 +		const CFont::TPositionParam::TOutput* output = aParam.iOutput;
   1.484 +		int semi_ascent = start_pen.iY + strike_top;
   1.485 +
   1.486 +		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
   1.487 +			{
   1.488 +			//get the character metrics for the glyph type
   1.489 +			TOpenFontCharMetrics characterParams;
   1.490 +			const TUint8* bitmap;
   1.491 +			TSize size;
   1.492 +			//note may now be using a glyph code, and not a character
   1.493 +			iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
   1.494 +			TGlyphBitmapType glyphType = characterParams.GlyphType();
   1.495 +			
   1.496 +			switch (glyphType)
   1.497 +				{
   1.498 +				case EAntiAliasedGlyphBitmap:
   1.499 +				case EFourColourBlendGlyphBitmap:
   1.500 +					DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphType);
   1.501 +					break;
   1.502 +
   1.503 +				case EDefaultGlyphBitmap:
   1.504 +				case EMonochromeGlyphBitmap:
   1.505 +					DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
   1.506 +					break;
   1.507 +
   1.508 +				default:
   1.509 +					//if the outline or shadow is not specified for the character, then use the font setting
   1.510 +					if (outlineShadowOrAntialiased)
   1.511 +						{
   1.512 +						DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphBitmapTypeForFont);			
   1.513 +						}
   1.514 +					else
   1.515 +						{
   1.516 +						DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
   1.517 +						}			 
   1.518 +					break;
   1.519 +				}
   1.520 +			}
   1.521 +
   1.522 +		iClipRect.iBr.iX = charclipping;
   1.523 +		if (adjustment)
   1.524 +			aParam.iPen.iX += adjustment;
   1.525 +		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
   1.526 +			{
   1.527 +			adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
   1.528 +			aParam.iPen.iX += adjustment;
   1.529 +			}
   1.530 +		}
   1.531 +	if (shapeInfo.IsOpen())
   1.532 +		shapeInfo.Close();
   1.533 +
   1.534 +	if (iUnderline == EUnderlineOn)
   1.535 +		{
   1.536 +		TRect ul(start_pen.iX,start_pen.iY + underline_top,aParam.iPen.iX,start_pen.iY + underline_bottom);
   1.537 +		if(ul.Intersects(iClipRect)) // checks for empty aRect as well
   1.538 +			{
   1.539 +			ul.Intersection(iClipRect);
   1.540 +			drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
   1.541 +			}
   1.542 +		}
   1.543 +
   1.544 +	if (iStrikethrough == EStrikethroughOn)
   1.545 +		{
   1.546 +		TRect st(start_pen.iX,start_pen.iY + strike_top,aParam.iPen.iX,start_pen.iY + strike_bottom);
   1.547 +		if(st.Intersects(iClipRect)) // checks for empty aRect as well
   1.548 +			{
   1.549 +			st.Intersection(iClipRect);
   1.550 +			drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
   1.551 +			}
   1.552 +		}
   1.553 +	}
   1.554 +
   1.555 +void CFbsBitGc::DoDrawCharacterEx(const TPoint& aTopLeft,
   1.556 +								  const TSize& aDataSize,
   1.557 +								  const TUint8* aData,
   1.558 +								  TBool aBold,TBool aItalic,TInt aSemiAscent)
   1.559 +	{
   1.560 +	/*
   1.561 +	Divert if the character is larger than expected; the criterion
   1.562 +	for choosing this function is only a heuristic, because it's perfectly legal for
   1.563 +	a character's bitmap to be wider than its escapement.
   1.564 +	*/
   1.565 +	TInt datalength = aDataSize.iWidth;
   1.566 +	TInt dataheight = aDataSize.iHeight;
   1.567 +	if (datalength > 30 || dataheight > 32)
   1.568 +		{
   1.569 +		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,1,1);
   1.570 +		return;
   1.571 +		}
   1.572 +
   1.573 +	TInt bitindex=0;
   1.574 +	TInt16 repeatcount=0;
   1.575 +	TUint32 binarydata[32];
   1.576 +	TUint32* binarydataptr=binarydata;
   1.577 +	TUint32* binarydataptrlimit;
   1.578 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   1.579 +		{
   1.580 +		repeatcount=Load16(aData+(bitindex>>3));
   1.581 +		repeatcount>>=bitindex&7;
   1.582 +		TInt multilineflag=repeatcount&1;
   1.583 +		repeatcount>>=1;
   1.584 +		repeatcount&=0xf;
   1.585 +		bitindex+=5;
   1.586 +		binarydataptrlimit=binarydata+charline+repeatcount;
   1.587 +		if(multilineflag)
   1.588 +			{
   1.589 +			while(binarydataptr<binarydataptrlimit)
   1.590 +				{
   1.591 +				CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
   1.592 +				bitindex+=datalength;
   1.593 +				binarydataptr++;
   1.594 +				}
   1.595 +			}
   1.596 +		else
   1.597 +			{
   1.598 +			TUint32 data=0;
   1.599 +			CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
   1.600 +			while(binarydataptr<binarydataptrlimit)
   1.601 +				*binarydataptr++=data;
   1.602 +			bitindex+=datalength;
   1.603 +			}
   1.604 +		}
   1.605 +	binarydataptr=binarydata;
   1.606 +	binarydataptrlimit=binarydata+dataheight;
   1.607 +	if(aBold)
   1.608 +		{
   1.609 +		TInt sparemask=(0xffffffff>>(32-datalength));
   1.610 +		while(binarydataptr<binarydataptrlimit)
   1.611 +			{
   1.612 +			*binarydataptr&=sparemask;
   1.613 +			*binarydataptr|=(*binarydataptr<<1);
   1.614 +			++binarydataptr;
   1.615 +			}
   1.616 +		binarydataptr=binarydata;
   1.617 +		datalength++;
   1.618 +		}
   1.619 +	if(aItalic)
   1.620 +		{
   1.621 +		TInt skewlevel=aSemiAscent-aTopLeft.iY;
   1.622 +		TUint32 sparemask=(0xffffffff>>(32-datalength));
   1.623 +		binarydataptrlimit=binarydata+skewlevel;
   1.624 +		while(binarydataptr<binarydataptrlimit)
   1.625 +			*binarydataptr++<<=1;
   1.626 +		binarydataptrlimit=binarydata+dataheight;
   1.627 +		while(binarydataptr<binarydataptrlimit)
   1.628 +			*binarydataptr++&=sparemask;
   1.629 +		binarydataptr=binarydata;
   1.630 +		datalength++;
   1.631 +		}
   1.632 +	TPoint topleft(aTopLeft);
   1.633 +	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
   1.634 +	if(datalength>0 && dataheight>0)
   1.635 +		iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
   1.636 +	}
   1.637 +
   1.638 +/** 
   1.639 +@internalTechnology
   1.640 +
   1.641 +This function draws an anti-aliased character.
   1.642 +
   1.643 +@param aTopLeft The position to output the character
   1.644 +@param aDataSize The size of the bitmap
   1.645 +@param aData the bitmap for outputt in their TOpenFontCharMetrics
   1.646 +@param aGlyphType the glyph type for the character
   1.647 +*/
   1.648 +void CFbsBitGc::DoDrawCharacterAntiAliased(const TPoint& aTopLeft,
   1.649 +										   const TSize& aDataSize,
   1.650 +										   const TUint8* aData,
   1.651 +										   const TGlyphBitmapType aGlyphType)
   1.652 +	{
   1.653 +	const int top_row = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
   1.654 +	const int bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iY - aTopLeft.iY);
   1.655 +	const int left_col = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
   1.656 +	const int right_col = Min(aDataSize.iWidth,iClipRect.iBr.iX - aTopLeft.iX);
   1.657 +	const TUint8* p = aData + top_row * aDataSize.iWidth + left_col;
   1.658 +	const int x = aTopLeft.iX + left_col;
   1.659 +	int y = aTopLeft.iY + top_row;
   1.660 +	const int cols = right_col - left_col;
   1.661 +	const TUint32 penColor = iPenColor.Internal();
   1.662 +	const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
   1.663 +	const TUint32 brushColor = iBrushColor.Internal();
   1.664 +
   1.665 +	if (EFourColourBlendGlyphBitmap == aGlyphType)
   1.666 +		{
   1.667 +		MOutlineAndShadowBlend* outlineAndShadow = NULL;
   1.668 +		const TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
   1.669 +		if(err == KErrNone) 
   1.670 +			{
   1.671 +			//There is a support for the interface with KOutlineAndShadowInterface id.
   1.672 +			for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
   1.673 +				outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p);
   1.674 +			}
   1.675 +		else
   1.676 +			{
   1.677 +			// Assert if MOutlineAndShadowBlend interface is not implemented
   1.678 +			BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
   1.679 +			}
   1.680 +		}
   1.681 +	else
   1.682 +		{
   1.683 +		for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
   1.684 +			iDevice->iDrawDevice->WriteRgbAlphaMulti(x,y,cols,iPenColor,p);
   1.685 +		}
   1.686 +	}
   1.687 +
   1.688 +void CFbsBitGc::DoDrawTextLarge(CFont::TPositionParam& aParam,const CBitmapFont* font,const TInt aEnd)
   1.689 +	{
   1.690 +	const TInt charclipping = iClipRect.iBr.iX;
   1.691 +	TPoint start_pen = aParam.iPen;
   1.692 +	const TInt strikeheight = start_pen.iY - (font->CBitmapFont::DoAscentInPixels() * 5/12) - 1;
   1.693 +	const TBool bold = font->iAlgStyle.IsBold();
   1.694 +	const TBool italic = font->iAlgStyle.IsItalic();
   1.695 +	const TInt widthfactor=font->iAlgStyle.WidthFactor();
   1.696 +	const TInt heightfactor=font->iAlgStyle.HeightFactor();
   1.697 +
   1.698 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.699 +
   1.700 +	RShapeInfo shapeInfo;
   1.701 +	while (aParam.iPosInText < aEnd)
   1.702 +		{
   1.703 +		if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
   1.704 +			continue;
   1.705 +		TInt adjustment = 0;
   1.706 +		if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
   1.707 +			{
   1.708 +			adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
   1.709 +			if(adjustment < 0)
   1.710 +				iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
   1.711 +			}
   1.712 +
   1.713 +		const CFont::TPositionParam::TOutput* output = aParam.iOutput;
   1.714 +		for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
   1.715 +			DoDrawCharacterLarge(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,strikeheight,
   1.716 +								 widthfactor,heightfactor);
   1.717 +
   1.718 +		iClipRect.iBr.iX = charclipping;
   1.719 +		if (adjustment)
   1.720 +			aParam.iPen.iX += adjustment;
   1.721 +		if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
   1.722 +			{
   1.723 +			adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
   1.724 +			aParam.iPen.iX += adjustment;
   1.725 +			}
   1.726 +		}
   1.727 +	if (shapeInfo.IsOpen())
   1.728 +		shapeInfo.Close();
   1.729 +	const TInt ulwidth = Max(font->CBitmapFont::DoHeightInPixels() / 10, 1);
   1.730 +	if (iUnderline == EUnderlineOn)
   1.731 +		{
   1.732 +		TInt ulstart = start_pen.iY + 1 + ulwidth / 2;
   1.733 +		TRect ul(start_pen.iX,ulstart,aParam.iPen.iX,ulstart + ulwidth);
   1.734 +		if(ul.Intersects(iClipRect)) // checks for empty aRect as well
   1.735 +			{
   1.736 +			ul.Intersection(iClipRect);
   1.737 +			drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
   1.738 +			}
   1.739 +		}
   1.740 +
   1.741 +	if (iStrikethrough == EStrikethroughOn)
   1.742 +		{
   1.743 +		TRect st(start_pen.iX,strikeheight,aParam.iPen.iX,strikeheight + ulwidth);
   1.744 +		if(st.Intersects(iClipRect)) // checks for empty aRect as well
   1.745 +			{
   1.746 +			st.Intersection(iClipRect);
   1.747 +			drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
   1.748 +			}
   1.749 +		}
   1.750 +	}
   1.751 +
   1.752 +void CFbsBitGc::DoDrawCharacterLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
   1.753 +									 TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
   1.754 +	{
   1.755 +	TInt datalength = aDataSize.iWidth;
   1.756 +	TInt dataheight = aDataSize.iHeight;
   1.757 +	
   1.758 +	if (aWidthFactor > 2 || aHeightFactor > 2)
   1.759 +		{
   1.760 +		DoDrawCharacterMultiplied(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
   1.761 +		return;
   1.762 +		}
   1.763 +	
   1.764 +	if (datalength > 30 || dataheight > 32 || (aWidthFactor == 2 && datalength > 14))
   1.765 +		{
   1.766 +		DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
   1.767 +		return;
   1.768 +		}
   1.769 +	
   1.770 +	TInt italicheight=aSemiAscent-aTopLeft.iY;
   1.771 +	if(aHeightFactor==2) italicheight>>=1;
   1.772 +	TInt bitindex=0;
   1.773 +	TInt16 repeatcount=0;
   1.774 +	TUint32 binarydata[64];
   1.775 +	TUint32* binarydataptr=binarydata;
   1.776 +	TUint32* binarydataptrlimit;
   1.777 +
   1.778 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   1.779 +		{
   1.780 +		repeatcount=Load16(aData+(bitindex>>3));
   1.781 +		repeatcount>>=bitindex&7;
   1.782 +		TInt multilineflag=repeatcount&1;
   1.783 +		repeatcount>>=1;
   1.784 +		repeatcount&=0xf;
   1.785 +		bitindex+=5;
   1.786 +		binarydataptrlimit=binarydata+charline+repeatcount;
   1.787 +		if(multilineflag)
   1.788 +			{
   1.789 +			while(binarydataptr<binarydataptrlimit)
   1.790 +				{
   1.791 +				CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
   1.792 +				bitindex+=datalength;
   1.793 +				binarydataptr++;
   1.794 +				}
   1.795 +			}
   1.796 +		else
   1.797 +			{
   1.798 +			TUint32 data=0;
   1.799 +			CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
   1.800 +			while(binarydataptr<binarydataptrlimit)
   1.801 +				*binarydataptr++=data;
   1.802 +			bitindex+=datalength;
   1.803 +			}
   1.804 +		}
   1.805 +	binarydataptr=binarydata;
   1.806 +	binarydataptrlimit=binarydata+dataheight;
   1.807 +	if(aBold)
   1.808 +		{
   1.809 +		TInt sparemask=(0xffffffff>>(32-datalength));
   1.810 +		while(binarydataptr<binarydataptrlimit)
   1.811 +			{
   1.812 +			*binarydataptr&=sparemask;
   1.813 +			*binarydataptr|=(*binarydataptr<<1);
   1.814 +			++binarydataptr;
   1.815 +			}
   1.816 +		binarydataptr=binarydata;
   1.817 +		datalength++;
   1.818 +		}
   1.819 +	if(aItalic)
   1.820 +		{
   1.821 +		TUint32 sparemask=(0xffffffff>>(32-datalength));
   1.822 +		binarydataptrlimit=Min(binarydataptrlimit,binarydata+italicheight);
   1.823 +		while(binarydataptr<binarydataptrlimit)
   1.824 +			{
   1.825 +			*binarydataptr<<=1;
   1.826 +			*binarydataptr++&=0xfffffffe;
   1.827 +			}
   1.828 +		binarydataptrlimit=binarydata+dataheight;
   1.829 +		while(binarydataptr<binarydataptrlimit)
   1.830 +			*binarydataptr++&=sparemask;
   1.831 +		binarydataptr=binarydata;
   1.832 +		datalength++;
   1.833 +		}
   1.834 +	if(aWidthFactor==2)
   1.835 +		{
   1.836 +		BG_ASSERT_DEBUG(datalength<=16,EBitgdiPanicCharacterTooBig);
   1.837 +		while(binarydataptr<binarydataptrlimit)
   1.838 +			{
   1.839 +			TUint32 singlemask=0x8000;
   1.840 +			TUint32 doublemask=0xc0000000;
   1.841 +			TUint32 newdata=0;
   1.842 +			while(singlemask)
   1.843 +				{
   1.844 +				if(*binarydataptr&singlemask)
   1.845 +					newdata|=doublemask;
   1.846 +				singlemask>>=1;
   1.847 +				doublemask>>=2;
   1.848 +				}
   1.849 +			*binarydataptr++=newdata;
   1.850 +			}
   1.851 +		datalength<<=1;
   1.852 +		binarydataptr=binarydata;
   1.853 +		}
   1.854 +	if(aHeightFactor==2)
   1.855 +		{
   1.856 +		binarydataptr=binarydata+dataheight-1;
   1.857 +		TUint32* tempptr=binarydataptr+dataheight;
   1.858 +		while(binarydataptr>=binarydata)
   1.859 +			{
   1.860 +			*tempptr--=*binarydataptr;
   1.861 +			*tempptr--=*binarydataptr--;
   1.862 +			}
   1.863 +		dataheight<<=1;
   1.864 +		binarydataptr=binarydata;
   1.865 +		}
   1.866 +	TPoint startpos=aTopLeft;
   1.867 +	binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,startpos);
   1.868 +	if(datalength>0 && dataheight>0)
   1.869 +		iDevice->iDrawDevice->WriteBinary(startpos.iX,startpos.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
   1.870 +	}
   1.871 +
   1.872 +void CFbsBitGc::DoDrawCharacterExLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
   1.873 +									   TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
   1.874 +	{
   1.875 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.876 +	TPoint printpos(aTopLeft);
   1.877 +	const TInt datalength = aDataSize.iWidth;
   1.878 +	const TInt dataheight = aDataSize.iHeight;
   1.879 +	TInt bitindex=0;
   1.880 +	TInt16 repeatcount=0;
   1.881 +	TUint32* slbuffer=drawDevice->ScanLineBuffer();
   1.882 +	const TInt slwords=(drawDevice->ScanLineBytes())<<3;
   1.883 +	if(aItalic && aTopLeft.iY<aSemiAscent)
   1.884 +		printpos.iX++;
   1.885 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   1.886 +		{
   1.887 +		repeatcount=Load16(aData+(bitindex>>3));
   1.888 +		repeatcount>>=bitindex&7;
   1.889 +		const TInt multilineflag=repeatcount&1;
   1.890 +		repeatcount>>=1;
   1.891 +		repeatcount&=0xf;
   1.892 +		bitindex+=5;
   1.893 +		if(multilineflag)
   1.894 +			{
   1.895 +			for(TInt currentline=0;currentline<repeatcount;currentline++)
   1.896 +				{
   1.897 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.898 +				OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
   1.899 +				bitindex+=datalength;
   1.900 +				printpos.iY++;
   1.901 +				if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
   1.902 +				if(aHeightFactor==2)
   1.903 +					{
   1.904 +					printpos.iY++;
   1.905 +					if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
   1.906 +					}
   1.907 +				}
   1.908 +			}
   1.909 +		else
   1.910 +			{
   1.911 +			if(aItalic)
   1.912 +				{
   1.913 +				for(TInt currentline=0;currentline<repeatcount;currentline++)
   1.914 +					{
   1.915 +					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.916 +					OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
   1.917 +					printpos.iY++;
   1.918 +					if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
   1.919 +					if(aHeightFactor==2)
   1.920 +						{
   1.921 +						printpos.iY++;
   1.922 +						if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
   1.923 +						}
   1.924 +					}
   1.925 +				}
   1.926 +			else
   1.927 +				{
   1.928 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.929 +				OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
   1.930 +				printpos.iY+=repeatcount;
   1.931 +				if(aHeightFactor==2) printpos.iY+=repeatcount;
   1.932 +				}
   1.933 +			bitindex+=datalength;
   1.934 +			}
   1.935 +		}
   1.936 +	}
   1.937 +
   1.938 +void CFbsBitGc::DoDrawCharacterMultiplied(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
   1.939 +										  TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
   1.940 +	{
   1.941 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.942 +	TPoint printpos(aTopLeft);
   1.943 +	const TInt datalength = aDataSize.iWidth;
   1.944 +	const TInt dataheight = aDataSize.iHeight;
   1.945 +	TInt bitindex=0;
   1.946 +	TInt16 repeatcount=0;
   1.947 +	TUint32* slbuffer=drawDevice->ScanLineBuffer();
   1.948 +	const TInt slwords=(drawDevice->ScanLineBytes())<<3;
   1.949 +	if(aItalic && aTopLeft.iY<aSemiAscent)
   1.950 +		printpos.iX++;
   1.951 +	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   1.952 +		{
   1.953 +		repeatcount=Load16(aData+(bitindex>>3));
   1.954 +		repeatcount>>=bitindex&7;
   1.955 +		const TInt multilineflag=repeatcount&1;
   1.956 +		repeatcount>>=1;
   1.957 +		repeatcount&=0xf;
   1.958 +		bitindex+=5;
   1.959 +		if(multilineflag)
   1.960 +			{
   1.961 +			for(TInt currentline=0;currentline<repeatcount;currentline++)
   1.962 +				{
   1.963 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.964 +				OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
   1.965 +				bitindex+=datalength;
   1.966 +				TBool aboveitalicjump=EFalse;
   1.967 +				if(aItalic && printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
   1.968 +				printpos.iY+=aHeightFactor;
   1.969 +				if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
   1.970 +				}
   1.971 +			}
   1.972 +		else
   1.973 +			{
   1.974 +			if(aItalic)
   1.975 +				{
   1.976 +				for(TInt currentline=0;currentline<repeatcount;currentline++)
   1.977 +					{
   1.978 +					CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.979 +					OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
   1.980 +					TBool aboveitalicjump=EFalse;
   1.981 +					if(printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
   1.982 +					printpos.iY+=aHeightFactor;
   1.983 +					if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
   1.984 +					}
   1.985 +				}
   1.986 +			else
   1.987 +				{
   1.988 +				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
   1.989 +				OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
   1.990 +				printpos.iY+=repeatcount*aHeightFactor;
   1.991 +				}
   1.992 +			bitindex+=datalength;
   1.993 +			}
   1.994 +		}
   1.995 +	}
   1.996 +
   1.997 +void CFbsBitGc::OutputCharLineMultiplied(TPoint aPrintPos,TUint32* aBuffer,TInt aDataLength,TInt aNum,TBool aBold,TInt aWidthFactor,TInt aHeightFactor)
   1.998 +	{
   1.999 +	if(aDataLength<=0) return;
  1.1000 +	TInt bufferwords=(aDataLength+31)>>5;
  1.1001 +	TUint32* bufferlimit=aBuffer+bufferwords;
  1.1002 +	if(aBold)
  1.1003 +		{
  1.1004 +		TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
  1.1005 +		if((aDataLength&0x1f)==0) sparemask=0xffffffff;
  1.1006 +		*(bufferlimit-1)&=sparemask;
  1.1007 +		TUint32* bufferptr=aBuffer;
  1.1008 +		TUint32 extrabit=0;
  1.1009 +		while(bufferptr<bufferlimit)
  1.1010 +			{
  1.1011 +			extrabit=*bufferptr>>31;
  1.1012 +			*bufferptr|=(*bufferptr<<1);
  1.1013 +			++bufferptr;
  1.1014 +			if(bufferptr<bufferlimit)
  1.1015 +				*bufferptr|=extrabit;
  1.1016 +			}
  1.1017 +		aDataLength++;
  1.1018 +		if((aDataLength&0x1f)==1)
  1.1019 +			{
  1.1020 +			bufferwords++;
  1.1021 +			*bufferlimit=extrabit;
  1.1022 +			bufferlimit++;
  1.1023 +			}
  1.1024 +		}
  1.1025 +	if(aWidthFactor>1)
  1.1026 +		{
  1.1027 +		BitMultiply(aBuffer,aDataLength,aWidthFactor);
  1.1028 +		aDataLength*=aWidthFactor;
  1.1029 +		bufferwords=(aDataLength+31)>>5;
  1.1030 +		bufferlimit=aBuffer+bufferwords;
  1.1031 +		}
  1.1032 +	if(aPrintPos.iX<iClipRect.iTl.iX)
  1.1033 +		{
  1.1034 +		TInt pixelexcess=iClipRect.iTl.iX-aPrintPos.iX;
  1.1035 +		while(pixelexcess>=32)
  1.1036 +			{
  1.1037 +			aBuffer++;
  1.1038 +			bufferwords--;
  1.1039 +			aDataLength-=32;
  1.1040 +			pixelexcess-=32;
  1.1041 +			}
  1.1042 +		if(aDataLength<=0) return;
  1.1043 +		if(pixelexcess>0)
  1.1044 +			{
  1.1045 +			TInt shiftup=32-pixelexcess;
  1.1046 +			TUint32* bufferptr=aBuffer;
  1.1047 +			while(bufferptr<bufferlimit)
  1.1048 +				{
  1.1049 +				*bufferptr>>=pixelexcess;
  1.1050 +				if(bufferptr<bufferlimit-1)
  1.1051 +					*bufferptr|=(*(bufferptr+1)<<shiftup);
  1.1052 +				bufferptr++;
  1.1053 +				}
  1.1054 +			aDataLength-=pixelexcess;
  1.1055 +			if(aDataLength<=0) return;
  1.1056 +			}
  1.1057 +		aPrintPos.iX=iClipRect.iTl.iX;
  1.1058 +		}
  1.1059 +	if(aPrintPos.iX+aDataLength>iClipRect.iBr.iX)
  1.1060 +		{
  1.1061 +		TInt pixelexcess=aPrintPos.iX+aDataLength-iClipRect.iBr.iX;
  1.1062 +		aDataLength-=pixelexcess;
  1.1063 +		if(aDataLength<=0) return;
  1.1064 +		}
  1.1065 +	aNum*=aHeightFactor;
  1.1066 +	while(aNum>0)
  1.1067 +		{
  1.1068 +		if(aPrintPos.iY>=iClipRect.iTl.iY && aPrintPos.iY<iClipRect.iBr.iY)
  1.1069 +			iDevice->iDrawDevice->WriteBinaryLine(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode);
  1.1070 +		aPrintPos.iY++;
  1.1071 +		aNum--;
  1.1072 +		}
  1.1073 +	}
  1.1074 +
  1.1075 +void CFbsBitGc::CopyCharWord(TUint32* aBinaryDataPtr,const TUint8* aData,TInt aBitShift)
  1.1076 +	{
  1.1077 +	const TUint32* dataword=(TUint32*)(TInt(aData)&~3);
  1.1078 +	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
  1.1079 +	*aBinaryDataPtr=*dataword++;
  1.1080 +	if(aBitShift<32) *aBinaryDataPtr>>=aBitShift;
  1.1081 +	if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
  1.1082 +	}
  1.1083 +	
  1.1084 +void CFbsBitGc::CopyCharLine(TUint32* aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth)
  1.1085 +	{
  1.1086 +	aBitShift&=7;
  1.1087 +	TInt wordstocopy=(aCharWidth+31)>>5;
  1.1088 +	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
  1.1089 +	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
  1.1090 +	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
  1.1091 +	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
  1.1092 +	while(aBinaryDataPtr<ptrlimit)
  1.1093 +		{
  1.1094 +		*aBinaryDataPtr=*dataword++;
  1.1095 +		*aBinaryDataPtr>>=aBitShift;
  1.1096 +		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
  1.1097 +		aBinaryDataPtr++;
  1.1098 +		}
  1.1099 +	}
  1.1100 +	
  1.1101 +TUint32* CFbsBitGc::ClipBinaryArray(TUint32* aArray,TUint32* aArrayLimit,TInt aArrayWordWd,TInt& aDataWd,TInt& aDataHt,TPoint& aPos)
  1.1102 +	{
  1.1103 +	TUint32* arrayptr=aArray;
  1.1104 +	TInt clipdiff=iClipRect.iTl.iX-aPos.iX;
  1.1105 +	if(aArrayWordWd==1)
  1.1106 +		{
  1.1107 +		if(clipdiff>0)
  1.1108 +			{
  1.1109 +			while(arrayptr<aArrayLimit)
  1.1110 +				*arrayptr++>>=clipdiff;
  1.1111 +			aDataWd-=clipdiff;
  1.1112 +			aPos.iX=iClipRect.iTl.iX;
  1.1113 +			arrayptr=aArray;
  1.1114 +			}
  1.1115 +		if(aPos.iX+aDataWd>iClipRect.iBr.iX && aDataWd>0)
  1.1116 +			aDataWd=iClipRect.iBr.iX-aPos.iX;
  1.1117 +		clipdiff=iClipRect.iTl.iY-aPos.iY;
  1.1118 +		if(clipdiff>0)
  1.1119 +			{
  1.1120 +			aDataHt-=clipdiff;
  1.1121 +			arrayptr+=clipdiff;
  1.1122 +			aPos.iY=iClipRect.iTl.iY;
  1.1123 +			}
  1.1124 +		if(aPos.iY+aDataHt>iClipRect.iBr.iY && aDataHt>0)
  1.1125 +			aDataHt=iClipRect.iBr.iY-aPos.iY;
  1.1126 +		}
  1.1127 +	return(arrayptr);
  1.1128 +	}
  1.1129 +
  1.1130 +void CFbsBitGc::BitMultiply(TUint32* aBinaryDataPtr,TInt aBitLength,TInt aFactor)
  1.1131 +	{
  1.1132 +	TInt bitpos=aBitLength-1;
  1.1133 +	TUint32* wordpos=aBinaryDataPtr+(bitpos>>5);
  1.1134 +	TInt bitoffset=bitpos&0x1f;
  1.1135 +	TInt multbitpos=(aBitLength*aFactor)-1;
  1.1136 +	TUint32* multwordpos=aBinaryDataPtr+(multbitpos>>5);
  1.1137 +	TInt multbitoffset=multbitpos&0x1f;
  1.1138 +	while(bitpos>=0)
  1.1139 +		{
  1.1140 +		TUint32 bit=((*wordpos)>>bitoffset)&1;
  1.1141 +		TInt next=multbitpos-aFactor;
  1.1142 +		while(multbitpos>next)
  1.1143 +			{
  1.1144 +			if(bit) *multwordpos|=(1<<multbitoffset);
  1.1145 +			else *multwordpos&=~(1<<multbitoffset);
  1.1146 +			multbitpos--;
  1.1147 +			multbitoffset--;
  1.1148 +			if(multbitoffset<0)
  1.1149 +				{
  1.1150 +				multbitoffset=31;
  1.1151 +				multwordpos--;
  1.1152 +				}
  1.1153 +			}
  1.1154 +		bitpos--;
  1.1155 +		bitoffset--;
  1.1156 +		if(bitoffset<0)
  1.1157 +			{
  1.1158 +			bitoffset=31;
  1.1159 +			wordpos--;
  1.1160 +			}
  1.1161 +		}
  1.1162 +	}
  1.1163 +
  1.1164 +void CFbsBitGc::GetStrikethroughMetrics(TInt& aTop,TInt& aBottom)
  1.1165 +/** Get the top and bottom of a strikethrough line for the current font, relative to the baseline.*/
  1.1166 +	{
  1.1167 +	aTop = -(iFont.AscentInPixels() * 5/12) - 1;
  1.1168 +	aBottom = aTop + Max(iFont.HeightInPixels() / 10,1);
  1.1169 +	}
  1.1170 +
  1.1171 +/** APIExtension can contain as many additional methods as is required by 
  1.1172 +CGraphicsContext after its original conception. It takes 3 parameters.
  1.1173 +Function is exported due to constrains of retaining BC with earlier versions.
  1.1174 +This is not used directly by external methods, instead it is called by a named 
  1.1175 +method in CGraphicsContext which passes the relivant arguements including an 
  1.1176 +unique identifier for the required action.
  1.1177 +@param aUid The unique identifier for the method that is required. Selected 
  1.1178 +internally by a series of "if" statements. 
  1.1179 +@see Valid Uid identifiers are listed in header gdi.h
  1.1180 +@see CGraphicsContext
  1.1181 +@param aOutput is a TAny pointer to a reference. Used to output data as the structure
  1.1182 +does not need to be instantiated before the function call this adds greater 
  1.1183 +flexibility.
  1.1184 +@param aInput is a TAny pointer used to input data.
  1.1185 +*/	
  1.1186 +EXPORT_C TInt CFbsBitGc::APIExtension(TUid aUid, TAny*& aOutput, TAny* aInput)
  1.1187 +	{
  1.1188 +	if (aUid == KGetUnderlineMetrics)
  1.1189 +		{		
  1.1190 +		APIExGetUnderlineMetrics(aOutput);
  1.1191 +		return KErrNone;	
  1.1192 +		}
  1.1193 +	else if (aUid == KSetShadowColor)
  1.1194 +		{
  1.1195 +		return APIExSetShadowColor(aInput);
  1.1196 +		}
  1.1197 +	else if (aUid == KGetShadowColor)
  1.1198 +		{
  1.1199 +		return APIExGetShadowColor(aOutput);
  1.1200 +		}
  1.1201 +	else if (aUid == KDrawTextInContextUid)
  1.1202 +		{
  1.1203 +		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
  1.1204 +		DrawText(contextParam->iText, &contextParam->iParam, contextParam->iPosition);
  1.1205 +		return KErrNone;
  1.1206 +		}
  1.1207 +	else if (aUid == KDrawBoxTextInContextUid)
  1.1208 +		{
  1.1209 +		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
  1.1210 +		DrawText(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iAlign,contextParam->iMargin);
  1.1211 +		return KErrNone;
  1.1212 +		}
  1.1213 +	else if (aUid == KDrawTextInContextVerticalUid)
  1.1214 +		{
  1.1215 +		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
  1.1216 +		DrawTextVertical(contextParam->iText, &contextParam->iParam, contextParam->iPosition,contextParam->iUp);
  1.1217 +		return KErrNone;
  1.1218 +		}
  1.1219 +	else if (aUid == KDrawBoxTextInContextVerticalUid)
  1.1220 +		{
  1.1221 +		TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
  1.1222 +		DrawTextVertical(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iUp,contextParam->iAlign,contextParam->iMargin);
  1.1223 +		return KErrNone;
  1.1224 +		}
  1.1225 +	else if (aUid == KUidIsFbsBitmapGc)
  1.1226 +		{
  1.1227 +		return APIExIsFbsBitGc(aOutput);
  1.1228 +		}
  1.1229 +	/* Future cases may be placed here later.*/
  1.1230 +	else
  1.1231 +		return CBitmapContext::APIExtension(aUid, aOutput, aInput);
  1.1232 +	}
  1.1233 +	
  1.1234 +	
  1.1235 +	
  1.1236 +	
  1.1237 +		
  1.1238 +	
  1.1239 +	
  1.1240 +	
  1.1241 +	
  1.1242 +//The methods listed above in APIExtension follow here with the prefix APIEx.
  1.1243 +void CFbsBitGc::APIExGetUnderlineMetrics(TAny*& aOutput)
  1.1244 +	{
  1.1245 +	const TInt width = Max(iFont.HeightInPixels() / 10,1);
  1.1246 +	TTwoTInt* ptr = (TTwoTInt*)aOutput;
  1.1247 +	ptr->iTop = 1 + width / 2;
  1.1248 +	ptr->iBottom = (ptr->iTop) + width;
  1.1249 +	}
  1.1250 +
  1.1251 +TInt CFbsBitGc::APIExSetShadowColor(TAny* aShadowColor)
  1.1252 +	{
  1.1253 +	iFbsBitGcExtraData->SetShadowColor(*(reinterpret_cast<TRgb*>(aShadowColor)));
  1.1254 +	return KErrNone;
  1.1255 +	}
  1.1256 +
  1.1257 +TInt CFbsBitGc::APIExGetShadowColor(TAny*& aShadowColor)
  1.1258 +	{
  1.1259 +	TRgb* output = reinterpret_cast<TRgb*>(aShadowColor);
  1.1260 +	*output = iFbsBitGcExtraData->ShadowColor();
  1.1261 +	return KErrNone;
  1.1262 +	}
  1.1263 +	
  1.1264 +TInt CFbsBitGc::APIExIsFbsBitGc(TAny*& aIsCFbsBitGc)
  1.1265 +	{
  1.1266 +	TBool *output = reinterpret_cast<TBool*>(aIsCFbsBitGc);
  1.1267 +	*output = ETrue;
  1.1268 +	return KErrNone;
  1.1269 +	}
  1.1270 +
  1.1271 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam)
  1.1272 +	{
  1.1273 +	DrawText(aText,aParam,iLastPrintPosition,ELeft,CFont::EHorizontal);
  1.1274 +	}
  1.1275 +
  1.1276 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition)
  1.1277 +	{
  1.1278 +	DrawText(aText,aParam,aPosition,ELeft,CFont::EHorizontal);
  1.1279 +	}
  1.1280 +	
  1.1281 +	
  1.1282 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox)
  1.1283 +	{
  1.1284 +	TRect boxcpy(aBox);
  1.1285 +	boxcpy.Move(iOrigin);
  1.1286 +	if(!iUserClipRect.Intersects(boxcpy)) return;
  1.1287 +	TRect oldcliprect(iUserClipRect);
  1.1288 +	iUserClipRect.Intersection(boxcpy);
  1.1289 +	DrawText(aText,aParam);
  1.1290 +	iUserClipRect=oldcliprect;
  1.1291 +	}
  1.1292 +	
  1.1293 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHrz,TInt aMargin)
  1.1294 +	{
  1.1295 +	DrawText(aText,aParam,aBox,aBaselineOffset,-1,aHrz,aMargin);
  1.1296 +	}
  1.1297 +	
  1.1298 +EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt /*aTextWidth*/,TTextAlign aHrz,TInt aMargin)
  1.1299 +	{
  1.1300 +	// aTextWidth is not used here - try to abolish this - I think it is unneeded
  1.1301 +	TPoint p(aBox.iTl);
  1.1302 +	p.iY += aBaselineOffset;
  1.1303 +	switch (aHrz)
  1.1304 +		{
  1.1305 +		case ELeft: p.iX += aMargin; break;
  1.1306 +		case ERight: p.iX = aBox.iBr.iX - aMargin; break;
  1.1307 +		case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
  1.1308 +		}
  1.1309 +	DrawText(aText,aParam,p,aHrz,CFont::EHorizontal,&aBox);
  1.1310 +	}