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