First public contribution.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <shapeinfo.h>
22 #include <graphics/fbsrasterizer.h>
24 #include <bmalphablend.h>
25 #include <bitdrawinterfaceid.h>
26 #include "bitgcextradata.h"
28 /** Draws text at the last print position and then rotates it into a vertical position.
30 @param aText The text string to be drawn.
31 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is
32 rotated 90 degrees clockwise. */
33 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,TBool aUp)
35 DrawTextVertical(aText,iLastPrintPosition,aUp);
38 /** Draws text vertically from the specified position.
40 @param aText The text string to be drawn.
41 @param aPosition A point specifying the position of the left end of the text.
42 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text
43 is rotated 90 degrees clockwise. */
44 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TPoint& aPosition,TBool aUp)
46 TBrushStyle brushstyle=iBrushStyle;
47 iBrushStyle=CGraphicsContext::ENullBrush;
48 TOpenFontMetrics metrics;
49 iFont.GetFontMetrics(metrics);
50 TInt ascent = metrics.MaxHeight();
51 TInt height = ascent + metrics.MaxDepth();
52 // The next few lines do much the same as TextWidthInPixels but pass
53 // the text in visual order instead of logical order and also take
54 // full account of left and right side bearings on the text
55 CFont::TMeasureTextOutput output;
56 CFont::TMeasureTextInput input;
57 input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
58 TInt advance = iFont.MeasureText(aText,&input,&output);
60 /* expand the clipping rectangle to take account of any underline */
61 if (iUnderline == EUnderlineOn)
63 TInt underline_top = 0, underline_bottom = 0;
64 TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
65 TInt underlineStrikeoutOffset;
66 underlineStrikeoutOffset= BaselineCorrection();
67 underline_top+=underlineStrikeoutOffset;
68 underline_bottom+=underlineStrikeoutOffset;
69 BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
70 output.iBounds.iTl.iY = Min(output.iBounds.iTl.iY,underline_top);
71 output.iBounds.iBr.iY = Max(output.iBounds.iBr.iY,underline_bottom);
74 TInt leftBearing = output.iBounds.iTl.iX;
75 TInt rightBearing = advance - output.iBounds.iBr.iX;
80 box.iTl.iX=aPosition.iX-ascent;
81 box.iTl.iY=aPosition.iY-advance;
82 box.iBr.iX=aPosition.iX+output.iBounds.iBr.iY+1;//was +height-ascent+1;
83 box.iBr.iY=aPosition.iY;
86 box.iBr.iY-=leftBearing;
91 box.iTl.iY+=rightBearing;
96 box.iTl.iX=aPosition.iX-output.iBounds.iBr.iY;//was +ascent-height;
97 box.iTl.iY=aPosition.iY;
98 box.iBr.iX=aPosition.iX+ascent+1;
99 box.iBr.iY=aPosition.iY+advance;
102 box.iTl.iY+=leftBearing;
107 box.iBr.iY-=rightBearing;
110 DrawTextVertical(aText,box,ascent,aUp,ELeft,margin);
111 iBrushStyle=brushstyle;
115 /** Draws text clipped to the specified rectangle and then rotates it into a vertical
118 @param aText The text string to be drawn
119 @param aBox The clipping rectangle.
120 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is
121 rotated 90 degrees clockwise. */
122 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TRect& aBox,TBool aUp)
125 boxcpy.Move(iOrigin);
126 TRect oldcliprect(iUserClipRect);
127 iUserClipRect.Intersection(boxcpy);
128 DrawTextVertical(aText,aUp);
129 iUserClipRect=oldcliprect;
133 /** Draws text vertically, clipped to a specified rectangle,
134 using a baseline offset, alignment and margin.
136 @param aText The text string to be drawn.
137 @param aBox A rectangle to clip the text to.
138 @param aBaselineOffset Number of pixels to offset the baseline by.
139 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text is
140 rotated 90 degrees clockwise.
141 @param aVert Verticaly alignment of the text relative to the specified
143 @param aMargin Offset of the text from the position within the rectangle,
144 using the specified alignment. */
145 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
147 TInt aBaselineOffset,
152 DrawTextVertical(aText,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
156 /** Draws text vertically, clipped to a specified rectangle, using a baseline
157 offset, alignment and margin.
159 @param aText The text string to be drawn.
160 @param aBox A rectangle to clip the text to.
161 @param aBaselineOffset Number of pixels to offset the baseline by.
162 @param aTextWidth Number of pixels to clip the text to.
163 @param aUp ETrue, text is rotated 90 degrees anti-clockwise; EFalse, text
164 is rotated 90 degrees clockwise.
165 @param aVert Verticaly alignment of the text relative to the specified
167 @param aMargin Offset of the text from the position within the rectangle,
168 using the specified alignment. */
169 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,
171 TInt aBaselineOffset,
178 BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
179 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
181 boxcpy.Move(iOrigin);
183 if (boxcpy.Intersects(iUserClipRect))
185 boxcpy.Intersection(iUserClipRect);
188 iDevice->DrawingBegin(&iBrushBitmap);
189 CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
190 const CBitmapFont* fontaddress=iFont.Address();
195 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
197 iDevice->DrawingEnd(&iBrushBitmap);
198 BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
201 TInt width = iFont.MeasureText(aText);
202 TOpenFontMetrics metrics;
203 iFont.GetFontMetrics(metrics);
204 TInt textlength=aText.Length();
205 if(aTextWidth<0) aTextWidth=width;
207 coords.iX=aBox.iTl.iX;
208 TInt dirmult=aUp?-1:1;
209 coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
211 // iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
214 // hhhhhhhhhhhhhhhhhhhh
215 // 01234567890123456789
216 // aaaaaaaaaaaaaaaaaadd aUp=ETrue
218 // iX = 18 (baseline)
220 // ddaaaaaaaaaaaaaaaaaa aUp=EFalse
222 // iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
224 coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
228 coords.iY+=aMargin*dirmult;
231 coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
234 coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
237 iLastPrintPosition=coords;
238 coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
240 TInt prewidth=width+iCharJustExcess+iWordJustExcess;
241 iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
246 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
248 iDevice->DrawingEnd(&iBrushBitmap);
249 if (iAutoUpdateJustification)
250 UpdateJustificationVertical(aText,aUp);
254 TBool userintersect=boxcpy.Intersects(iUserClipRect);
255 if(!userintersect || !textlength || !width)
259 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
261 iDevice->DrawingEnd(&iBrushBitmap);
262 if (iAutoUpdateJustification)
263 UpdateJustificationVertical(aText,aUp);
266 boxcpy.Intersection(iUserClipRect);
267 TInt charjustexcess=iCharJustExcess;
268 TInt charjustnum=iCharJustNum;
269 TInt wordjustexcess=iWordJustExcess;
270 TInt wordjustnum=iWordJustNum;
271 TInt limit=iDefaultRegionPtr->Count();
272 for(TInt count=0;count<limit;count++)
275 Initialise the justification parameters to the original values at the start of each pass.
276 This means that any number of passes have exactly the same effect on the parameters as one pass;
277 that is, to reduce them by the numbers of items and pixels consumed.
279 iCharJustExcess = charjustexcess;
280 iCharJustNum = charjustnum;
281 iWordJustExcess = wordjustexcess;
282 iWordJustNum = wordjustnum;
284 iClipRect=(*iDefaultRegionPtr)[count];
285 if(!iClipRect.Intersects(boxcpy))
289 drawDevice->GetDrawRect(deviceRect);
290 BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
291 BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
292 BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
293 BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
295 iClipRect.Intersection(boxcpy);
297 Set up the parameter block for character positioning.
298 Draw left to right, because although the text is being drawn vertically,
299 it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
300 the characters in their normal orientation but in a vertical column.
302 CFont::TPositionParam param;
303 param.iText.Set(aText);
307 DoDrawTextVertical(param,fontaddress,aUp,aText.Length());
309 drawDevice->UpdateRegion(iClipRect);
313 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
315 iDevice->DrawingEnd(&iBrushBitmap);
316 if(iAutoUpdateJustification)
317 UpdateJustificationVertical(aText,aUp);
320 // Transform a vector, defined by a point relative to an origin, from left-to-right to up or down.
321 static void Rotate(TPoint& aPoint,const TPoint aOrigin,TBool aUp)
323 int dx = aPoint.iX - aOrigin.iX;
324 int dy = aPoint.iY - aOrigin.iY;
327 aPoint.iX = aOrigin.iX + dy;
328 aPoint.iY = aOrigin.iY - dx;
332 aPoint.iX = aOrigin.iX - dy;
333 aPoint.iY = aOrigin.iY + dx;
337 void CFbsBitGc::DoDrawTextVertical(CFont::TPositionParam& aParam,
338 const CBitmapFont* font,
339 TBool aUp,const TInt aEnd)
341 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
342 TInt charclipping=iClipRect.iTl.iY;
343 TPoint start_pen = aParam.iPen;
344 TInt underline_top = 0, underline_bottom = 0;
345 TInt underlineStrikeoutOffset;
347 //note using measured text here, but the full text string
348 underlineStrikeoutOffset= BaselineCorrection();
350 if (iUnderline == EUnderlineOn)
352 TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
353 underline_top+=underlineStrikeoutOffset;
354 underline_bottom+=underlineStrikeoutOffset;
355 BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
358 const TBool outlineAndShadow = (font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
359 if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
361 //For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used
362 //when drawing outline and shadow fonts.
363 BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
366 TInt strike_top = 0, strike_bottom = 0;
367 TBool italic = font->iAlgStyle.IsItalic();
368 if (italic || iStrikethrough == EStrikethroughOn)
370 GetStrikethroughMetrics(strike_top,strike_bottom);
371 if (iStrikethrough == EStrikethroughOn) //not for italic only, mimimum change
373 strike_top+=underlineStrikeoutOffset;
374 strike_bottom+=underlineStrikeoutOffset;
377 TInt italicheight=start_pen.iX;
378 italicheight += aUp ? -strike_top : strike_top;
379 TBool bold = font->iAlgStyle.IsBold();
380 TInt widthfactor = font->iAlgStyle.WidthFactor();
381 TInt heightfactor = font->iAlgStyle.HeightFactor();
382 TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
383 TBool outlineShadowOrAntialiased = (glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap ||
384 glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap);
386 RShapeInfo shapeInfo;
387 while (aParam.iPosInText < aEnd)
389 TPoint start_pen = aParam.iPen;
391 if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
393 Rotate(aParam.iPen,start_pen,aUp);
395 if(iCharJustExcess && iCharJustNum>0) // character clipping/justification
397 adjustment=CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
399 iClipRect.iTl.iY = aParam.iPen.iY + (aUp ? -adjustment : adjustment);
404 CFont::TPositionParam::TOutput* output = aParam.iOutput;
406 for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
408 TOpenFontCharMetrics characterParams;
409 const TUint8* bitmap;
411 //note may now be using a glyph code, and not a character
412 iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
413 TGlyphBitmapType glyphType = characterParams.GlyphType();
415 Rotate(output->iBounds.iTl,start_pen,aUp);
416 Rotate(output->iBounds.iBr,start_pen,aUp);
420 //the glyphType from the character takes precidence over the glyphType from the fon
421 case EAntiAliasedGlyphBitmap:
422 case EFourColourBlendGlyphBitmap:
423 DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphType);
426 case EDefaultGlyphBitmap:
427 case EMonochromeGlyphBitmap:
428 DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
429 bold,italic,italicheight,widthfactor,heightfactor,aUp);
433 //if the outline or shadow is not specified for the character, then use the font setting
434 if (outlineShadowOrAntialiased)
436 DoDrawCharacterVerticalAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,aUp,glyphBitmapTypeForFont);
440 DoDrawCharacterVertical(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,
441 bold,italic,italicheight,widthfactor,heightfactor,aUp);
447 iClipRect.iTl.iY = charclipping;
449 aParam.iPen.iY += aUp ? -adjustment : adjustment;
450 if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
452 adjustment=CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
453 aParam.iPen.iY += aUp ? -adjustment : adjustment;
456 if (shapeInfo.IsOpen())
458 if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
460 TRect ul; // underline
461 TRect st; // strikethrough
464 ul.SetRect(start_pen.iX+underline_top,aParam.iPen.iY,start_pen.iX+underline_bottom,start_pen.iY+1);
465 st.SetRect(start_pen.iX+strike_top,aParam.iPen.iY,start_pen.iX+strike_bottom,start_pen.iY+1);
466 ul.iTl.iY= ul.iBr.iY-ul.Height()*widthfactor;
467 st.iTl.iY= st.iBr.iY-st.Height()*widthfactor;
471 ul.SetRect(start_pen.iX-underline_bottom,start_pen.iY,start_pen.iX-underline_top,aParam.iPen.iY);
472 st.SetRect(start_pen.iX-strike_bottom,start_pen.iY,start_pen.iX-strike_top,aParam.iPen.iY);
473 ul.iBr.iY=ul.iTl.iY+ul.Height()*widthfactor;
474 st.iBr.iY=st.iTl.iY+st.Height()*widthfactor;
475 ul.iTl.iX++; // adjust for rect not including last line
481 if (iUnderline == EUnderlineOn)
482 if (ul.Intersects(iClipRect)) // checks for empty aRect as well
484 ul.Intersection(iClipRect);
485 drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
488 if (iStrikethrough == EStrikethroughOn)
489 if(st.Intersects(iClipRect)) // checks for empty aRect as well
491 st.Intersection(iClipRect);
492 drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
497 void CFbsBitGc::DoDrawCharacterVertical(const TPoint& aTopLeft,
498 const TSize& aDataSize,
507 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
508 TPoint printpos(aTopLeft);
509 TInt datalength = aDataSize.iWidth;
510 TInt dataheight = aDataSize.iHeight;
512 TInt16 repeatcount=0;
513 TInt xinc=aUp?1:-1,yinc=aUp?-1:1;
514 TUint32* slbuffer=drawDevice->ScanLineBuffer();
515 TInt slwords=(drawDevice->ScanLineBytes())<<3;
516 if(aItalic && aTopLeft.iY<aItalicPos)
518 for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
520 repeatcount=Load16(aData+(bitindex>>3));
521 repeatcount>>=bitindex&7;
522 TInt multilineflag=repeatcount&1;
526 TInt signedrepeatcount=aUp?repeatcount:-repeatcount;
529 for(TInt currentline=0;currentline<repeatcount;currentline++)
531 CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
532 OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
533 bitindex+=datalength;
534 TBool aboveitalicjump=EFalse;
535 if(aItalic && ((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos)))
536 aboveitalicjump=ETrue;
537 printpos.iX+=xinc*aHeightFactor;
538 if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
539 printpos.iY-=yinc*aWidthFactor;
546 for(TInt currentline=0;currentline<repeatcount;currentline++)
548 CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
549 OutputCharLineVertical(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor,aUp);
550 TBool aboveitalicjump=EFalse;
551 if((aUp && printpos.iX<aItalicPos) || (!aUp && printpos.iX>aItalicPos))
552 aboveitalicjump=ETrue;
553 printpos.iX+=xinc*aHeightFactor;
554 if(aboveitalicjump && ((aUp && printpos.iX>=aItalicPos) || (!aUp && printpos.iX<=aItalicPos)))
555 printpos.iY-=yinc*aWidthFactor;
560 CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
561 OutputCharLineVertical(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor,aUp);
562 printpos.iX+=signedrepeatcount*aHeightFactor;
564 bitindex+=datalength;
572 This function draws an anti-aliased character.
574 @param aTopLeft The position to output the character
575 @param aDataSize The size of the bitmap
576 @param aData the bitmap for outputt in their TOpenFontCharMetrics
577 @param aUp the direction of the text
578 @param aGlyphType the glyph type for the character
580 void CFbsBitGc::DoDrawCharacterVerticalAntiAliased(const TPoint& aTopLeft,
581 const TSize& aDataSize,
584 TGlyphBitmapType aGlyphBitmapType)
586 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
587 const int KBufferSize = 32;
588 TUint8 mask_buffer[KBufferSize];
593 const TUint32 penColor = iPenColor.Internal();
594 const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
595 const TUint32 brushColor = iBrushColor.Internal();
597 MOutlineAndShadowBlend* outlineAndShadow = NULL;
598 if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
600 TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
603 // Assert if MOutlineAndShadowBlend interface is not implemented
604 BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
610 top_row = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
611 bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iX - aTopLeft.iX);
612 left_col = Max(0,aTopLeft.iY - iClipRect.iBr.iY + 1);
613 right_col = Min(aDataSize.iWidth,aTopLeft.iY - iClipRect.iTl.iY + 1);
614 int y = aTopLeft.iY - (right_col - 1);
615 for (int col = right_col - 1; col >= left_col; col--, y++)
617 int x = aTopLeft.iX + top_row;
618 for (int row = top_row; row < bottom_row; row += KBufferSize, x += KBufferSize)
620 int length = KBufferSize;
621 if (length > bottom_row - row)
622 length = bottom_row - row;
623 const TUint8* p = aData + row * aDataSize.iWidth + col;
624 for (int i = 0; i < length; i++, p += aDataSize.iWidth)
626 if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
628 //There is a support for the interface with KOutlineAndShadowInterface id.
629 outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor, brushColor, mask_buffer);
633 drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
640 top_row = Max(0,aTopLeft.iX - iClipRect.iBr.iX + 1);
641 bottom_row = Min(aDataSize.iHeight,aTopLeft.iX - iClipRect.iTl.iX + 1);
642 left_col = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
643 right_col = Min(aDataSize.iWidth,iClipRect.iBr.iY - aTopLeft.iY);
644 int y = aTopLeft.iY + left_col;
645 for (int col = left_col; col < right_col; col++, y++)
647 int x = aTopLeft.iX - (bottom_row - 1);
648 for (int row = bottom_row; row > top_row; row -= KBufferSize, x += KBufferSize)
650 int length = KBufferSize;
651 if (length > row - top_row)
652 length = row - top_row;
653 const TUint8* p = aData + (row - 1) * aDataSize.iWidth + col;
654 for (int i = 0; i < length; i++, p -= aDataSize.iWidth)
656 if (EFourColourBlendGlyphBitmap == aGlyphBitmapType)
658 //There is a support for the interface with KOutlineAndShadowInterface id.
659 outlineAndShadow->WriteRgbOutlineAndShadow(x, y, length, penColor, shadowColor, brushColor, mask_buffer);
663 drawDevice->WriteRgbAlphaMulti(x,y,length,iPenColor,mask_buffer);
670 void CFbsBitGc::OutputCharLineVertical(TPoint aPrintPos,
680 if(aDataLength<=0) return;
681 TInt bufferwords=(aDataLength+31)>>5;
682 TUint32* bufferlimit=aBuffer+bufferwords;
685 TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
686 if((aDataLength&0x1f)==0) sparemask=0xffffffff;
687 *(bufferlimit-1)&=sparemask;
688 TUint32* bufferptr=aBuffer;
690 while(bufferptr<bufferlimit)
692 extrabit=*bufferptr>>31;
693 *bufferptr|=(*bufferptr<<1);
695 if(bufferptr<bufferlimit)
696 *bufferptr|=extrabit;
699 if((aDataLength&0x1f)==1)
702 *bufferlimit=extrabit;
708 BitMultiply(aBuffer,aDataLength,aWidthFactor);
709 aDataLength*=aWidthFactor;
710 bufferwords=(aDataLength+31)>>5;
711 bufferlimit=aBuffer+bufferwords;
715 if(aPrintPos.iY>=iClipRect.iBr.iY)
717 TInt pixelexcess=aPrintPos.iY-iClipRect.iBr.iY+1;
718 while(pixelexcess>=32)
725 if(aDataLength<=0) return;
728 TInt shiftup=32-pixelexcess;
729 TUint32* bufferptr=aBuffer;
730 while(bufferptr<bufferlimit)
732 *bufferptr>>=pixelexcess;
733 if(bufferptr<bufferlimit-1)
734 *bufferptr|=(*(bufferptr+1)<<shiftup);
737 aDataLength-=pixelexcess;
738 if(aDataLength<=0) return;
740 aPrintPos.iY=iClipRect.iBr.iY-1;
742 if(aPrintPos.iY-aDataLength<iClipRect.iTl.iY-1)
744 TInt pixelexcess=iClipRect.iTl.iY-1-aPrintPos.iY+aDataLength;
745 aDataLength-=pixelexcess;
746 if(aDataLength<=0) return;
751 if(aPrintPos.iY<iClipRect.iTl.iY)
753 TInt pixelexcess=iClipRect.iTl.iY-aPrintPos.iY;
754 while(pixelexcess>=32)
761 if(aDataLength<=0) return;
764 TInt shiftup=32-pixelexcess;
765 TUint32* bufferptr=aBuffer;
766 while(bufferptr<bufferlimit)
768 *bufferptr>>=pixelexcess;
769 if(bufferptr<bufferlimit-1)
770 *bufferptr|=(*(bufferptr+1)<<shiftup);
773 aDataLength-=pixelexcess;
774 if(aDataLength<=0) return;
776 aPrintPos.iY=iClipRect.iTl.iY;
778 if(aPrintPos.iY+aDataLength>iClipRect.iBr.iY)
780 TInt pixelexcess=aPrintPos.iY+aDataLength-iClipRect.iBr.iY;
781 aDataLength-=pixelexcess;
782 if(aDataLength<=0) return;
788 if(aPrintPos.iX>=iClipRect.iTl.iX && aPrintPos.iX<iClipRect.iBr.iX)
789 iDevice->iDrawDevice->WriteBinaryLineVertical(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode,aUp);
796 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,TBool aUp)
798 DrawTextVertical(aText,aParam,iLastPrintPosition,aUp);
801 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TBool aUp)
803 TBrushStyle brushstyle=iBrushStyle;
804 iBrushStyle=CGraphicsContext::ENullBrush;
805 TOpenFontMetrics metrics;
806 iFont.GetFontMetrics(metrics);
807 TInt ascent = metrics.MaxHeight();
808 TInt height = ascent + metrics.MaxDepth();
809 // The next few lines do much the same as TextWidthInPixels but pass
810 // the text in visual order instead of logical order and also take
811 // full account of left and right side bearings on the text
812 CFont::TMeasureTextOutput output;
813 CFont::TMeasureTextInput input;
814 input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
817 BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
818 input.iStartInputChar = aParam->iStart;
819 input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
821 TInt advance = iFont.MeasureText(aText,&input,&output);
823 //the box is not expanded by the underline position, as it is for horizontal text.
824 TInt leftBearing = output.iBounds.iTl.iX;
825 TInt rightBearing = advance - output.iBounds.iBr.iX;
830 box.iTl.iX=aPosition.iX-ascent;
831 box.iTl.iY=aPosition.iY-advance;
832 box.iBr.iX=aPosition.iX+height-ascent+1;
833 box.iBr.iY=aPosition.iY;
836 box.iBr.iY-=leftBearing;
841 box.iTl.iY+=rightBearing;
846 box.iTl.iX=aPosition.iX+ascent-height;
847 box.iTl.iY=aPosition.iY;
848 box.iBr.iX=aPosition.iX+ascent+1;
849 box.iBr.iY=aPosition.iY+advance;
852 box.iTl.iY+=leftBearing;
857 box.iBr.iY-=rightBearing;
860 DrawTextVertical(aText,aParam,box,ascent,aUp,ELeft,margin);
861 iBrushStyle=brushstyle;
864 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TBool aUp)
867 boxcpy.Move(iOrigin);
868 TRect oldcliprect(iUserClipRect);
869 iUserClipRect.Intersection(boxcpy);
870 DrawTextVertical(aText,aParam,aUp);
871 iUserClipRect=oldcliprect;
874 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TBool aUp,TTextAlign aVert,TInt aMargin)
876 DrawTextVertical(aText,aParam,aBox,aBaselineOffset,-1,aUp,aVert,aMargin);
879 EXPORT_C void CFbsBitGc::DrawTextVertical(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt aTextWidth,TBool aUp,TTextAlign aVert,TInt aMargin)
882 BG_ASSERT_ALWAYS(iFont.Handle()!=0,EBitgdiPanicNoFontSelected);
883 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
885 boxcpy.Move(iOrigin);
887 if (boxcpy.Intersects(iUserClipRect))
889 boxcpy.Intersection(iUserClipRect);
892 iDevice->DrawingBegin(&iBrushBitmap);
893 CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
894 const CBitmapFont* fontaddress=iFont.Address();
899 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
901 iDevice->DrawingEnd(&iBrushBitmap);
902 BG_PANIC_ALWAYS(EBitgdiPanicNoFontSelected);
904 CFont::TMeasureTextInput input;
905 //CFont::TMeasureTextOutput
908 BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
909 input.iStartInputChar = aParam->iStart;
910 input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
912 TInt width = iFont.MeasureText(aText,&input);
913 TOpenFontMetrics metrics;
914 iFont.GetFontMetrics(metrics);
915 TInt textlength=aText.Length();
916 if(aTextWidth<0) aTextWidth=width;
918 coords.iX=aBox.iTl.iX;
919 TInt dirmult=aUp?-1:1;
920 coords.iY=aUp?aBox.iBr.iY-1:aBox.iTl.iY;
922 // iX calculation, for example: ascent(a)=18 descent(d)=2 size=boxwidth=fontheight(h)=20 baseline=ascent
925 // hhhhhhhhhhhhhhhhhhhh
926 // 01234567890123456789
927 // aaaaaaaaaaaaaaaaaadd aUp=ETrue
929 // iX = 18 (baseline)
931 // ddaaaaaaaaaaaaaaaaaa aUp=EFalse
933 // iX = 1 (instead of 2 ie 20-18-1 which is boxwidth-baseline-1)
935 coords.iX+=aUp?aBaselineOffset:aBox.Width()-aBaselineOffset-1;
939 coords.iY+=aMargin*dirmult;
942 coords.iY+=(((aBox.iBr.iY-aBox.iTl.iY-aTextWidth)>>1)+aMargin)*dirmult;
945 coords.iY+=(aBox.iBr.iY-aBox.iTl.iY-aTextWidth-aMargin)*dirmult;
948 iLastPrintPosition=coords;
949 coords.iX+=fontaddress->iAlgStyle.iBaselineOffsetInPixels*dirmult;
951 TInt prewidth=width+iCharJustExcess+iWordJustExcess;
952 iLastPrintPosition.iY-=aUp?prewidth-1:-prewidth;
957 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
959 iDevice->DrawingEnd(&iBrushBitmap);
960 if (iAutoUpdateJustification)
961 UpdateJustificationVertical(aText,aParam,aUp);
965 TBool userintersect=boxcpy.Intersects(iUserClipRect);
966 if(!userintersect || !textlength || !width)
970 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
972 iDevice->DrawingEnd(&iBrushBitmap);
973 if (iAutoUpdateJustification)
974 UpdateJustificationVertical(aText,aParam,aUp);
977 boxcpy.Intersection(iUserClipRect);
978 TInt charjustexcess=iCharJustExcess;
979 TInt charjustnum=iCharJustNum;
980 TInt wordjustexcess=iWordJustExcess;
981 TInt wordjustnum=iWordJustNum;
982 TInt limit=iDefaultRegionPtr->Count();
983 for(TInt count=0;count<limit;count++)
986 Initialise the justification parameters to the original values at the start of each pass.
987 This means that any number of passes have exactly the same effect on the parameters as one pass;
988 that is, to reduce them by the numbers of items and pixels consumed.
990 iCharJustExcess = charjustexcess;
991 iCharJustNum = charjustnum;
992 iWordJustExcess = wordjustexcess;
993 iWordJustNum = wordjustnum;
995 iClipRect=(*iDefaultRegionPtr)[count];
996 if(!iClipRect.Intersects(boxcpy))
1000 drawDevice->GetDrawRect(deviceRect);
1001 BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
1002 BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
1003 BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
1004 BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
1006 iClipRect.Intersection(boxcpy);
1008 Set up the parameter block for character positioning.
1009 Draw left to right, because although the text is being drawn vertically,
1010 it is done by rotating the baseline 90 degrees and drawing in the ordinary way, not by drawing
1011 the characters in their normal orientation but in a vertical column.
1013 CFont::TPositionParam param;
1014 param.iText.Set(aText);
1015 param.iPen = coords;
1016 TInt endDraw = aText.Length();
1019 param.iPosInText = aParam->iStart;
1020 endDraw = Min(aText.Length(),aParam->iEnd);
1023 param.iPosInText = 0;
1026 DoDrawTextVertical(param,fontaddress,aUp,endDraw);
1028 drawDevice->UpdateRegion(iClipRect);
1030 if (brushRasterizer)
1032 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
1034 iDevice->DrawingEnd(&iBrushBitmap);
1035 if(iAutoUpdateJustification)
1036 UpdateJustificationVertical(aText,aParam,aUp);