--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1307 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <fntstore.h>
+#include <bitdraw.h>
+#include <bitstd.h>
+#include <bitdev.h>
+#include "BITPANIC.H"
+#include <shapeinfo.h>
+#include <bmalphablend.h>
+#include <bitdrawinterfaceid.h>
+#include <graphics/fbsrasterizer.h>
+#include "bitgcextradata.h"
+#include <graphics/gdi/gdiconsts.h>
+#include <graphics/gdi/gdistructs.h>
+
+
+/** Draws text at the last print position.
+
+@param aText The text string to be drawn. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText)
+ {
+ TTextParameters* param = NULL;
+ DrawText(aText,param,iLastPrintPosition,ELeft,CFont::EHorizontal);
+ }
+
+/** Draws text at the specified position and updates the print position.
+
+@param aText The text string to be drawn
+@param aCoords Coordinates to draw the text at. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TPoint& aCoords)
+ {
+ TTextParameters* param = NULL;
+ DrawText(aText,param,aCoords,ELeft,CFont::EHorizontal);
+ }
+
+
+/** Draws text clipped to the specified rectangle.
+
+@param aText The text string to be drawn
+@param aBox The clipping rectangle. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox)
+ {
+ TTextParameters* param = NULL;
+ DrawText(aText,param,aBox);
+ }
+
+
+/** Draws text clipped to the specified rectangle using a baseline offset,
+horizontal alignment and a margin.
+
+@param aText The text string to be drawn
+@param aBox The clipping rectangle.
+@param aBLOff An offset in pixels for the baseline from the normal position
+ (bottom of the rectangle minus the descent of the font).
+@param aHrz Horizontal alignment option relative to the specified rectangle.
+@param aMargin Offset to add to the position as calculated using specified
+ rectangle. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,TInt aBLOff,
+ TTextAlign aHrz,TInt aMargin)
+ {
+ TTextParameters* param = NULL;
+ DrawText(aText,param,aBox,aBLOff,-1,aHrz,aMargin);
+ }
+
+/** Draws text clipped to the specified rectangle.
+
+@param aText The text string to be drawn
+@param aBox The clipping rectangle. */
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TRect& aBox,
+ TInt aBLOff,TInt /*aTextWidth*/,
+ TTextAlign aHrz,TInt aMargin)
+ {
+// aTextWidth is not used here - try to abolish this - I think it is unneeded
+ TPoint p(aBox.iTl);
+ p.iY += aBLOff;
+ switch (aHrz)
+ {
+ case ELeft: p.iX += aMargin; break;
+ case ERight: p.iX = aBox.iBr.iX - aMargin; break;
+ case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
+ }
+ TTextParameters* param = NULL;
+ DrawText(aText,param,p,aHrz,CFont::EHorizontal,&aBox);
+ }
+
+
+/** The general DrawText routine that implements all the others.
+
+@param aText the text to be drawn
+@param aPosition the origin of the text
+@param aAlignment left, centred or right, around aPosition; not used if drawing vertically
+@param aDirection direction: left to right, right to left, or top to bottom
+@param aBox if non-null, filled before the text is drawn
+@param aTextBounds if non-null returns the bounding box of the text
+*/
+void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition,TTextAlign aAlignment,
+ CFont::TTextDirection aDirection,const TRect* aBox)
+ {
+ // sanity checks
+ BG_ASSERT_ALWAYS(iDevice,EBitgdiPanicNoDevicePresent);
+ BG_ASSERT_ALWAYS(iFont.Handle() != 0,EBitgdiPanicNoFontSelected);
+ const CBitmapFont* bitmap_font = iFont.Address();
+ BG_ASSERT_ALWAYS(bitmap_font != 0,EBitgdiPanicNoFontSelected);
+
+ // anything to do?
+ if (!aBox && !aText.Length())
+ return;
+
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+ TRect deviceRect;
+ drawDevice->GetDrawRect(deviceRect);
+
+ // measure the text
+ CFont::TMeasureTextInput measure_text_input;
+ measure_text_input.iCharJustNum = iCharJustNum;
+ measure_text_input.iCharJustExcess = iCharJustExcess;
+ measure_text_input.iWordJustNum = iWordJustNum;
+ measure_text_input.iWordJustExcess = iWordJustExcess;
+ measure_text_input.iFlags |= CFont::TMeasureTextInput::EFVisualOrder;
+ if (aParam)
+ {
+ BG_ASSERT_ALWAYS(aParam->iStart < aParam->iEnd ,EBitgdiPanicInvalidParameter);
+ measure_text_input.iStartInputChar = aParam->iStart;
+ measure_text_input.iEndInputChar = Min(aText.Length(),aParam->iEnd);
+ }
+ CFont::TMeasureTextOutput measure_text_output;
+ const int advance = iFont.MeasureText(aText,&measure_text_input,&measure_text_output);
+ TRect text_bounds = measure_text_output.iBounds;
+ TInt underlineStrikeoutOffset;
+
+ //this call is only needed in the case of linked fonts
+ //should this pass by one structure?
+ underlineStrikeoutOffset= BaselineCorrection();
+
+ if (iUnderline == EUnderlineOn)
+ {
+ TInt underline_top = 0, underline_bottom = 0;
+ TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
+ underline_top+=underlineStrikeoutOffset;
+ underline_bottom+=underlineStrikeoutOffset;
+ BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
+ text_bounds.iTl.iY = Min(text_bounds.iTl.iY,underline_top);
+ text_bounds.iBr.iY = Max(text_bounds.iBr.iY,underline_bottom);
+ }
+ if (iStrikethrough == EStrikethroughOn)
+ {
+ TInt strike_top = 0,strike_bottom = 0;
+ GetStrikethroughMetrics(strike_top,strike_bottom);
+ strike_top+=underlineStrikeoutOffset;
+ strike_bottom+=underlineStrikeoutOffset;
+ text_bounds.iTl.iY = Min(text_bounds.iTl.iY,strike_top);
+ text_bounds.iBr.iY = Max(text_bounds.iBr.iY,strike_bottom);
+ }
+ if (iUnderline == EUnderlineOn || iStrikethrough == EStrikethroughOn)
+ {
+ if (aDirection == CFont::EHorizontal)
+ {
+ text_bounds.iTl.iX = Min(text_bounds.iTl.iX, 0);
+ text_bounds.iBr.iX = Max(text_bounds.iBr.iX, advance);
+ }
+ else
+ {
+ text_bounds.iTl.iY = Min(text_bounds.iTl.iY, 0);
+ text_bounds.iBr.iY = Max(text_bounds.iBr.iY, advance);
+ }
+ }
+
+ // work out the text origin and new drawing position
+ TPoint text_origin = aPosition;
+ if (aDirection != CFont::EVertical)
+ {
+ const TInt leftSideBearing = Min(text_bounds.iTl.iX, 0);
+ const TInt rightSideBearing = Max(text_bounds.iBr.iX, advance);
+ switch (aAlignment)
+ {
+ // We are forbidding side-bearings to leak over the sides here,
+ // but still keeping the start and end pen positions within bounds.
+ case ELeft:
+ text_origin.iX -= leftSideBearing;
+ break;
+ case ERight:
+ text_origin.iX -= rightSideBearing;
+ break;
+ case ECenter:
+ // Centre is the average of left and right
+ text_origin.iX -= (leftSideBearing + rightSideBearing) >> 1;
+ break;
+ default:
+ break;
+ }
+ }
+ iLastPrintPosition = text_origin;
+ if (aDirection == CFont::EHorizontal)
+ iLastPrintPosition.iX += advance;
+ else
+ iLastPrintPosition.iY += advance;
+ text_origin.iY += bitmap_font->iAlgStyle.iBaselineOffsetInPixels;
+ text_bounds.Move(text_origin);
+ text_origin += iOrigin;
+
+ // determine clipping rectangle
+ TRect clip_rect = aBox ? *aBox : text_bounds;
+ AddRect(clip_rect);
+ clip_rect.Move(iOrigin);
+
+ if (UserClipRect(clip_rect))
+ {
+ if (iAutoUpdateJustification)
+ UpdateJustification(aText,aParam);
+ return; // nothing to do
+ }
+
+ SetupDevice();
+ iDevice->DrawingBegin(&iBrushBitmap);
+ CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+
+ // fill the box if necessary
+ if (aBox)
+ {
+ TRect fill_box = *aBox;
+ fill_box.Move(iOrigin);
+ RectFill(fill_box);
+ }
+
+ // decide which drawing routine to call
+ const TBool bold = bitmap_font->iAlgStyle.IsBold();
+ const TBool italic = bitmap_font->iAlgStyle.IsItalic();
+ const TBool multiw = bitmap_font->iAlgStyle.WidthFactor() > 1;
+ const TBool multih = bitmap_font->iAlgStyle.HeightFactor() > 1;
+
+ TOpenFontMetrics metrics;
+ iFont.GetFontMetrics(metrics);
+ const TInt maxwidth = metrics.MaxWidth();
+ // extext will be TRUE, if font is bold/italic/underline/strikethrough/anti-aliased or it
+ // has shadow/outline effects ON. Depending on these properties it will call the proper draw routine.
+ TBool extext = FALSE;
+ TBool normaltext = FALSE;
+ const TBool anti_aliased = (bitmap_font->GlyphBitmapType() == EAntiAliasedGlyphBitmap);
+ const TBool outlineAndShadow = (bitmap_font->GlyphBitmapType() == EFourColourBlendGlyphBitmap);
+ if (anti_aliased || outlineAndShadow)
+ {
+ if ((outlineAndShadow) && !(iBrushStyle == ENullBrush || iBrushStyle == ESolidBrush))
+ {
+ //For future compatibility it is better if brush style of ENullBrush or ESolidBrush is used
+ //when drawing outline and shadow fonts.
+ BG_PANIC_ALWAYS(EBitgdiPanicInvalidBrushStyle);
+ }
+ extext = TRUE;
+ }
+ else if (maxwidth > 30 || text_bounds.Height() > 32 || multiw || multih)
+ {
+ }
+ else if (iUnderline == EUnderlineOn || bold || italic || iStrikethrough == EStrikethroughOn ||
+ iCharJustNum > 0 || iWordJustNum > 0)
+ extext = TRUE;
+ else
+ normaltext = TRUE;
+
+ const TInt charjustexcess = iCharJustExcess;
+ const TInt charjustnum = iCharJustNum;
+ const TInt wordjustexcess = iWordJustExcess;
+ const TInt wordjustnum = iWordJustNum;
+
+ // draw the text to all clip rectangles in turn
+ int clip_rects = iDefaultRegionPtr->Count();
+ for (int i = 0; i < clip_rects; i++)
+ {
+ iClipRect = (*iDefaultRegionPtr)[i];
+ if (!iClipRect.Intersects(clip_rect))
+ continue;
+
+#ifdef _DEBUG
+ BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
+ BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
+#endif
+
+ iClipRect.Intersection(clip_rect);
+
+ // Set up the parameter block for character positioning.
+ CFont::TPositionParam param;
+ param.iDirection = static_cast<TInt16>(aDirection);
+ param.iText.Set(aText);
+ TInt endDraw = aText.Length();
+ if (aParam)
+ {
+ param.iPosInText = aParam->iStart;
+ endDraw = Min(aText.Length(),aParam->iEnd);
+ }
+ else
+ param.iPosInText = 0;
+ param.iPen = text_origin;
+
+ // Draw the text.
+ if (normaltext)
+ DoDrawText(param,endDraw);
+ else if (extext)
+ DoDrawTextEx(param,bitmap_font,endDraw,underlineStrikeoutOffset);
+ else
+ DoDrawTextLarge(param,bitmap_font,endDraw);
+
+ /*
+ Reset the justification parameters to their original values.
+ These will be updated as required later in code.
+ */
+ iCharJustExcess = charjustexcess;
+ iCharJustNum = charjustnum;
+ iWordJustExcess = wordjustexcess;
+ iWordJustNum = wordjustnum;
+
+ drawDevice->UpdateRegion(iClipRect);
+ }
+
+ if (brushRasterizer)
+ {
+ brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+ }
+ iDevice->DrawingEnd(&iBrushBitmap);
+ if (iAutoUpdateJustification)
+ UpdateJustification(aText,aParam);
+ }
+
+void CFbsBitGc::DoDrawText(CFont::TPositionParam& aParam, const TInt aEnd)
+ {
+ //const int n = aParam.iText.Length();
+ RShapeInfo shapeInfo;
+ while (aParam.iPosInText < /*n*/aEnd)
+ {
+ if (iFont.GetCharacterPosition2(aParam, shapeInfo))
+ {
+ const CFont::TPositionParam::TOutput* output = aParam.iOutput;
+ for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+ DoDrawCharacter(output->iBounds.iTl,output->iBitmapSize,output->iBitmap);
+ }
+ }
+ if (shapeInfo.IsOpen())
+ shapeInfo.Close();
+
+ }
+
+void CFbsBitGc::DoDrawCharacter(const TPoint& aTopLeft,
+ const TSize& aDataSize,
+ const TUint8* aData)
+ {
+ /*
+ Divert if the character is larger than expected; the criterion
+ for choosing this function is only a heuristic, because it's perfectly legal for
+ a character's bitmap to be wider than its escapement.
+
+ Use a dummy value (0) for semi-ascent because this character is not italic and so semi-ascent
+ is irrelevant; it's used for pseudo-italic slanting.
+ */
+ TInt dataheight = aDataSize.iHeight;
+ TInt datalength = aDataSize.iWidth;
+ if (datalength > 30 || dataheight > 32)
+ {
+ DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,FALSE,FALSE,0,1,1);
+ return;
+ }
+
+ TInt bitindex=0;
+ TInt16 repeatcount=0;
+ TUint32 binarydata[32];
+ TUint32* binarydataptr=binarydata;
+ TUint32* binarydataptrlimit;
+ for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+ {
+ repeatcount=Load16(aData+(bitindex>>3));
+ repeatcount>>=bitindex&7;
+ TInt multilineflag=repeatcount&1;
+ repeatcount>>=1;
+ repeatcount&=0xf;
+ bitindex+=5;
+ binarydataptrlimit=binarydata+charline+repeatcount;
+ if(multilineflag)
+ {
+ while(binarydataptr<binarydataptrlimit)
+ {
+ TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
+ TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
+ TInt bitshift=bitindex&7;
+ bitshift+=(chardataoffsetptr&3)<<3;
+ *binarydataptr=(*chardataword++)>>bitshift;
+ if(bitshift) *binarydataptr|=(*chardataword<<(32-bitshift));
+ bitindex+=datalength;
+ binarydataptr++;
+ }
+ }
+ else
+ {
+ TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
+ TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
+ TInt bitshift=bitindex&7;
+ bitshift+=(chardataoffsetptr&3)<<3;
+ TUint32 data=(*chardataword++)>>bitshift;
+ if(bitshift) data|=(*chardataword<<(32-bitshift));
+ while(binarydataptr<binarydataptrlimit)
+ *binarydataptr++=data;
+ bitindex+=datalength;
+ }
+ }
+ TPoint topleft(aTopLeft);
+ binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
+ if(datalength>0 && dataheight>0)
+ iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
+ }
+
+/**
+@internalTechnology
+
+This function retrieves the baseline offset from the metrics of the text currently being drawn.
+This is used to alter the positioning of underline and strikethrough on a linked font
+
+@return The baseline correction associated with the currently used font.
+*/
+TInt CFbsBitGc::BaselineCorrection()
+ {
+ TOpenFontMetrics metrics;
+ if (iFont.GetFontMetrics(metrics))
+ return metrics.BaselineCorrection();
+ else
+ return 0;
+ }
+
+void CFbsBitGc::DoDrawTextEx(CFont::TPositionParam& aParam,const CBitmapFont* font, const TInt aEnd, const TInt aUnderlineStrikethroughOffset)
+ {
+ const TInt charclipping = iClipRect.iBr.iX;
+ TPoint start_pen = aParam.iPen;
+ const TBool bold = font->iAlgStyle.IsBold();
+ const TBool italic = font->iAlgStyle.IsItalic();
+ const TGlyphBitmapType glyphBitmapTypeForFont = font->GlyphBitmapType();
+ const TBool outlineShadowOrAntialiased = ((glyphBitmapTypeForFont == EAntiAliasedGlyphBitmap) ||
+ (glyphBitmapTypeForFont == EFourColourBlendGlyphBitmap));
+
+ TInt underline_top = 0, underline_bottom = 0;
+ if (iUnderline == EUnderlineOn)
+ {
+ TInt err = GetUnderlineMetrics(underline_top,underline_bottom);
+ underline_top+=aUnderlineStrikethroughOffset;
+ underline_bottom+=aUnderlineStrikethroughOffset;
+ BG_ASSERT_DEBUG(err == KErrNone, EBitgdiPanicInvalidArg);
+ }
+ TInt strike_top = 0, strike_bottom = 0;
+ if (italic || iStrikethrough == EStrikethroughOn)
+ {
+ GetStrikethroughMetrics(strike_top,strike_bottom);
+ strike_top+=aUnderlineStrikethroughOffset;
+ strike_bottom+=aUnderlineStrikethroughOffset;
+ }
+
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+ RShapeInfo shapeInfo;
+ while (aParam.iPosInText < aEnd)
+ {
+ if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
+ continue;
+ TInt adjustment = 0;
+ if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
+ {
+ adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
+ if(adjustment < 0)
+ iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
+ }
+
+ const CFont::TPositionParam::TOutput* output = aParam.iOutput;
+ int semi_ascent = start_pen.iY + strike_top;
+
+ for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+ {
+ //get the character metrics for the glyph type
+ TOpenFontCharMetrics characterParams;
+ const TUint8* bitmap;
+ TSize size;
+ //note may now be using a glyph code, and not a character
+ iFont.GetCharacterData(aParam.iOutput[i].iCode,characterParams,bitmap,size);
+ TGlyphBitmapType glyphType = characterParams.GlyphType();
+
+ switch (glyphType)
+ {
+ case EAntiAliasedGlyphBitmap:
+ case EFourColourBlendGlyphBitmap:
+ DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphType);
+ break;
+
+ case EDefaultGlyphBitmap:
+ case EMonochromeGlyphBitmap:
+ DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
+ break;
+
+ default:
+ //if the outline or shadow is not specified for the character, then use the font setting
+ if (outlineShadowOrAntialiased)
+ {
+ DoDrawCharacterAntiAliased(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,glyphBitmapTypeForFont);
+ }
+ else
+ {
+ DoDrawCharacterEx(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,semi_ascent);
+ }
+ break;
+ }
+ }
+
+ iClipRect.iBr.iX = charclipping;
+ if (adjustment)
+ aParam.iPen.iX += adjustment;
+ if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
+ {
+ adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
+ aParam.iPen.iX += adjustment;
+ }
+ }
+ if (shapeInfo.IsOpen())
+ shapeInfo.Close();
+
+ if (iUnderline == EUnderlineOn)
+ {
+ TRect ul(start_pen.iX,start_pen.iY + underline_top,aParam.iPen.iX,start_pen.iY + underline_bottom);
+ if(ul.Intersects(iClipRect)) // checks for empty aRect as well
+ {
+ ul.Intersection(iClipRect);
+ drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
+ }
+ }
+
+ if (iStrikethrough == EStrikethroughOn)
+ {
+ TRect st(start_pen.iX,start_pen.iY + strike_top,aParam.iPen.iX,start_pen.iY + strike_bottom);
+ if(st.Intersects(iClipRect)) // checks for empty aRect as well
+ {
+ st.Intersection(iClipRect);
+ drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
+ }
+ }
+ }
+
+void CFbsBitGc::DoDrawCharacterEx(const TPoint& aTopLeft,
+ const TSize& aDataSize,
+ const TUint8* aData,
+ TBool aBold,TBool aItalic,TInt aSemiAscent)
+ {
+ /*
+ Divert if the character is larger than expected; the criterion
+ for choosing this function is only a heuristic, because it's perfectly legal for
+ a character's bitmap to be wider than its escapement.
+ */
+ TInt datalength = aDataSize.iWidth;
+ TInt dataheight = aDataSize.iHeight;
+ if (datalength > 30 || dataheight > 32)
+ {
+ DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,1,1);
+ return;
+ }
+
+ TInt bitindex=0;
+ TInt16 repeatcount=0;
+ TUint32 binarydata[32];
+ TUint32* binarydataptr=binarydata;
+ TUint32* binarydataptrlimit;
+ for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+ {
+ repeatcount=Load16(aData+(bitindex>>3));
+ repeatcount>>=bitindex&7;
+ TInt multilineflag=repeatcount&1;
+ repeatcount>>=1;
+ repeatcount&=0xf;
+ bitindex+=5;
+ binarydataptrlimit=binarydata+charline+repeatcount;
+ if(multilineflag)
+ {
+ while(binarydataptr<binarydataptrlimit)
+ {
+ CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
+ bitindex+=datalength;
+ binarydataptr++;
+ }
+ }
+ else
+ {
+ TUint32 data=0;
+ CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
+ while(binarydataptr<binarydataptrlimit)
+ *binarydataptr++=data;
+ bitindex+=datalength;
+ }
+ }
+ binarydataptr=binarydata;
+ binarydataptrlimit=binarydata+dataheight;
+ if(aBold)
+ {
+ TInt sparemask=(0xffffffff>>(32-datalength));
+ while(binarydataptr<binarydataptrlimit)
+ {
+ *binarydataptr&=sparemask;
+ *binarydataptr|=(*binarydataptr<<1);
+ ++binarydataptr;
+ }
+ binarydataptr=binarydata;
+ datalength++;
+ }
+ if(aItalic)
+ {
+ TInt skewlevel=aSemiAscent-aTopLeft.iY;
+ TUint32 sparemask=(0xffffffff>>(32-datalength));
+ binarydataptrlimit=binarydata+skewlevel;
+ while(binarydataptr<binarydataptrlimit)
+ *binarydataptr++<<=1;
+ binarydataptrlimit=binarydata+dataheight;
+ while(binarydataptr<binarydataptrlimit)
+ *binarydataptr++&=sparemask;
+ binarydataptr=binarydata;
+ datalength++;
+ }
+ TPoint topleft(aTopLeft);
+ binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,topleft);
+ if(datalength>0 && dataheight>0)
+ iDevice->iDrawDevice->WriteBinary(topleft.iX,topleft.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
+ }
+
+/**
+@internalTechnology
+
+This function draws an anti-aliased character.
+
+@param aTopLeft The position to output the character
+@param aDataSize The size of the bitmap
+@param aData the bitmap for outputt in their TOpenFontCharMetrics
+@param aGlyphType the glyph type for the character
+*/
+void CFbsBitGc::DoDrawCharacterAntiAliased(const TPoint& aTopLeft,
+ const TSize& aDataSize,
+ const TUint8* aData,
+ const TGlyphBitmapType aGlyphType)
+ {
+ const int top_row = Max(0,iClipRect.iTl.iY - aTopLeft.iY);
+ const int bottom_row = Min(aDataSize.iHeight,iClipRect.iBr.iY - aTopLeft.iY);
+ const int left_col = Max(0,iClipRect.iTl.iX - aTopLeft.iX);
+ const int right_col = Min(aDataSize.iWidth,iClipRect.iBr.iX - aTopLeft.iX);
+ const TUint8* p = aData + top_row * aDataSize.iWidth + left_col;
+ const int x = aTopLeft.iX + left_col;
+ int y = aTopLeft.iY + top_row;
+ const int cols = right_col - left_col;
+ const TUint32 penColor = iPenColor.Internal();
+ const TUint32 shadowColor = iFbsBitGcExtraData->ShadowColor().Internal();
+ const TUint32 brushColor = iBrushColor.Internal();
+
+ if (EFourColourBlendGlyphBitmap == aGlyphType)
+ {
+ MOutlineAndShadowBlend* outlineAndShadow = NULL;
+ const TInt err = iDevice->iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
+ if(err == KErrNone)
+ {
+ //There is a support for the interface with KOutlineAndShadowInterface id.
+ for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
+ outlineAndShadow->WriteRgbOutlineAndShadow(x, y, cols, penColor, shadowColor, brushColor, p);
+ }
+ else
+ {
+ // Assert if MOutlineAndShadowBlend interface is not implemented
+ BG_ASSERT_DEBUG(outlineAndShadow, EBitgdiPanicInvalidInterfaceHandle);
+ }
+ }
+ else
+ {
+ for (int row = top_row; row < bottom_row; row++, p += aDataSize.iWidth, y++)
+ iDevice->iDrawDevice->WriteRgbAlphaMulti(x,y,cols,iPenColor,p);
+ }
+ }
+
+void CFbsBitGc::DoDrawTextLarge(CFont::TPositionParam& aParam,const CBitmapFont* font,const TInt aEnd)
+ {
+ const TInt charclipping = iClipRect.iBr.iX;
+ TPoint start_pen = aParam.iPen;
+ const TInt strikeheight = start_pen.iY - (font->CBitmapFont::DoAscentInPixels() * 5/12) - 1;
+ const TBool bold = font->iAlgStyle.IsBold();
+ const TBool italic = font->iAlgStyle.IsItalic();
+ const TInt widthfactor=font->iAlgStyle.WidthFactor();
+ const TInt heightfactor=font->iAlgStyle.HeightFactor();
+
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+
+ RShapeInfo shapeInfo;
+ while (aParam.iPosInText < aEnd)
+ {
+ if (!iFont.GetCharacterPosition2(aParam, shapeInfo))
+ continue;
+ TInt adjustment = 0;
+ if(iCharJustExcess && iCharJustNum > 0) // character clipping/justification
+ {
+ adjustment = CGraphicsContext::JustificationInPixels(iCharJustExcess,iCharJustNum);
+ if(adjustment < 0)
+ iClipRect.iBr.iX = Min(aParam.iPen.iX + adjustment,iClipRect.iBr.iX);
+ }
+
+ const CFont::TPositionParam::TOutput* output = aParam.iOutput;
+ for (int i = 0; i < aParam.iOutputGlyphs; i++, output++)
+ DoDrawCharacterLarge(output->iBounds.iTl,output->iBitmapSize,output->iBitmap,bold,italic,strikeheight,
+ widthfactor,heightfactor);
+
+ iClipRect.iBr.iX = charclipping;
+ if (adjustment)
+ aParam.iPen.iX += adjustment;
+ if (iWordJustExcess > 0 && iWordJustNum > 0 && aParam.iOutput[0].iCode == 0x0020) // word justification
+ {
+ adjustment = CGraphicsContext::JustificationInPixels(iWordJustExcess,iWordJustNum);
+ aParam.iPen.iX += adjustment;
+ }
+ }
+ if (shapeInfo.IsOpen())
+ shapeInfo.Close();
+ const TInt ulwidth = Max(font->CBitmapFont::DoHeightInPixels() / 10, 1);
+ if (iUnderline == EUnderlineOn)
+ {
+ TInt ulstart = start_pen.iY + 1 + ulwidth / 2;
+ TRect ul(start_pen.iX,ulstart,aParam.iPen.iX,ulstart + ulwidth);
+ if(ul.Intersects(iClipRect)) // checks for empty aRect as well
+ {
+ ul.Intersection(iClipRect);
+ drawDevice->WriteRgbMulti(ul.iTl.iX,ul.iTl.iY,ul.iBr.iX-ul.iTl.iX,ul.iBr.iY-ul.iTl.iY,iPenColor,iDrawMode);
+ }
+ }
+
+ if (iStrikethrough == EStrikethroughOn)
+ {
+ TRect st(start_pen.iX,strikeheight,aParam.iPen.iX,strikeheight + ulwidth);
+ if(st.Intersects(iClipRect)) // checks for empty aRect as well
+ {
+ st.Intersection(iClipRect);
+ drawDevice->WriteRgbMulti(st.iTl.iX,st.iTl.iY,st.iBr.iX-st.iTl.iX,st.iBr.iY-st.iTl.iY,iPenColor,iDrawMode);
+ }
+ }
+ }
+
+void CFbsBitGc::DoDrawCharacterLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
+ TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
+ {
+ TInt datalength = aDataSize.iWidth;
+ TInt dataheight = aDataSize.iHeight;
+
+ if (aWidthFactor > 2 || aHeightFactor > 2)
+ {
+ DoDrawCharacterMultiplied(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
+ return;
+ }
+
+ if (datalength > 30 || dataheight > 32 || (aWidthFactor == 2 && datalength > 14))
+ {
+ DoDrawCharacterExLarge(aTopLeft,aDataSize,aData,aBold,aItalic,aSemiAscent,aWidthFactor,aHeightFactor);
+ return;
+ }
+
+ TInt italicheight=aSemiAscent-aTopLeft.iY;
+ if(aHeightFactor==2) italicheight>>=1;
+ TInt bitindex=0;
+ TInt16 repeatcount=0;
+ TUint32 binarydata[64];
+ TUint32* binarydataptr=binarydata;
+ TUint32* binarydataptrlimit;
+
+ for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+ {
+ repeatcount=Load16(aData+(bitindex>>3));
+ repeatcount>>=bitindex&7;
+ TInt multilineflag=repeatcount&1;
+ repeatcount>>=1;
+ repeatcount&=0xf;
+ bitindex+=5;
+ binarydataptrlimit=binarydata+charline+repeatcount;
+ if(multilineflag)
+ {
+ while(binarydataptr<binarydataptrlimit)
+ {
+ CopyCharWord(binarydataptr,aData+(bitindex>>3),bitindex&7);
+ bitindex+=datalength;
+ binarydataptr++;
+ }
+ }
+ else
+ {
+ TUint32 data=0;
+ CopyCharWord(&data,aData+(bitindex>>3),bitindex&7);
+ while(binarydataptr<binarydataptrlimit)
+ *binarydataptr++=data;
+ bitindex+=datalength;
+ }
+ }
+ binarydataptr=binarydata;
+ binarydataptrlimit=binarydata+dataheight;
+ if(aBold)
+ {
+ TInt sparemask=(0xffffffff>>(32-datalength));
+ while(binarydataptr<binarydataptrlimit)
+ {
+ *binarydataptr&=sparemask;
+ *binarydataptr|=(*binarydataptr<<1);
+ ++binarydataptr;
+ }
+ binarydataptr=binarydata;
+ datalength++;
+ }
+ if(aItalic)
+ {
+ TUint32 sparemask=(0xffffffff>>(32-datalength));
+ binarydataptrlimit=Min(binarydataptrlimit,binarydata+italicheight);
+ while(binarydataptr<binarydataptrlimit)
+ {
+ *binarydataptr<<=1;
+ *binarydataptr++&=0xfffffffe;
+ }
+ binarydataptrlimit=binarydata+dataheight;
+ while(binarydataptr<binarydataptrlimit)
+ *binarydataptr++&=sparemask;
+ binarydataptr=binarydata;
+ datalength++;
+ }
+ if(aWidthFactor==2)
+ {
+ BG_ASSERT_DEBUG(datalength<=16,EBitgdiPanicCharacterTooBig);
+ while(binarydataptr<binarydataptrlimit)
+ {
+ TUint32 singlemask=0x8000;
+ TUint32 doublemask=0xc0000000;
+ TUint32 newdata=0;
+ while(singlemask)
+ {
+ if(*binarydataptr&singlemask)
+ newdata|=doublemask;
+ singlemask>>=1;
+ doublemask>>=2;
+ }
+ *binarydataptr++=newdata;
+ }
+ datalength<<=1;
+ binarydataptr=binarydata;
+ }
+ if(aHeightFactor==2)
+ {
+ binarydataptr=binarydata+dataheight-1;
+ TUint32* tempptr=binarydataptr+dataheight;
+ while(binarydataptr>=binarydata)
+ {
+ *tempptr--=*binarydataptr;
+ *tempptr--=*binarydataptr--;
+ }
+ dataheight<<=1;
+ binarydataptr=binarydata;
+ }
+ TPoint startpos=aTopLeft;
+ binarydataptr=ClipBinaryArray(binarydata,binarydata+dataheight,1,datalength,dataheight,startpos);
+ if(datalength>0 && dataheight>0)
+ iDevice->iDrawDevice->WriteBinary(startpos.iX,startpos.iY,binarydataptr,datalength,dataheight,iPenColor,iDrawMode);
+ }
+
+void CFbsBitGc::DoDrawCharacterExLarge(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
+ TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+ TPoint printpos(aTopLeft);
+ const TInt datalength = aDataSize.iWidth;
+ const TInt dataheight = aDataSize.iHeight;
+ TInt bitindex=0;
+ TInt16 repeatcount=0;
+ TUint32* slbuffer=drawDevice->ScanLineBuffer();
+ const TInt slwords=(drawDevice->ScanLineBytes())<<3;
+ if(aItalic && aTopLeft.iY<aSemiAscent)
+ printpos.iX++;
+ for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+ {
+ repeatcount=Load16(aData+(bitindex>>3));
+ repeatcount>>=bitindex&7;
+ const TInt multilineflag=repeatcount&1;
+ repeatcount>>=1;
+ repeatcount&=0xf;
+ bitindex+=5;
+ if(multilineflag)
+ {
+ for(TInt currentline=0;currentline<repeatcount;currentline++)
+ {
+ CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+ OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+ bitindex+=datalength;
+ printpos.iY++;
+ if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+ if(aHeightFactor==2)
+ {
+ printpos.iY++;
+ if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+ }
+ }
+ }
+ else
+ {
+ if(aItalic)
+ {
+ for(TInt currentline=0;currentline<repeatcount;currentline++)
+ {
+ CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+ OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+ printpos.iY++;
+ if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+ if(aHeightFactor==2)
+ {
+ printpos.iY++;
+ if(printpos.iY==aSemiAscent && aItalic) printpos.iX--;
+ }
+ }
+ }
+ else
+ {
+ CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+ OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
+ printpos.iY+=repeatcount;
+ if(aHeightFactor==2) printpos.iY+=repeatcount;
+ }
+ bitindex+=datalength;
+ }
+ }
+ }
+
+void CFbsBitGc::DoDrawCharacterMultiplied(const TPoint& aTopLeft,const TSize& aDataSize,const TUint8* aData,
+ TBool aBold,TBool aItalic,TInt aSemiAscent,TInt aWidthFactor,TInt aHeightFactor)
+ {
+ CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
+ TPoint printpos(aTopLeft);
+ const TInt datalength = aDataSize.iWidth;
+ const TInt dataheight = aDataSize.iHeight;
+ TInt bitindex=0;
+ TInt16 repeatcount=0;
+ TUint32* slbuffer=drawDevice->ScanLineBuffer();
+ const TInt slwords=(drawDevice->ScanLineBytes())<<3;
+ if(aItalic && aTopLeft.iY<aSemiAscent)
+ printpos.iX++;
+ for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
+ {
+ repeatcount=Load16(aData+(bitindex>>3));
+ repeatcount>>=bitindex&7;
+ const TInt multilineflag=repeatcount&1;
+ repeatcount>>=1;
+ repeatcount&=0xf;
+ bitindex+=5;
+ if(multilineflag)
+ {
+ for(TInt currentline=0;currentline<repeatcount;currentline++)
+ {
+ CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+ OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+ bitindex+=datalength;
+ TBool aboveitalicjump=EFalse;
+ if(aItalic && printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
+ printpos.iY+=aHeightFactor;
+ if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
+ }
+ }
+ else
+ {
+ if(aItalic)
+ {
+ for(TInt currentline=0;currentline<repeatcount;currentline++)
+ {
+ CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+ OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor);
+ TBool aboveitalicjump=EFalse;
+ if(printpos.iY<aSemiAscent) aboveitalicjump=ETrue;
+ printpos.iY+=aHeightFactor;
+ if(aboveitalicjump && printpos.iY>=aSemiAscent) printpos.iX-=aWidthFactor;
+ }
+ }
+ else
+ {
+ CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength);
+ OutputCharLineMultiplied(printpos,slbuffer,datalength,repeatcount,aBold,aWidthFactor,aHeightFactor);
+ printpos.iY+=repeatcount*aHeightFactor;
+ }
+ bitindex+=datalength;
+ }
+ }
+ }
+
+void CFbsBitGc::OutputCharLineMultiplied(TPoint aPrintPos,TUint32* aBuffer,TInt aDataLength,TInt aNum,TBool aBold,TInt aWidthFactor,TInt aHeightFactor)
+ {
+ if(aDataLength<=0) return;
+ TInt bufferwords=(aDataLength+31)>>5;
+ TUint32* bufferlimit=aBuffer+bufferwords;
+ if(aBold)
+ {
+ TInt sparemask=(0xffffffff>>(32-(aDataLength&0x1f)));
+ if((aDataLength&0x1f)==0) sparemask=0xffffffff;
+ *(bufferlimit-1)&=sparemask;
+ TUint32* bufferptr=aBuffer;
+ TUint32 extrabit=0;
+ while(bufferptr<bufferlimit)
+ {
+ extrabit=*bufferptr>>31;
+ *bufferptr|=(*bufferptr<<1);
+ ++bufferptr;
+ if(bufferptr<bufferlimit)
+ *bufferptr|=extrabit;
+ }
+ aDataLength++;
+ if((aDataLength&0x1f)==1)
+ {
+ bufferwords++;
+ *bufferlimit=extrabit;
+ bufferlimit++;
+ }
+ }
+ if(aWidthFactor>1)
+ {
+ BitMultiply(aBuffer,aDataLength,aWidthFactor);
+ aDataLength*=aWidthFactor;
+ bufferwords=(aDataLength+31)>>5;
+ bufferlimit=aBuffer+bufferwords;
+ }
+ if(aPrintPos.iX<iClipRect.iTl.iX)
+ {
+ TInt pixelexcess=iClipRect.iTl.iX-aPrintPos.iX;
+ while(pixelexcess>=32)
+ {
+ aBuffer++;
+ bufferwords--;
+ aDataLength-=32;
+ pixelexcess-=32;
+ }
+ if(aDataLength<=0) return;
+ if(pixelexcess>0)
+ {
+ TInt shiftup=32-pixelexcess;
+ TUint32* bufferptr=aBuffer;
+ while(bufferptr<bufferlimit)
+ {
+ *bufferptr>>=pixelexcess;
+ if(bufferptr<bufferlimit-1)
+ *bufferptr|=(*(bufferptr+1)<<shiftup);
+ bufferptr++;
+ }
+ aDataLength-=pixelexcess;
+ if(aDataLength<=0) return;
+ }
+ aPrintPos.iX=iClipRect.iTl.iX;
+ }
+ if(aPrintPos.iX+aDataLength>iClipRect.iBr.iX)
+ {
+ TInt pixelexcess=aPrintPos.iX+aDataLength-iClipRect.iBr.iX;
+ aDataLength-=pixelexcess;
+ if(aDataLength<=0) return;
+ }
+ aNum*=aHeightFactor;
+ while(aNum>0)
+ {
+ if(aPrintPos.iY>=iClipRect.iTl.iY && aPrintPos.iY<iClipRect.iBr.iY)
+ iDevice->iDrawDevice->WriteBinaryLine(aPrintPos.iX,aPrintPos.iY,aBuffer,aDataLength,iPenColor,iDrawMode);
+ aPrintPos.iY++;
+ aNum--;
+ }
+ }
+
+void CFbsBitGc::CopyCharWord(TUint32* aBinaryDataPtr,const TUint8* aData,TInt aBitShift)
+ {
+ const TUint32* dataword=(TUint32*)(TInt(aData)&~3);
+ aBitShift+=(TInt(aData)-TInt(dataword))<<3;
+ *aBinaryDataPtr=*dataword++;
+ if(aBitShift<32) *aBinaryDataPtr>>=aBitShift;
+ if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
+ }
+
+void CFbsBitGc::CopyCharLine(TUint32* aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth)
+ {
+ aBitShift&=7;
+ TInt wordstocopy=(aCharWidth+31)>>5;
+ if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
+ TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
+ TUint32* dataword=(TUint32*)(TInt(aData)&~3);
+ aBitShift+=(TInt(aData)-TInt(dataword))<<3;
+ while(aBinaryDataPtr<ptrlimit)
+ {
+ *aBinaryDataPtr=*dataword++;
+ *aBinaryDataPtr>>=aBitShift;
+ if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
+ aBinaryDataPtr++;
+ }
+ }
+
+TUint32* CFbsBitGc::ClipBinaryArray(TUint32* aArray,TUint32* aArrayLimit,TInt aArrayWordWd,TInt& aDataWd,TInt& aDataHt,TPoint& aPos)
+ {
+ TUint32* arrayptr=aArray;
+ TInt clipdiff=iClipRect.iTl.iX-aPos.iX;
+ if(aArrayWordWd==1)
+ {
+ if(clipdiff>0)
+ {
+ while(arrayptr<aArrayLimit)
+ *arrayptr++>>=clipdiff;
+ aDataWd-=clipdiff;
+ aPos.iX=iClipRect.iTl.iX;
+ arrayptr=aArray;
+ }
+ if(aPos.iX+aDataWd>iClipRect.iBr.iX && aDataWd>0)
+ aDataWd=iClipRect.iBr.iX-aPos.iX;
+ clipdiff=iClipRect.iTl.iY-aPos.iY;
+ if(clipdiff>0)
+ {
+ aDataHt-=clipdiff;
+ arrayptr+=clipdiff;
+ aPos.iY=iClipRect.iTl.iY;
+ }
+ if(aPos.iY+aDataHt>iClipRect.iBr.iY && aDataHt>0)
+ aDataHt=iClipRect.iBr.iY-aPos.iY;
+ }
+ return(arrayptr);
+ }
+
+void CFbsBitGc::BitMultiply(TUint32* aBinaryDataPtr,TInt aBitLength,TInt aFactor)
+ {
+ TInt bitpos=aBitLength-1;
+ TUint32* wordpos=aBinaryDataPtr+(bitpos>>5);
+ TInt bitoffset=bitpos&0x1f;
+ TInt multbitpos=(aBitLength*aFactor)-1;
+ TUint32* multwordpos=aBinaryDataPtr+(multbitpos>>5);
+ TInt multbitoffset=multbitpos&0x1f;
+ while(bitpos>=0)
+ {
+ TUint32 bit=((*wordpos)>>bitoffset)&1;
+ TInt next=multbitpos-aFactor;
+ while(multbitpos>next)
+ {
+ if(bit) *multwordpos|=(1<<multbitoffset);
+ else *multwordpos&=~(1<<multbitoffset);
+ multbitpos--;
+ multbitoffset--;
+ if(multbitoffset<0)
+ {
+ multbitoffset=31;
+ multwordpos--;
+ }
+ }
+ bitpos--;
+ bitoffset--;
+ if(bitoffset<0)
+ {
+ bitoffset=31;
+ wordpos--;
+ }
+ }
+ }
+
+void CFbsBitGc::GetStrikethroughMetrics(TInt& aTop,TInt& aBottom)
+/** Get the top and bottom of a strikethrough line for the current font, relative to the baseline.*/
+ {
+ aTop = -(iFont.AscentInPixels() * 5/12) - 1;
+ aBottom = aTop + Max(iFont.HeightInPixels() / 10,1);
+ }
+
+/** APIExtension can contain as many additional methods as is required by
+CGraphicsContext after its original conception. It takes 3 parameters.
+Function is exported due to constrains of retaining BC with earlier versions.
+This is not used directly by external methods, instead it is called by a named
+method in CGraphicsContext which passes the relivant arguements including an
+unique identifier for the required action.
+@param aUid The unique identifier for the method that is required. Selected
+internally by a series of "if" statements.
+@see Valid Uid identifiers are listed in header gdi.h
+@see CGraphicsContext
+@param aOutput is a TAny pointer to a reference. Used to output data as the structure
+does not need to be instantiated before the function call this adds greater
+flexibility.
+@param aInput is a TAny pointer used to input data.
+*/
+EXPORT_C TInt CFbsBitGc::APIExtension(TUid aUid, TAny*& aOutput, TAny* aInput)
+ {
+ if (aUid == KGetUnderlineMetrics)
+ {
+ APIExGetUnderlineMetrics(aOutput);
+ return KErrNone;
+ }
+ else if (aUid == KSetShadowColor)
+ {
+ return APIExSetShadowColor(aInput);
+ }
+ else if (aUid == KGetShadowColor)
+ {
+ return APIExGetShadowColor(aOutput);
+ }
+ else if (aUid == KDrawTextInContextUid)
+ {
+ TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+ DrawText(contextParam->iText, &contextParam->iParam, contextParam->iPosition);
+ return KErrNone;
+ }
+ else if (aUid == KDrawBoxTextInContextUid)
+ {
+ TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+ DrawText(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iAlign,contextParam->iMargin);
+ return KErrNone;
+ }
+ else if (aUid == KDrawTextInContextVerticalUid)
+ {
+ TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+ DrawTextVertical(contextParam->iText, &contextParam->iParam, contextParam->iPosition,contextParam->iUp);
+ return KErrNone;
+ }
+ else if (aUid == KDrawBoxTextInContextVerticalUid)
+ {
+ TDrawTextInContextInternal* contextParam = (TDrawTextInContextInternal*)aInput;
+ DrawTextVertical(contextParam->iText,&contextParam->iParam,contextParam->iBox,contextParam->iBaselineOffset,contextParam->iUp,contextParam->iAlign,contextParam->iMargin);
+ return KErrNone;
+ }
+ else if (aUid == KUidIsFbsBitmapGc)
+ {
+ return APIExIsFbsBitGc(aOutput);
+ }
+ /* Future cases may be placed here later.*/
+ else
+ return CBitmapContext::APIExtension(aUid, aOutput, aInput);
+ }
+
+
+
+
+
+
+
+
+
+//The methods listed above in APIExtension follow here with the prefix APIEx.
+void CFbsBitGc::APIExGetUnderlineMetrics(TAny*& aOutput)
+ {
+ const TInt width = Max(iFont.HeightInPixels() / 10,1);
+ TTwoTInt* ptr = (TTwoTInt*)aOutput;
+ ptr->iTop = 1 + width / 2;
+ ptr->iBottom = (ptr->iTop) + width;
+ }
+
+TInt CFbsBitGc::APIExSetShadowColor(TAny* aShadowColor)
+ {
+ iFbsBitGcExtraData->SetShadowColor(*(reinterpret_cast<TRgb*>(aShadowColor)));
+ return KErrNone;
+ }
+
+TInt CFbsBitGc::APIExGetShadowColor(TAny*& aShadowColor)
+ {
+ TRgb* output = reinterpret_cast<TRgb*>(aShadowColor);
+ *output = iFbsBitGcExtraData->ShadowColor();
+ return KErrNone;
+ }
+
+TInt CFbsBitGc::APIExIsFbsBitGc(TAny*& aIsCFbsBitGc)
+ {
+ TBool *output = reinterpret_cast<TBool*>(aIsCFbsBitGc);
+ *output = ETrue;
+ return KErrNone;
+ }
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam)
+ {
+ DrawText(aText,aParam,iLastPrintPosition,ELeft,CFont::EHorizontal);
+ }
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TPoint& aPosition)
+ {
+ DrawText(aText,aParam,aPosition,ELeft,CFont::EHorizontal);
+ }
+
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox)
+ {
+ TRect boxcpy(aBox);
+ boxcpy.Move(iOrigin);
+ if(!iUserClipRect.Intersects(boxcpy)) return;
+ TRect oldcliprect(iUserClipRect);
+ iUserClipRect.Intersection(boxcpy);
+ DrawText(aText,aParam);
+ iUserClipRect=oldcliprect;
+ }
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TTextAlign aHrz,TInt aMargin)
+ {
+ DrawText(aText,aParam,aBox,aBaselineOffset,-1,aHrz,aMargin);
+ }
+
+EXPORT_C void CFbsBitGc::DrawText(const TDesC& aText,const TTextParameters* aParam,const TRect& aBox,TInt aBaselineOffset,TInt /*aTextWidth*/,TTextAlign aHrz,TInt aMargin)
+ {
+ // aTextWidth is not used here - try to abolish this - I think it is unneeded
+ TPoint p(aBox.iTl);
+ p.iY += aBaselineOffset;
+ switch (aHrz)
+ {
+ case ELeft: p.iX += aMargin; break;
+ case ERight: p.iX = aBox.iBr.iX - aMargin; break;
+ case ECenter: p.iX += aBox.Width() / 2 + aMargin; break;
+ }
+ DrawText(aText,aParam,p,aHrz,CFont::EHorizontal,&aBox);
+ }