diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/bitgdi/sbit/TEXT.CPP --- /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 +#include +#include +#include +#include "BITPANIC.H" +#include +#include +#include +#include +#include "bitgcextradata.h" +#include +#include + + +/** 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(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>3)); + repeatcount>>=bitindex&7; + TInt multilineflag=repeatcount&1; + repeatcount>>=1; + repeatcount&=0xf; + bitindex+=5; + binarydataptrlimit=binarydata+charline+repeatcount; + if(multilineflag) + { + while(binarydataptr>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(binarydataptr0 && 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>3)); + repeatcount>>=bitindex&7; + TInt multilineflag=repeatcount&1; + repeatcount>>=1; + repeatcount&=0xf; + bitindex+=5; + binarydataptrlimit=binarydata+charline+repeatcount; + if(multilineflag) + { + while(binarydataptr>3),bitindex&7); + bitindex+=datalength; + binarydataptr++; + } + } + else + { + TUint32 data=0; + CopyCharWord(&data,aData+(bitindex>>3),bitindex&7); + while(binarydataptr>(32-datalength)); + while(binarydataptr>(32-datalength)); + binarydataptrlimit=binarydata+skewlevel; + while(binarydataptr0 && 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 (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>3)); + repeatcount>>=bitindex&7; + TInt multilineflag=repeatcount&1; + repeatcount>>=1; + repeatcount&=0xf; + bitindex+=5; + binarydataptrlimit=binarydata+charline+repeatcount; + if(multilineflag) + { + while(binarydataptr>3),bitindex&7); + bitindex+=datalength; + binarydataptr++; + } + } + else + { + TUint32 data=0; + CopyCharWord(&data,aData+(bitindex>>3),bitindex&7); + while(binarydataptr>(32-datalength)); + while(binarydataptr>(32-datalength)); + binarydataptrlimit=Min(binarydataptrlimit,binarydata+italicheight); + while(binarydataptr>=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>3)); + repeatcount>>=bitindex&7; + const TInt multilineflag=repeatcount&1; + repeatcount>>=1; + repeatcount&=0xf; + bitindex+=5; + if(multilineflag) + { + for(TInt currentline=0;currentline>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>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>3)); + repeatcount>>=bitindex&7; + const TInt multilineflag=repeatcount&1; + repeatcount>>=1; + repeatcount&=0xf; + bitindex+=5; + if(multilineflag) + { + for(TInt currentline=0;currentline>3),bitindex&7,datalength); + OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor); + bitindex+=datalength; + TBool aboveitalicjump=EFalse; + if(aItalic && printpos.iY=aSemiAscent) printpos.iX-=aWidthFactor; + } + } + else + { + if(aItalic) + { + for(TInt currentline=0;currentline>3),bitindex&7,datalength); + OutputCharLineMultiplied(printpos,slbuffer,datalength,1,aBold,aWidthFactor,aHeightFactor); + TBool aboveitalicjump=EFalse; + if(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>31; + *bufferptr|=(*bufferptr<<1); + ++bufferptr; + if(bufferptr1) + { + BitMultiply(aBuffer,aDataLength,aWidthFactor); + aDataLength*=aWidthFactor; + bufferwords=(aDataLength+31)>>5; + bufferlimit=aBuffer+bufferwords; + } + if(aPrintPos.iX=32) + { + aBuffer++; + bufferwords--; + aDataLength-=32; + pixelexcess-=32; + } + if(aDataLength<=0) return; + if(pixelexcess>0) + { + TInt shiftup=32-pixelexcess; + TUint32* bufferptr=aBuffer; + while(bufferptr>=pixelexcess; + if(bufferptriClipRect.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.iYiDrawDevice->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>=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>=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<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(aShadowColor))); + return KErrNone; + } + +TInt CFbsBitGc::APIExGetShadowColor(TAny*& aShadowColor) + { + TRgb* output = reinterpret_cast(aShadowColor); + *output = iFbsBitGcExtraData->ShadowColor(); + return KErrNone; + } + +TInt CFbsBitGc::APIExIsFbsBitGc(TAny*& aIsCFbsBitGc) + { + TBool *output = reinterpret_cast(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); + }