diff -r 000000000000 -r 88edb906c587 svgtopt/SVG/SVGImpl/src/SVGTextElementImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgtopt/SVG/SVGImpl/src/SVGTextElementImpl.cpp Wed Nov 03 18:56:10 2010 +0200 @@ -0,0 +1,3395 @@ +/* +* Copyright (c) 2003 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: SVG Implementation source file + * +*/ + + +#if !defined(__E32BASE_H__) +#include +#endif +#include "SVGTextElementImpl.h" +#include "SVGDocumentImpl.h" +#include "SVGEngineImpl.h" +#include "SVGSchemaData.h" +#include "SVGFloatCssValueImpl.h" +#include "SVGStrCssValueImpl.h" +#include "SVGIntCssValueImpl.h" +#include "SVGPaintCssValueImpl.h" + +#include "GfxLine2D.h" +#include "GfxStroke.h" +#include "GfxColor.h" + +#include "GfxAffineTransform.h" + + +#include "SVGStringTokenizer.h" +#include "GfxGeneralPath.h" + +#include "SVGGlyphElementImpl.h" +//#include "SvgDefaultFont.h" +#include "SVGErrorImpl.h" +#include "SVGFourPointRect.h" + +#include "hal.h" +#include "hal_data.h" + +#define KDefaultFontSize 10 +#define KOne 1 +#define KDefaultUnitsPerEm 1000 + +_LIT( KGlyphNameNone, "GlyphNameNone"); +_LIT( KDefaultFont, "serif" ); // Similar changes should be applied to Gfx2dGcOpenVg.cpp file + +// --------------------------------------------------------------------------- +// Two phase construction +// --------------------------------------------------------------------------- + +CSvgTextElementImpl* CSvgTextElementImpl::NewL( const TUint8 aElemID, + CSvgDocumentImpl* aDoc ) + + { + CSvgTextElementImpl*self = new ( ELeave ) CSvgTextElementImpl( aDoc ); + CleanupStack::PushL( self ); + + + self->ConstructL( aElemID ); + CleanupStack::Pop(); + + return self; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- + + +CSvgTextElementImpl* CSvgTextElementImpl::NewLC( const TUint8 aElemID, + CSvgDocumentImpl* aDoc ) + { + CSvgTextElementImpl*self = new ( ELeave ) CSvgTextElementImpl( aDoc ); + CleanupStack::PushL( self ); + self->ConstructL( aElemID ); + + return self; + } + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +CSvgTextElementImpl::CSvgTextElementImpl( CSvgDocumentImpl* aDoc ): iOffset(0) + { + SetOwnerDocument(aDoc); + + } + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- + +void CSvgTextElementImpl::ConstructL( const TUint8 aElemID ) + { + CSvgElementImpl::InitializeL( aElemID ); + + + iArrayX = new ( ELeave ) CArrayFixFlat( 1 ); + iArrayY = new ( ELeave ) CArrayFixFlat( 1 ); + + #ifdef SVG_FLOAT_BUILD + iArrayX->AppendL( TFloatFixPt(0) ); + iArrayY->AppendL( TFloatFixPt(0) ); + + iPoint.iX = TFloatFixPt( 0 ); + iPoint.iY = TFloatFixPt( 0 ); + #else + iArrayX->AppendL( TFloatFixPt( 0 , ETrue) ); + iArrayY->AppendL( TFloatFixPt( 0 , ETrue) ); + + + iPoint.iX = TFloatFixPt( 0 ,ETrue); + iPoint.iY = TFloatFixPt( 0 ,ETrue); + #endif + + iText = HBufC::NewL( 2 ); + // *iText = _L( " " ); + + iG1 = HBufC::NewL( 0 ); + iG2 = HBufC::NewL( 0 ); + + iU1 = HBufC::NewL( 0 ); + iU2 = HBufC::NewL( 0 ); + + iSvgStyleProperties = new(ELeave) RPointerArray(KCSS_MAX_ATTR); + User::LeaveIfError( iSvgStyleProperties->Append( NULL ) ); + iSvgStyleProperties->Remove( 0 ); + + iTriedLoadingSVGFonts = EFalse; + iNeedToCacheGlyphs = EFalse; + + iSvgTransformable = CSvgTransformableImpl::NewL(); + + //set in the default font...just in case + SetFontFamilyL(KDefaultFont ); //_L("DefaultFont")); + + iEditable = EFalse; + + if (OwnerDocument()) + { + ((CSvgDocumentImpl*)OwnerDocument())->AddInternalMouseListener( this ); + } + + //gets the default font that the graphics context holds at the start + //should be whatever the client side specified as the initial fontspec + //GetCurrentFontScaled(iBitmapFont, iBitmapFontSpec); + + } + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +CSvgTextElementImpl::~CSvgTextElementImpl() + { + + iGlyphElements.Close(); + + if ( iFamilies ) + { + iFamilies->Reset(); + delete iFamilies; + iFamilies = NULL; + } + if ( iArrayX ) + { + iArrayX->Reset(); + delete iArrayX; + iArrayX = NULL; + } + if ( iArrayY ) + { + iArrayY->Reset(); + delete iArrayY; + iArrayY = NULL; + } + if ( iArrayRotate ) + { + iArrayRotate->Reset(); + delete iArrayRotate; + iArrayRotate = NULL; + } + + if ( iText ) + { + delete iText; + iText = NULL; + } + + if ( iG1 ) + { + delete iG1; + iG1 = NULL; + } + + if ( iG2 ) + { + delete iG2; + iG2 = NULL; + } + + if ( iU1) + { + delete iU1; + iU1 = NULL; + } + + if ( iU2 ) + { + delete iU2; + iU2 = NULL; + } + + ((CSvgDocumentImpl*)OwnerDocument())->RemoveInternalMouseListener( this ); + // The Font is owned by TextElement + // now as each text element may have its own specific font + // and keeping one copy at Gc level will not work. + // Gc is just refering to the Font from Textelement, so + // need to free it here. Note the iWsSceenDevice initialisation + // was done in draw as it needs to happens in main thread in case + // of progressive rendering. + // + if (iBitmapFont) + { + CSvgBitmapFontProvider *tempBitmapFontProvider = ((CSvgDocumentImpl*)iOwnerDocument)->GetBitmapFontProvider(); + tempBitmapFontProvider->ReleaseFont(iBitmapFont); + iBitmapFont = NULL; + + } + + if ( iSvgStyleProperties ) + { + iSvgStyleProperties->Close(); + delete iSvgStyleProperties; + iSvgStyleProperties = NULL; + } + + } + + +// ******************************************************* +// From SVG DOM +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TInt32 CSvgTextElementImpl::NumberOfChars() + { + return iText->Length(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::GetX( CArrayFix* aX ) + { + if (aX->Count() > 0) + { + aX->At( 0 ) = iPoint.iX; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::GetY( CArrayFix* aY ) + { + if (aY->Count() > 0 ) + { + aY->At( 0 ) = iPoint.iY; + } + } + +// ******************************************************* +// SVG Implementation + +TBool CSvgTextElementImpl::IsNumberAttributeValid( const TDesC& aValue ) + + { + TBool lValidAttr = EFalse; + + if ( aValue.Length() > 0 ) + { + + TLex lInput ( aValue ); + + TChar tmpchar; + while ( lInput.Peek() != 0 ) + { + tmpchar = lInput.Get(); + if( !(tmpchar.IsDigit()) && !(tmpchar == '.') && !(tmpchar == '-') && !(tmpchar == ' ') ) + { + lValidAttr = EFalse; + break; + } + lValidAttr = ETrue; + } + + } + + return lValidAttr; +} + +// --------------------------------------------------------------------------- +// xml:space is an inheritable attribute which can have one of two values: +// +// default (the initial/default value for xml:space) - When xml:space="default": +// - Remove all newline characters. +// - Convert all tab characters into space characters. +// - Strip off all leading and trailing space characters. +// - All contiguous space characters will be consolidated. +// +// preserve - When xml:space="preserve" : +// - Convert all newline and tab characters into space characters. +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetTextL( const TDesC& aText ) + { + _LIT( KPreserve, "preserve" ); + _LIT( KDefault, "default"); + if ( iText ) + { + delete iText; + iText = NULL; + } + + iText = aText.AllocL(); + TPtr textDes = iText->Des(); + TBool def = ETrue; + + // Get the xml:space value. + TBuf<20> lXmlspace; + + if(XMLSpace() == KPreserve) + { + lXmlspace=KPreserve; + def=EFalse; + } + else if(XMLSpace() == KDefault) + { + lXmlspace=KDefault; + } + // xml:space is inherited if not specified + if ( lXmlspace!= KPreserve && lXmlspace != KDefault) + { + // Traverse to the nearest parent element which has the xml:space + // If no xml:space then render using xml:space="default" + CSvgElementImpl *lRoot=(CSvgElementImpl *)this->ParentNode(); + while(lRoot) + { + if ((lRoot->XMLSpace() == KPreserve)) + { + def = EFalse; + break; + } + else if(lRoot->XMLSpace()==KDefault) + { + break; + } + lRoot=(CSvgElementImpl *)lRoot->ParentNode(); + } + + } + + _LIT(KSpace, " "); + // default + if ( def && lXmlspace != KPreserve ) + { + + // Remove leading, trailing and contiguous spaces + textDes.TrimAll(); + + for (TInt i = textDes.Length() - 1; i >= 0; i--) + { + + // Remove new line character + if (textDes[i] == '\n' || + textDes[i] == '\r') + { + textDes.Delete(i,1); + } + + // Tab to be replaced with space. + if(textDes[i] == '\t') + { + textDes.Replace(i,1,KSpace); + } + } + } + // preserve + else + { + + for ( TInt i = 0; i < textDes.Length(); i++ ) + { + // ms-dos carriage return contains two characters: 13, 10 + const TInt KCarriageReturn1 = 13; + const TInt KCarriageReturn2 = 10; + + if ( i + 1 < textDes.Length() && + (TInt)textDes[i] == KCarriageReturn1 && + (TInt)textDes[i+1] == KCarriageReturn2 ) + { + textDes[i] = ' '; + textDes.Delete( i+1, 1 ); + } + + // New line and tab should be replaced by space character. + if (textDes[i] == '\n' ||textDes[i] == '\t') + { + textDes.Replace(i,1, KSpace); + } + } + } + + iUseDefaultSVGFont = IsMostBasicLatin(); + iNeedToCacheGlyphs = ETrue; + } + +void CSvgTextElementImpl::CacheGlyphsForText() +{ + if (!iNeedToCacheGlyphs || iText == NULL || iText->Length() == 0 || iSVGFont == NULL) + { + return; + } + // Reset the cache first + iGlyphElements.Reset(); + //initialize the glyph elements cache array...this seems expensive any other way to do this + TInt textLength = iText->Length(); + for (TInt j = 0; j < textLength; j++) + { + //it might actually be better to put a ptr to missing glyph in here instead of null + iGlyphElements.Append(NULL); + } + + //we have an svg font... + if ( iSVGFont->HasChildNodes() ) + { + /*******************************/ + /* Text Caching functionality, */ + /*******************************/ + + CSvgElementImpl* lFirstChild = ( CSvgElementImpl * ) iSVGFont->FirstChild(); + + while ( lFirstChild != NULL ) + { + /***********************/ + /*CACHING HKERN ELEMENT*/ + /***********************/ + if( lFirstChild->ElemID() == KSvgHkernElement) + { + //1 per font + iHkernElement = lFirstChild; + } + + /******************************/ + /*CACHING MISSINGGLYPH ELEMENT*/ + /******************************/ + + if ( lFirstChild->ElemID() == KSvgMissingglyphElement) + { + //1 per font + iMissingGlyphElement = lFirstChild; + } + + /***********************/ + /* FONTFACE ELEMENT */ + /***********************/ + + if ( lFirstChild->ElemID() == KSvgFontfaceElement ) + { + //1 per font + iFontFaceElement = lFirstChild; + } + + /***********************/ + /* CACHE GLYPH ELEMENT */ + /***********************/ + + if ( lFirstChild->ElemID() == KSvgGlyphElement) + { + TPtrC16 lUnicode; + lFirstChild->GetAttributeDes( KAtrUnicode, lUnicode ); + + TPtr textDes = iText->Des(); + + TPtrC lLangCode; + TInt langCodeFound = 0; + + TInt checkErrorLangCode = lFirstChild->GetAttributeDes( KAtrLang, lLangCode); + + if (checkErrorLangCode != KErrNoAttribute) + { + TPtrC lXmlLangAttr(this->XMLLang()); + langCodeFound = lLangCode.CompareF( lXmlLangAttr ); + } + + TInt textLength = iText->Length(); + for (TInt i=0; i < textLength; i++) + { + //this probably isnt right i think one of these is a string that needs to be an int + if ( textDes[i] == lUnicode[0] && langCodeFound == 0) + { + //then this text string uses this glyph and we need to cache it in each spot it is used + iGlyphElements[i] = lFirstChild; + } + } + } + + lFirstChild = ( CSvgElementImpl* ) lFirstChild->NextSibling(); + } + } + + iNeedToCacheGlyphs = EFalse; +} + +TBool CSvgTextElementImpl::IsMostBasicLatin() +{ + //check to see if all basic latin characters + if (iText == NULL || iText->Length() == 0) + { + return EFalse; + } + + TPtr textDes = iText->Des(); + + TInt lOutOfLatinCount = 0; + + TInt textDesLength = textDes.Length(); + for (TInt i=0; i< textDesLength; i++) + { + if (!((TInt)textDes[i] <= 0x007F)) + { + lOutOfLatinCount++; + break; + } + } + + //make sure that at least half arent outside of basic latin characters + if (lOutOfLatinCount > (textDes.Length() / 2) ) + { + return EFalse; + } + + return ETrue; +} + +TDesC& CSvgTextElementImpl::GetText() +{ + return *iText; +} + +void CSvgTextElementImpl::SetFont(CFont* aBitmapFont, CSvgElementImpl* aSVGFont) +{ + if (aBitmapFont != NULL) + { + iBitmapFont = aBitmapFont; + } + if (aSVGFont != NULL) + { + iSVGFont = aSVGFont; + } +} + +TBool CSvgTextElementImpl::HasFont() +{ + if (iBitmapFont || iSVGFont) + { + return ETrue; + } + else + { + return EFalse; + } +} + + +void CSvgTextElementImpl::FreeFontData() +{ + + if (iBitmapFont) + { + CSvgBitmapFontProvider *tempBitmapFontProvider = ((CSvgDocumentImpl*)iOwnerDocument)->GetBitmapFontProvider(); + tempBitmapFontProvider->ReleaseFont(iBitmapFont); + iBitmapFont = NULL; + + } + +} + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetFontFamilyL( const TDesC& aValue ) + { + //May not need to be called every frame, the CSS value is stored on the element level + + TInt pos; + if ( iFamilies ) + { + iFamilies->Reset(); + delete iFamilies; + iFamilies = NULL; + } + iFamilies = new ( ELeave ) CDesCArrayFlat( 1 ); + TStringTokenizer tkn ( aValue, _L( "," ) ); + + _LIT( KQuote, "'" ); + while ( tkn.HasMoreTokens() ) + { + TPtrC lToken = tkn.NextToken(); + pos = lToken.Find( KQuote ); + TLex lStr( lToken ); + + const TChar KQuoteChar( '\'' ); + if ( pos == KErrNotFound ) + { + lStr.SkipSpaceAndMark(); //Skip whitespaces at beginning of font-family value + while (lStr.Get()) //get the remaining string from Mark + { + } + lStr.UnGet(); //"back" up one character + + const TChar KWhiteSpaceChar( ' ' ); + + while (lStr.Peek() == KWhiteSpaceChar) //for multi white spaces at the end + { + lStr.UnGet(); + } + //Token length = iNext pos - iMark pos + lStr.Inc(); //Increment iNext position by 1 to "include" iNext + + } + else + { + pos++; + lStr.SkipAndMark( pos ); + lStr.Inc( pos ); + while ( lStr.Get() != KQuoteChar ) + { + } + lStr.UnGet(); + } + TPtrC lFontFamily = lStr.MarkedToken(); + iFamilies->AppendL( lFontFamily ); + } + + //default font added to end here... + iFamilies->AppendL( KDefaultFont ); // _L("DefaultFont")); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetRotateL( const TDesC& aValue ) + { + iArrayRotate = new ( ELeave ) CArrayFixFlat( 1 ); + TStringTokenizer tkn ( aValue, _L( ", " ) ); + + TInt lCount = 0; + + while ( tkn.HasMoreTokens() ) + { + TPtrC lToken = tkn.NextToken(); + TLex lString ( lToken ); + TReal32 val; + if (lString.Val( val, '.' ) == KErrNone) + { + iArrayRotate->AppendL( val ); + lCount++; + } + } + + if( lCount == 0) + { + if ( iArrayRotate ) + { + iArrayRotate->Reset(); + delete iArrayRotate; + iArrayRotate = NULL; + } + } + + } + +// --------------------------------------------------------------------------- +//AA: Generic function to parse the "x" or "y" coordinate values +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetArrayL( const TDesC& aValue , const TBool aIsX) + { + + CArrayFixFlat* lArray; + TFloatFixPt lPt; + // the flag is used to determine which coodinate needs to be processed + if(aIsX) + { + lArray=iArrayX; + lPt=iPoint.iX; + + } + else + { + lArray=iArrayY; + lPt=iPoint.iY; + } + + if ( lArray ) + { + lArray->Reset(); + delete lArray; + lArray = NULL; + } + + lArray = new ( ELeave ) CArrayFixFlat( 1 ); +CleanupStack::PushL(lArray); + + if( (aValue.Length() > 0 ) && ( IsNumberAttributeValid(aValue) ) ) + { + TStringTokenizer tkn ( aValue, _L( ", " ) ); + + TInt lFirstXY = 0; + + TInt lCount = 0; + + while ( tkn.HasMoreTokens() ) + { + TPtrC lToken = tkn.NextToken(); + TLex lString ( lToken ); + TReal32 val; + if (lString.Val( val, '.' ) == KErrNone) + { + if( val < -32765 ) + val = -32765; + if( val > 32765 ) + val = 32765; + + if ( lFirstXY == 0 ) + { + lPt = val; + lFirstXY = 1; + } + + lArray->AppendL( ( TFloatFixPt ) val ); + lCount++; + } + } + + if( lCount == 0) + { + lPt = TFloatFixPt( 0 ); + lArray->AppendL( ( TFloatFixPt ) 0 ); + } + } + else + { + lPt = TFloatFixPt( 0 ); + lArray->AppendL( ( TFloatFixPt ) 0 ); + + } +CleanupStack::Pop(lArray); + + if(aIsX) + { + iPoint.iX = lPt; + iArrayX = lArray; + } + else + { + iPoint.iY = lPt; + iArrayY = lArray; + } + // In case of fewer x and more y and + // fewer y and more x, we need to append the last value of the + // coordinate to the corresponding array to be used for all the + // remaining characters. + if ( iArrayY && iArrayX ) + { + + TInt xCount=iArrayX->Count(); + TInt yCount=iArrayY->Count(); + TInt charCount=iText->Length(); + + // Either x or y should be having valid values. + if(xCount>0 || yCount>0) + { + // Text has more characters than the x or y values. + if(charCount>xCount||charCount>yCount) + + { + // More y than x and More characters than x append last + // value of the x coordinate. + if((yCount>=xCount) && (charCount>xCount)) + { + iArrayX->AppendL(iArrayX->At(xCount-1), (charCount-xCount)); + } + // More x than y and More characters than y append last + // value of the y coordinate. + if((yCount<=xCount) && (charCount>yCount)) + { + iArrayY->AppendL(iArrayY->At(yCount-1), (charCount-yCount)); + } + } + + } + } + + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetX( CArrayFix* aX ) + { + if (aX->Count() > 0) + { + iPoint.iX = aX->At( 0 ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetY( CArrayFix* aY ) + { + if (aY->Count() > 0) + { + iPoint.iY = aY->At( 0 ); + } + } + +// ******************************************************* +// From MXmlElement + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TInt CSvgTextElementImpl::SetAttributeL( const TDesC& aName, + const TDesC& aValue ) + { + CSvgElementImpl::SetAttributeL(aName,aValue); + return KErrNone; + } + + +// ******************************************************* +// From MXmlElementOpt + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TInt CSvgTextElementImpl::GetAttributeFloat( const TInt aNameId, + TFloatFixPt& aValue ) + { + switch ( aNameId ) + { + case KAtrX: + case KAtrRefX: + aValue = iPoint.iX; + break; + case KAtrY: + case KAtrRefY: + aValue = iPoint.iY; + break; + default: + return CSvgElementImpl::GetAttributeFloat( aNameId, aValue ); + } + return KErrNone; + } +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TInt CSvgTextElementImpl::SetAttributeFloatL( const TInt aNameId, + const TFloatFixPt aValue ) + { + switch ( aNameId ) + { + case KAtrX: + { + iPoint.iX = aValue; + if(!iArrayX) + { + iArrayX= new ( ELeave ) CArrayFixFlat( 1 ); + } + + iArrayX->Reset(); + iArrayX->AppendL((TFloatFixPt)aValue); + } + break; + case KAtrY: + { + iPoint.iY = aValue; + if(!iArrayY) + { + iArrayY= new ( ELeave ) CArrayFixFlat( 1 ); + } + + iArrayY->Reset(); + iArrayY->AppendL((TFloatFixPt)aValue); + } + break; + + + default: + return CSvgElementImpl::SetAttributeFloatL( aNameId, aValue ); + } + return KErrNone; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TInt CSvgTextElementImpl::GetAttributeDes( const TInt aNameId, TPtrC16& aValue ) + { + switch ( aNameId ) + { + case KAtrCdata: + aValue.Set(*iText); + break; + default: + return CSvgElementImpl::GetAttributeDes( aNameId, aValue ); + } + return KErrNone; + } +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TInt CSvgTextElementImpl::SetAttributeDesL( const TInt aNameId, + const TDesC& aValue ) + { + switch ( aNameId ) + { + case KAtrCdata: + SetTextL( aValue ); + break; + + case KAtrX: + SetArrayL(aValue, ETrue); + break; + + case KAtrY: + SetArrayL(aValue, EFalse); + break; + + case KAtrRotate: + SetRotateL( aValue ); + break; + + default: + return CSvgElementImpl::SetAttributeDesL( aNameId, aValue ); + } + + // check first character is number or '.' + if ( aNameId == KAtrX || aNameId == KAtrY ) + { + if ( aValue.Length() == 0 || + ( !TChar( aValue[0] ).IsDigit() && aValue[0] != '.' && aValue[0] != '-') ) + { + if ( iOwnerDocument ) + { + _LIT( KMsg, "Invalid value-string for number attribute: " ); + ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue ); + } + } + } + return KErrNone; + } + + +// --------------------------------------------------------------------------- +// This is a Local Function. +// Checks to see if the given character is within the SVG Font's Unicode Range.* +// Only the following formats are allowed for "unicode-range" attribute +// Single numbers: U+20A7 | U+215? | U+00?? | U+E?? +// Pair of numbers: U+AC00-D7FF | U+F9000-FAFF +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::IsWithinUnicodeRange( const TDesC& aUnicodeRange, + const TDesC& aCharacter ) + { + _LIT( KQQ, "??" ); + _LIT( KQ, "?" ); + _LIT( KF, "F" ); + _LIT( KFF, "FF" ); + _LIT( KLitZero, "0" ); + _LIT( KZZero, "00" ); + _LIT( KHyph, "-" ); + _LIT( KUni, "U+" ); + + TUint32 lStartRange = 0; + TUint32 lEndRange = 65536; + + TUint32 lCharacter = ( TUint32 ) aCharacter.operator[]( 0 ); + + TBuf<11> lUnicodeRange; + + if(aUnicodeRange.Length() <= 11) + lUnicodeRange = aUnicodeRange; //Max.Length "U+00AB-00AF" + else + return EFalse; //Length is greater than 11. + + TInt pos; + + + //Removing "U+" + pos = lUnicodeRange.Find( KUni ); + if ( pos != KErrNotFound ) + lUnicodeRange.Delete( pos, 2 ); + else + return EFalse; // Not a valid unicode range, i.e. not "U+" element + + //Finding "-", if yes, then pair found. + pos = lUnicodeRange.Find( KHyph ); + if ( pos != KErrNotFound )//found + { + TPtrC lStartString = lUnicodeRange.Left( pos ); + TLex lStart ( lStartString ); + if (lStart.Val( lStartRange, EHex ) != KErrNone) + lStartRange=0; + + TPtrC lEndString = lUnicodeRange.Right( lUnicodeRange.Length() - + pos - + 1 ); + TLex lEnd ( lEndString ); + if (lEnd.Val( lEndRange, EHex ) != KErrNone) + lEndRange= 65536; + } + else //single number + { + pos = lUnicodeRange.Find( KQQ ); + if ( pos != KErrNotFound ) + { + lUnicodeRange.Replace( pos, 2, KZZero ); + TPtrC lStartString = lUnicodeRange.Left( pos + 2 ); + TLex lStart ( lStartString ); + if (lStart.Val( lStartRange, EHex ) != KErrNone) + lStartRange=0; + + lUnicodeRange.Replace( pos, 2, KFF ); + TPtrC lEndString = lUnicodeRange.Left( pos + 2 ); + TLex lEnd ( lEndString ); + if (lEnd.Val( lEndRange, EHex ) != KErrNone) + lEndRange= 65536; + } + + else if ( (pos = lUnicodeRange.Find( KQ ) ) != KErrNotFound ) + { + lUnicodeRange.Replace( pos, 1, KLitZero ); + TPtrC lStartString = lUnicodeRange.Left( pos + 1 ); + TLex lStart ( lStartString ); + if (lStart.Val( lStartRange, EHex ) != KErrNone) + lStartRange=0; + + lUnicodeRange.Replace( pos, 1, KF ); + TPtrC lEndString = lUnicodeRange.Left( pos + 1 ); + TLex lEnd ( lEndString ); + if (lEnd.Val( lEndRange, EHex ) != KErrNone) + lEndRange= 65536; + } + else + { + TLex lEnd ( lUnicodeRange ); + if (lEnd.Val( lEndRange, EHex ) != KErrNone) + lEndRange= 65536; + lStartRange = lEndRange; + } + } + + if ( ( lCharacter >= lStartRange ) && ( lCharacter <= lEndRange ) ) + return ETrue; + else + return EFalse; + } + +//Method to set kerning pairs u1 and u2. +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetUKernPairsL( const TDesC& aU1, const TDesC& aU2 ) + { + if(iU1) + { + delete iU1; + iU1 = NULL; + } + iU1 = aU1.AllocL(); + if(iU2) + { + delete iU2; + iU2 = NULL; + } + iU2 = aU2.AllocL(); + + } + + +//Method to set kerning pairs g1 and g2. +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetGKernPairsL( const TDesC& aG1, const TDesC& aG2 ) + { + + if(iG1) + { + delete iG1; + iG1 = NULL; + } + iG1 = aG1.AllocL(); + + if(iG2) + { + delete iG2; + iG2 = NULL; + } + iG2 = aG2.AllocL(); + + } + + +// --------------------------------------------------------------------------- +// This method checks to see whether kerning is required. +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::IsKerningRequired( const TDesC& aPrevGlyphName, + const TDesC& aCurrGlyphName, + const TDesC& aPrevUnicode, + const TDesC& aCurrUnicode ) + { + _LIT( KGlyphNameNone, "GlyphNameNone"); + TBool lFoundG1(EFalse); + TBool lFoundG2(EFalse); + TBool lFoundU1(EFalse); + TBool lFoundU2(EFalse); + + //Finding G1 + if( aPrevGlyphName != KGlyphNameNone) + { + TStringTokenizer tkn1 ( iG1->Des(), _L( "," ) ); + while ( tkn1.HasMoreTokens() ) + { + TPtrC lToken = tkn1.NextToken(); + if( (lToken.Compare(aPrevGlyphName)) == 0 ) + { + lFoundG1 = ETrue; + break; + } + } + } + //Finding G2 + if( aCurrGlyphName != KGlyphNameNone) + { + TStringTokenizer tkn2 ( iG2->Des(), _L( "," ) ); + while ( tkn2.HasMoreTokens() ) + { + TPtrC lToken = tkn2.NextToken(); + if( (lToken.Compare(aCurrGlyphName)) == 0 ) + { + lFoundG2 = ETrue; + break; + } + } + } + //Finding U1 + TStringTokenizer tkn3 ( iU1->Des(), _L( "," ) ); + while ( tkn3.HasMoreTokens() ) + { + + TPtrC lToken = tkn3.NextToken(); + + if( lToken.Length() == 1) //Unicode character + { + if( (lToken.Compare(aPrevUnicode.Right(1))) == 0 ) + { + lFoundU1 = ETrue; + break; + } + + } + else // Unicode Range + { + if(IsWithinUnicodeRange( lToken, aPrevUnicode )) + lFoundU1 = ETrue; + break; + } + + } + + //Finding U2 + TStringTokenizer tkn4 ( iU2->Des(), _L( "," ) ); + while ( tkn4.HasMoreTokens() ) + { + + TPtrC lToken = tkn4.NextToken(); + + if( lToken.Length() == 1) //Unicode character + { + if( (lToken.Compare(aCurrUnicode.Left(1))) == 0 ) + { + lFoundU2 = ETrue; + break; + } + + } + else // Unicode Range + { + if(IsWithinUnicodeRange( lToken, aCurrUnicode )) + { + lFoundU2 = ETrue; + break; + } + } + + } + + if ( (lFoundG1 || lFoundU1) && (lFoundG2 || lFoundU2) ) + return ETrue; + else + return EFalse; + } + + +// ******************************************************* +// From CSvgElementImpl + +// perform a deep clone of this object +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +MXmlElement* CSvgTextElementImpl::CloneL(MXmlElement* aParentElement) + { + + CSvgTextElementImpl* newElement = CSvgTextElementImpl::NewL( this->ElemID(), ((CSvgDocumentImpl*)iOwnerDocument) ); + + CleanupStack::PushL(newElement); + newElement->iParentNode = aParentElement; + // copy everything over + this->CopyL(newElement); + CleanupStack::Pop(); + return newElement; + } + +// --------------------------------------------------------------------------- +// perform a deep copy of this object +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::CopyL( CSvgTextElementImpl* aDestElement ) + { + if(aDestElement) + { + + // copy stuff from superclass + this->CSvgElementImpl::CopyL(aDestElement); + + if(this->iText) + { + delete aDestElement->iText; + aDestElement->iText= NULL; + aDestElement->iText= (this->iText)->AllocL(); + } + aDestElement->iPoint.iX= this->iPoint.iX; + aDestElement->iPoint.iY= this->iPoint.iY; + + aDestElement->iLetterSpacing= this->iLetterSpacing; + aDestElement->iWordSpacing= this->iWordSpacing; + aDestElement->iRotate= this->iRotate; + + //iFamilies + if(this->iFamilies) + { + TInt lCount= (this->iFamilies)->Count(); + if(lCount) + { + if(aDestElement->iFamilies) + { + aDestElement->iFamilies->Reset(); + delete aDestElement->iFamilies; + aDestElement->iFamilies = NULL; + } + aDestElement->iFamilies = new ( ELeave ) CDesCArrayFlat( 1 ); + for(TInt i=0; iiFamilies)->operator[](i); + aDestElement->iFamilies->AppendL(lPtr); + } + } + } + + //iArraX + if(this->iArrayX) + { + TInt lCount= (this->iArrayX)->Count(); + if(lCount) + { + if(aDestElement->iArrayX) + { + aDestElement->iArrayX->Reset(); + delete aDestElement->iArrayX; + aDestElement->iArrayX = NULL; + } + aDestElement->iArrayX = new ( ELeave ) CArrayFixFlat( 1 ); + for(TInt i=0; iiArrayX)->operator[](i); + aDestElement->iArrayX->AppendL(lFix); + } + } + } + + //iArrayY + if(this->iArrayY) + { + TInt lCount= (this->iArrayY)->Count(); + if(lCount) + { + if(aDestElement->iArrayY) + { + aDestElement->iArrayY->Reset(); + delete aDestElement->iArrayY; + aDestElement->iArrayY = NULL; + } + aDestElement->iArrayY = new ( ELeave ) CArrayFixFlat( 1 ); + for(TInt i=0; iiArrayY)->operator[](i); + aDestElement->iArrayY->AppendL(lFix); + } + } + } + + // iArrayRotate + if(this->iArrayRotate) + { + TInt lCount= (this->iArrayRotate)->Count(); + if(lCount) + { + if(aDestElement->iArrayRotate) + { + aDestElement->iArrayRotate->Reset(); + delete aDestElement->iArrayRotate; + aDestElement->iArrayRotate = NULL; + } + aDestElement->iArrayRotate = new ( ELeave ) CArrayFixFlat( 1 ); + for(TInt i=0; iiArrayRotate)->operator[](i); + aDestElement->iArrayRotate->AppendL(lFix); + } + } + } + +///////////////////Cloning the glyph elements/////////////////////// + TInt lCount= (this->iGlyphElements).Count(); + if(lCount) + { + for(TInt i=0; iiGlyphElements).operator[](i); + aDestElement->iGlyphElements.AppendL(element); + } + } + + + aDestElement->iNeedToCacheGlyphs = this->iNeedToCacheGlyphs; + +////////////////////////////////////////////////////////////////////// + aDestElement->iTextAnchor= this->iTextAnchor; + aDestElement->iTextDecoration= this->iTextDecoration; + + if(this->iG1) + { + delete aDestElement->iG1; + aDestElement->iG1= NULL; + aDestElement->iG1= (this->iG1)->AllocL(); + } + + if(this->iG2) + { + delete aDestElement->iG2; + aDestElement->iG2= NULL; + aDestElement->iG2= (this->iG2)->AllocL(); + } + + if(this->iU1) + { + delete aDestElement->iU1; + aDestElement->iU1= NULL; + aDestElement->iU1= (this->iU1)->AllocL(); + } + + if(this->iU2) + { + delete aDestElement->iU2; + aDestElement->iU2= NULL; + aDestElement->iU2= (this->iU2)->AllocL(); + } + + //Note that copying iBitmapFont from one text element to + //another, there is danger of double free. Let new element + //get its own Font pointer. Anyway it just updates the + //access count on the server side if two fonts are same. + //aDestElement->iBitmapFont= this->iBitmapFont; + aDestElement->iBitmapFont= NULL; + + + // copy the reference to idoc (CSvgDocumentImpl) + aDestElement->iOwnerDocument = this->iOwnerDocument; + } + + } + +// --------------------------------------------------------------------------- +// This Method is used to draw the TEXT described within the element. +// There are 2 types of Fonts used to render the text. First, the family-name +// is checked to see if there exists a SVG FONT defined within the SVG File. +// If there is one, then text is rendered using this font, else the text is +// rendered using the Bitmap system fonts using the Drawstring() in Gfx2D. +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::DrawL( CGfx2dGc* aGc, CSvgElementImpl* aElement ) +{ + if (iText->Length() == 0) + { + return EFalse; + } + + // Reset and set GC + this->DrawShapeL( aGc, aElement ); + //if ( !aGc->RenderingHints()->Visibility() ) + // return EFalse; // Do nothing if visibility is False. + + + TInt8 lTextDecoration = (TInt8) + (((CIntCssValueImpl *)(iSvgStyleProperties->operator[](KCSS_ATTR_TEXTDECORATION)))->Value()); + + TInt8 lTextAnchor =(TInt8)( + ((CIntCssValueImpl *)(iSvgStyleProperties->operator[](KCSS_ATTR_TEXTANCHOR)))->Value()); + +/**********************************************************/ +/* ROM Configuration Flag whether to include SVG FONTS */ +/**********************************************************/ + + //get the scaling factor currently in the graphics library. + + TFloatFixPt KZero; + + //CSvgElementImpl* lFirstChild = NULL; + CGfxGeneralPath* lShape = NULL; + CGfxGeneralPath* lShapeMG = NULL; + TFloatFixPt origX ( iPoint.iX ); + TFloatFixPt currentPosOrigX( iPoint.iX ); + /*iSVGBbox.iX = iPoint.iX; + iSVGBbox.iY = iPoint.iY; + iSVGBbox.iWidth = 0;*/ + TFloatFixPt currentPosOrigY( iPoint.iY ); + TFloatFixPt lUnitsPerEm( 1000 ); + TFloatFixPt lAlphabetic( 0 ); + TFloatFixPt lFontHorzOrgX( 0 ); + TFloatFixPt lFontHorzAdvX( 0 ); + TFloatFixPt lMissingGlyphHorzAdvX( 0 ); + TFloatFixPt lFontSize( 10 ); + TPtrC lFontFamily; + TPtrC16 lUnicode; + TPtrC16 lPrevUnicode; + TPtrC16 lUnicodeRange; //Max.Length "U+00AB-00AF" + TPtrC16 lLangCode; //ex: en-US or en-GB or ja-JP or zh-CN or en.... + TPtrC16 lG1; + TPtrC16 lG2; + TPtrC16 lU1; + TPtrC16 lU2; + TPtrC16 lPrevGlyphName; + TPtrC16 lCurrGlyphName; + TFloatFixPt lK; //kerning purpose.... + + TFloatFixPt lAscent( KZero ); + TFloatFixPt lDescent( KZero ); + TFloatFixPt lUnderlinePosition( KZero ); + TFloatFixPt lUnderlineThickness( KZero ); + TFloatFixPt lOverlinePosition( KZero ); + TFloatFixPt lOverlineThickness( KZero ); + TFloatFixPt lStrikethroughPosition( KZero ); + TFloatFixPt lStrikethroughThickness( KZero ); + TFloatFixPt lTotalTextAdvance ( KZero ); + + //Getting font-size property + + CCssValue* lCssValue = NULL; + this->FindProperty( KCSS_ATTR_FONTSIZE, lCssValue, aElement ); + if ( lCssValue ) + { + lFontSize = (( CFloatCssValueImpl * ) lCssValue )->Value(); + if(lFontSize <= KZero ) + lFontSize = TFloatFixPt ( 10 ); + } + + //Getting font-family property + this->FindProperty( KCSS_ATTR_FONTFAMILY, lCssValue, aElement ); + if ( lCssValue && ((( CStrCssValueImpl * ) lCssValue )->Value()).Length() != 0) + { + lFontFamily.Set( ( ( CStrCssValueImpl * ) lCssValue )->Value() ); + SetFontFamilyL( lFontFamily ); + } + + + //attempt to load svg font files of same font family name + //this boolean will be a problem if we want to be able to swap + //font-family names on the fly and use svg fonts. + if (!iTriedLoadingSVGFonts) + { + LoadExternalSVGFontL(lFontFamily); + iTriedLoadingSVGFonts = ETrue; + } + + //Retrieving Font Element Pointer from the Font Table + //if font in svg document + iSVGFont = NULL; + if ( iFamilies != NULL ) + { + TInt familiesCnt = iFamilies->Count(); + for (int i=0; i< familiesCnt; i++) + { + iSVGFont = ( CSvgElementImpl * ) + ((CSvgDocumentImpl*)iOwnerDocument)->Engine()->iFontHashMap->GetFontPtr(iFamilies->operator[]( i )); + + if (iSVGFont == NULL) + { + iSVGFont = ( CSvgElementImpl * ) + ((CSvgDocumentImpl*)iOwnerDocument)->iFontHashMap->GetFontPtr( iFamilies->operator[]( i ) ); + } + + if (iSVGFont != NULL) + { + //found a font with that family name...continue + break; + } + } + } + +/**********************************************************/ +/* Checking for pre-defined SVG Fonts through the */ +/* retrieved pointer from the Font Table. */ +/* IF the Font is found (ptr!=NULL), SVG Fonts are used */ +/* ELSE Bitmap Font is used through DrawString() method */ +/**********************************************************/ + + if ( iSVGFont != NULL && iSVGFont->HasChildNodes()) + { + TGfxAffineTransform currentTM; + //we found an svg font and are using it... + + iSVGFont->GetAttributeFloat( KAtrHorizOriginX, lFontHorzOrgX ); + iSVGFont->GetAttributeFloat( KAtrHorizAdvX, lFontHorzAdvX ); + lMissingGlyphHorzAdvX = lFontHorzAdvX; //Default Value + TInt checkErrShapeMG = -1;//To keep a value other than KErrNone. Should this be replaced + + if (iNeedToCacheGlyphs) + { + CacheGlyphsForText(); + } + + TFloatFixPt lUnitsPerEmInverse; + TFloatFixPt minusOne( -1 ); + + /***********************/ + /* HKERN ELEMENT */ + /***********************/ + if (iHkernElement != NULL) + { + iHkernElement->GetAttributeFloat( KAtrK, lK ); + + TInt checkErrorG1 = iHkernElement->GetAttributeDes( KAtrG1, lG1); + TInt checkErrorG2 = iHkernElement->GetAttributeDes( KAtrG2, lG2); + TInt checkErrorU1 = iHkernElement->GetAttributeDes( KAtrU1, lU1); + TInt checkErrorU2 = iHkernElement->GetAttributeDes( KAtrU2, lU2); + + if( (checkErrorG1 != KErrNoAttribute) && (checkErrorG2 != KErrNoAttribute) ) + { + SetGKernPairsL( lG1, lG2); + } + + if( (checkErrorU1 != KErrNoAttribute) && (checkErrorU2 != KErrNoAttribute) ) + { + SetUKernPairsL( lU1, lU2); + } + } + + /********************************/ + /* Text Rendering functionality */ + /*******************************/ + + /***********************/ + /* MISSINGGLYPH ELEMENT*/ + /***********************/ + if (iMissingGlyphElement != NULL) + { + iMissingGlyphElement->GetAttributeFloat( KAtrHorizAdvX, + lMissingGlyphHorzAdvX ); + + if ( lMissingGlyphHorzAdvX == TFloatFixPt( 0 ) ) + { + lMissingGlyphHorzAdvX = lFontHorzAdvX; + } + + checkErrShapeMG = iMissingGlyphElement->GetAttributePath( KAtrData, + lShapeMG ); + } + + /***********************/ + /* FONTFACE ELEMENT */ + /***********************/ + + if (iFontFaceElement != NULL) + { + iFontFaceElement->GetAttributeFloat( KAtrUnitsPerEm, + lUnitsPerEm ); + + #ifdef SVG_FLOAT_BUILD + if ( lUnitsPerEm <= TFloatFixPt( 0 ) ) + { + lUnitsPerEm = TFloatFixPt( 1000 ); + } + #else + if ( lUnitsPerEm <= TFloatFixPt( 0,ETrue ) ) + { + lUnitsPerEm = TFloatFixPt( 1000 ); + } + #endif + lUnitsPerEmInverse = TFloatFixPt( 1 ) / lUnitsPerEm; + + iFontFaceElement->GetAttributeFloat( KAtrAscent, + lAscent ); + + iFontFaceElement->GetAttributeFloat( KAtrDescent, + lDescent ); + + iFontFaceElement->GetAttributeFloat( KAtrUnderlinePosition, + lUnderlinePosition ); + + iFontFaceElement->GetAttributeFloat( KAtrUnderlineThickness, + lUnderlineThickness ); + + iFontFaceElement->GetAttributeFloat( KAtrOverlinePosition, + lOverlinePosition ); + + iFontFaceElement->GetAttributeFloat( KAtrOverlineThickness, + lOverlineThickness ); + + iFontFaceElement->GetAttributeFloat( KAtrStrikethroughPosition, + lStrikethroughPosition ); + + iFontFaceElement->GetAttributeFloat( KAtrStrikethroughThickness, + lStrikethroughThickness ); + + iFontFaceElement->GetAttributeFloat( KAtrAlphabetic, + lAlphabetic ); + } + + //Checking valid UnicodeRange of FontFace Element this is trying to limit the number that we have to search through + //but why do we need this in here + + /*TInt checkErrorUnicodeRange = iFontFaceElement->GetAttributeDes( KAtrUnicodeRange, + lUnicodeRange ); + if ( checkErrorUnicodeRange != KErrNoAttribute ) + { + //Function call to unicode-range bounds. + if(!IsWithinUnicodeRange( lUnicodeRange, + outputChar )) + { + currentPosOrigX += ( lFontHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + lIsWithinUnicodeRange = EFalse; + break; + } + }*/ + + //Text Anchor related. + //lTotalTextAdvance = lFontHorzAdvX * (TFloatFixPt)iText->Length() * lUnitsPerEmInverse * lFontSize; + // Calculate the exact total text advance instead of taking default per glyph + // advance which will approximate the value. + TFloatFixPt lGlyphHorzAdvX; + TInt langCodeFound( 0 ); + // Calculate the total text advance in the following cases: + // a. Text Anchor is middle + // b. Text Anchor is end + // c. Text Decoration is needed( Underline/Overline/Strikethrough ) + if( lTextAnchor == 1 || lTextAnchor == 2 || lTextDecoration != -1 ) + { + lTotalTextAdvance= GetTotalTextAdvance(lK,lUnitsPerEmInverse,lFontSize,lMissingGlyphHorzAdvX,lFontHorzAdvX); + } + + if( lTextAnchor == 1 )//Middle + { + currentPosOrigX -= (lTotalTextAdvance * TFloatFixPt(.5f)); + origX -= (lTotalTextAdvance * TFloatFixPt(.5f)); + } + + if( lTextAnchor == 2 )//End + { + currentPosOrigX -= lTotalTextAdvance; + origX -= lTotalTextAdvance; + } + //else default:start + + if( lAlphabetic != KZero ) + { + //Should be rationally negative, but Adobe traverses positive. + currentPosOrigY += ( lAlphabetic * lUnitsPerEmInverse ) * lFontSize; + } + + if( lFontHorzOrgX != KZero ) + { + //Should be rationally positive, but Adobe traverses negative. + currentPosOrigX -= ( lFontHorzOrgX * lUnitsPerEmInverse ) * lFontSize; + origX -= ( lFontHorzOrgX * lUnitsPerEmInverse ) * lFontSize; + } + + /***********************/ + /* GLYPH ELEMENT */ + /***********************/ + //Assume that xml:lang matches lang code of glyph element. + //TInt lUnicodeLength( 0 ); + + //The x coordinate is needed to draw the text decorations. + if(iArrayX) + { + origX=iArrayX->At(0); + } + TInt glyphEleCnt = iGlyphElements.Count(); + for (TInt i=0; i < glyphEleCnt; i++) + { + CSvgElementImpl* lGlyphElement = (CSvgElementImpl*)iGlyphElements[i]; + + if (lGlyphElement != NULL) + { + //have a valid glyph + TInt checkErrorUnicode = lGlyphElement->GetAttributeDes( KAtrUnicode, + lUnicode ); + //check the glyph name + TInt checkErrorGlyphName = lGlyphElement->GetAttributeDes( KAtrGlyphName, + lCurrGlyphName ); + if( checkErrorGlyphName == KErrNoAttribute ) + { + lCurrGlyphName.Set( KGlyphNameNone ); + } + + //check its language + TInt checkErrorLangCode = lGlyphElement->GetAttributeDes( KAtrLang, + lLangCode ); + TPtrC lXmlLangAttr(this->XMLLang()); + + if( checkErrorLangCode != KErrNoAttribute ) //if Lang code present + { + langCodeFound = lLangCode.CompareF( lXmlLangAttr );//compare xml:lang with Lang code. + } + + //if Lang code is matching && unicode attr. present, we are good. + if ( (checkErrorUnicode != KErrNoAttribute) && (langCodeFound == 0) ) + { + //Checking and Introducing kerning(adjusting spacing). + if( lPrevGlyphName.Length() > 0 ) + { + if( IsKerningRequired( lPrevGlyphName, lCurrGlyphName, lPrevUnicode, lUnicode )) + { + currentPosOrigX -= ( lK * lUnitsPerEmInverse ) * lFontSize; + } + } + + lGlyphElement->GetAttributeFloat( KAtrHorizAdvX, + lGlyphHorzAdvX ); + + #ifdef SVG_FLOAT_BUILD + if ( lGlyphHorzAdvX == TFloatFixPt( 0 ) ) + #else + if ( lGlyphHorzAdvX == TFloatFixPt( 0,ETrue ) ) + #endif + { + lGlyphHorzAdvX = /*(TFloatFixPt)lUnicodeLength **/ lFontHorzAdvX; + } + + TInt checkErrorShape = lGlyphElement->GetAttributePath( KAtrData, + lShape ); + /***********************/ + /* Drawing the Glyph */ + /***********************/ + if ( checkErrorShape == KErrNone ) + { + this->DrawShapeL( aGc, aElement ); + + // Fix for UMAA-753ARS + // Scale the strokewidth before applying + // the scaling for glyph + ScaleStrokeWidth(aGc); + + // For multiple x, y get the current position + // from the array. + if((iArrayX != NULL ) && ( i< iArrayX->Count() )) + { + currentPosOrigX = iArrayX->At(i); + } + if((iArrayY!=NULL) && (iCount() ) ) + { + currentPosOrigY = iArrayY->At(i); + } + + currentTM = this->GetCTM(); + + currentTM.Translate( currentPosOrigX, + currentPosOrigY ); + currentTM.Scale( lUnitsPerEmInverse, + minusOne * lUnitsPerEmInverse ); + currentTM.Scale( lFontSize, lFontSize ); + aGc->SetTransform( currentTM ); + + aGc->DrawL( lShape ); + + lPrevUnicode.Set(lUnicode); + lPrevGlyphName.Set(lCurrGlyphName); + + currentPosOrigX += ( lGlyphHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + + } + } + + } + else + { + //need to use missing glyph for this one... + //iGlyphElements.Insert(iMissingGlyphElement, i); + + /***********************/ + /* Drawing MissingGlyph*/ + /***********************/ + + if ( checkErrShapeMG == KErrNone ) + { + this->DrawShapeL( aGc, aElement ); + + // Fix for UMAA-753ARS + // Scale the strokewidth before applying + // the scaling for glyph + ScaleStrokeWidth(aGc); + + // For multiple x, y get the current position + // from the array. + if((iArrayX != NULL ) && ( i< iArrayX->Count() )) + { + currentPosOrigX = iArrayX->At(i); + } + if((iArrayY!=NULL) && (iCount() ) ) + { + currentPosOrigY = iArrayY->At(i); + } + currentTM = this->GetCTM(); + + currentTM.Translate( currentPosOrigX, currentPosOrigY ); + currentTM.Scale( lUnitsPerEmInverse, + minusOne * lUnitsPerEmInverse ); + currentTM.Scale( lFontSize, lFontSize ); + aGc->SetTransform( currentTM ); + + aGc->DrawL( lShapeMG ); + } + + currentPosOrigX += ( lMissingGlyphHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + + } + }//end-for + TGfxRectangle2D lBbox; + if(iGlyphElements[glyphEleCnt-1] && lShape) + { + // Get the bbox for the last glyph element. + lShape->GetBounds(currentTM,lBbox); + } + else if ( lShapeMG ) + { + // Get the bbox for the last missing-glyph element. + lShapeMG->GetBounds(currentTM,lBbox); + } + currentPosOrigX=lBbox.iX+lBbox.iWidth; +/**********************************************************/ +/* Text Decoration Implementation for SVG Fonts */ +/* The following attributes are supported in this section */ +/* "underline-position" */ +/* "underline-thickness" */ +/* "overline-position" */ +/* "overline-thickness" */ +/* "strikethrough-position" */ +/* "strikethrough-thickness" */ +/**********************************************************/ + + if( lTextDecoration != -1 ) + { + TFloatFixPt lLineStartX( origX );//Text Anchored position(see under fontfaceFound section). + TFloatFixPt lLineStartY( currentPosOrigY ); + TFloatFixPt lLineEndX( origX + lTotalTextAdvance ); + TFloatFixPt lLineEndY( currentPosOrigY ); + TFloatFixPt lStrokeThickness ( 1 );//default thickness > 0; pensize is set to 1 in Gfx2D. + + if( lTextDecoration == 1 ) + { + if( lUnderlinePosition != KZero ) + { + //negative(minus sign) due to inverted font coordinate system + lLineStartY = lLineEndY = currentPosOrigY - (lUnderlinePosition * lUnitsPerEmInverse) * lFontSize; + } + else if( lUnderlinePosition == KZero && lDescent != KZero ) + { + lLineStartY = lLineEndY = currentPosOrigY - ((lDescent/TFloatFixPt(2)) * lUnitsPerEmInverse) * lFontSize; + } + else + { + //default. No information provided( descent or underline position) + } + if( lUnderlineThickness != KZero ) + { + lStrokeThickness = lUnderlineThickness * lUnitsPerEmInverse * lFontSize ; + } + } + + if( lTextDecoration == 2 ) + { + if( lOverlinePosition != KZero ) + { + //negative(minus sign) due to inverted font coordinate system + lLineStartY = lLineEndY = currentPosOrigY - (lOverlinePosition * lUnitsPerEmInverse) * lFontSize; + } + else if( lOverlinePosition == KZero && lAscent != KZero ) + { + lLineStartY = lLineEndY = currentPosOrigY - (lAscent * lUnitsPerEmInverse) * lFontSize; + } + else + { + //default. No information provided( ascent or overline position) + } + if( lOverlineThickness != KZero ) + { + lStrokeThickness = lOverlineThickness * lUnitsPerEmInverse * lFontSize ; + } + } + + + if( lTextDecoration == 3 ) + { + if( lStrikethroughPosition != KZero ) + { + //negative(minus sign) due to inverted font coordinate system + lLineStartY = lLineEndY = currentPosOrigY - (lStrikethroughPosition * lUnitsPerEmInverse) * lFontSize; + } + else if( lStrikethroughPosition == KZero && lAscent != KZero ) + { + lLineStartY = lLineEndY = currentPosOrigY - ((lAscent/TFloatFixPt(3)) * lUnitsPerEmInverse) * lFontSize; + } + else + { + //default. No information provided( ascent or strikethrough position) + } + if( lStrikethroughThickness != KZero ) + { + lStrokeThickness = lStrikethroughThickness * lUnitsPerEmInverse * lFontSize ; + } + } + + TGfxLine2D lLine( lLineStartX ,lLineStartY, lLineEndX, lLineEndY ); + + this->DrawShapeL( aGc, aElement ); + + // Setting Stokewidth for SVG Fonts. Check if there exists a value or default value (1) is set. + if( ( lOverlineThickness != KZero ) || ( lUnderlineThickness != KZero ) || ( lStrikethroughThickness != KZero ) ) + { + TGfxStroke lStroke = aGc->Stroke(); + lStroke.SetStrokeWidth( lStrokeThickness); // relation to font co-ordinate system. + aGc->SetStroke( lStroke ); + } + + + TGfxColor lForegroundColor(aGc->ForegroundColor()); + if ( lForegroundColor.GetColor() == KGfxColorNull ) + { + if ( (aGc->Paint()) != NULL ) + aGc->SetForegroundColor(TGfxColor( (aGc->Paint())->GetColor() )); + } + + aGc->DrawL( &lLine ); + }//end of text decoration functionality + } + else + { + +/**********************************************************/ +/* If SVG Font is not available then Bitmap Fonts are used*/ +/* to render the text by calling the DrawString() function*/ +/* of Gfx2D */ +/**********************************************************/ + UpdateCurrentScaledFont(); + + aGc->DrawStringL( iText->Des(), + iPoint.iX, + iPoint.iY, + lTextAnchor, + lTextDecoration, + iFamilies, + iWordSpacing, + iLetterSpacing, + iArrayRotate, + iArrayX, + iArrayY, + iBoundingBox, + iBitmapFont, + iBitmapFontSpec ); + + // Storing of the font is done in above routine + // only, hence removing below lines. + // store font info for bitmap font + //if ( iBitmapFont == NULL ) + //iBitmapFont = GetCurrentFontScaled(); + + } + // Fix for ScreenSaver Bug + CSvgDocumentImpl* doc = (CSvgDocumentImpl*)OwnerDocument(); + if ( doc && doc->Engine() ) + { + iGfx2dGc = doc->Engine()->GraphicsContext(); + } + return EFalse; +} + +// ----------------------------------------------------------------------------- +// void CSvgTextElementImpl::ScaleStrokeWidth(CGfx2dGc* aGc) +// Scale the stroke width in order to nullify the effect of scaling appiled on +// the glyph +// ----------------------------------------------------------------------------- +void CSvgTextElementImpl::ScaleStrokeWidth(CGfx2dGc* aGc) + { + + TFloatFixPt lStrokeWidth; + CCssValue* lCssValue = NULL; + this->FindProperty( KCSS_ATTR_STROKEWIDTH, lCssValue); + if ( lCssValue ) + { + lStrokeWidth = ( ( CFloatCssValueImpl * ) lCssValue )->Value(); + if (lStrokeWidth <= TFloatFixPt(0)) + { + aGc->SetStrokeWidth( TFloatFixPt(0) ); + } + else + { + // Get the font-size + TFloatFixPt lFontSize( 10 ); + this->FindProperty( KCSS_ATTR_FONTSIZE, lCssValue, NULL ); + if ( lCssValue ) + { + lFontSize = (( CFloatCssValueImpl * ) lCssValue )->Value(); + if(lFontSize <= TFloatFixPt(0) ) + { + lFontSize = TFloatFixPt ( 10 ); + } + } + TFloatFixPt lUnitsPerEm( 1000 ); + + // Get units-per-em + if (iFontFaceElement != NULL) + { + iFontFaceElement->GetAttributeFloat( KAtrUnitsPerEm, + lUnitsPerEm ); + + #ifdef SVG_FLOAT_BUILD + if ( lUnitsPerEm <= TFloatFixPt( 0 ) ) + { + lUnitsPerEm = TFloatFixPt( 1000 ); + } + #else + if ( lUnitsPerEm <= TFloatFixPt( 0,ETrue ) ) + { + lUnitsPerEm = TFloatFixPt( 1000 ); + } + #endif + + } + + lStrokeWidth=(lStrokeWidth*lUnitsPerEm)/lFontSize; + aGc->SetStrokeWidth(lStrokeWidth); + } + } + + } + +// ******************************************************* +// From MSvgLocatable/MSvgTransformable +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::GetBBox( TGfxRectangle2D& aBbox ) + { + if (iSVGFont) + { + //get the bounding boxes of + //all of the glyphs in the child and add them together. + GetBBoxForSVGText(aBbox); + } + else if (iBitmapFont) + { + GetBBoxForSystemText(aBbox); + } + else + { + //this is an error case if it gets to here + // When GetBBox is called just after PrepareDom, the font + // spec is not initialied yet. It happens only in DrawL. + // To take care of this issue, and give a correct bounding box, + // Bitmap font is assumed. Note: This would not work if + // SVG font is selected. This needs to be fixed more generically. + + UpdateCurrentScaledFont(); + if (iBitmapFont) + { + GetBBoxForSystemText(aBbox); + } + else + { + aBbox.iY = iPoint.iY; + aBbox.iX = iPoint.iX; + aBbox.iWidth = 0; + aBbox.iHeight = 0; + } + + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::GetFourPointBBox( TSvgFourPointRect& aFourPointBBox ) + { + if (iSVGFont) + { + //get the bounding boxes of + //all of the glyphs in the child and add them together. + GetBBoxForSVGText(aFourPointBBox,this->GetCTM()); + } + else if (iBitmapFont) + { + GetBBoxForSystemText(aFourPointBBox); + } + else + { + //this is an error case if it gets to here + } + } + +void CSvgTextElementImpl::GetBBoxForSVGText( TGfxRectangle2D& aBbox ) +{ + //bbox for svg fonts + TSvgFourPointRect lFourPtRect; + GetBBoxForSVGText(lFourPtRect,this->GetCTM()); + + lFourPtRect.GetTRect(aBbox); +} + +void CSvgTextElementImpl::GetBBoxForSVGText( TSvgFourPointRect& aFourPointBbox, const TGfxAffineTransform& aTransform) +{ + //bbox for svg fonts + TGfxRectangle2D lBbox; + + TFloatFixPt lascent = Ascent(); + TFloatFixPt ldescent = Descent(); + + // Fix for ANAE-739CPX + // When ascent and descent are not specified, get the + // the translated and scaled bounding-box for each glyph + // and then find the total bounding box. + TFloatFixPt KZero; + if(lascent<=KZero||ldescent<=KZero) + { + TGfxRectangle2D lBbox1; /* Final bounding box for the text */ + TFloatFixPt lFontSize; + CCssValue* lCssValue = NULL; + + // Get the font-size + this->FindProperty( KCSS_ATTR_FONTSIZE, lCssValue, NULL ); + if ( lCssValue ) + { + lFontSize = (( CFloatCssValueImpl * ) lCssValue )->Value(); + if(lFontSize <= KZero ) + { + lFontSize = TFloatFixPt ( KDefaultFontSize ); + } + } + + TFloatFixPt lUnitsPerEm( KDefaultUnitsPerEm ); + TFloatFixPt lUnitsPerEmInverse(KZero); + + // Get units-per-em + if (iFontFaceElement != NULL) + { + iFontFaceElement->GetAttributeFloat( KAtrUnitsPerEm, + lUnitsPerEm ); + + + if ( lUnitsPerEm <= KZero ) + { + lUnitsPerEm = TFloatFixPt( KDefaultUnitsPerEm ); + } + + lUnitsPerEmInverse = TFloatFixPt( KOne ) / lUnitsPerEm; + } + + TFloatFixPt lGlyphHorzAdvX(KZero); + TFloatFixPt lFontHorzAdvX(KZero); + TFloatFixPt lMissingGlyphHorzAdvX(KZero); + TFloatFixPt lK(KZero); + + if(iSVGFont) + { + // Get horiz-adv-x + iSVGFont->GetAttributeFloat( KAtrHorizAdvX, lFontHorzAdvX ); + } + + + if (iMissingGlyphElement != NULL) + { + iMissingGlyphElement->GetAttributeFloat( KAtrHorizAdvX, + lMissingGlyphHorzAdvX ); + + + if ( lMissingGlyphHorzAdvX == KZero ) + { + lMissingGlyphHorzAdvX = lFontHorzAdvX; + } + } + + // Get "k" for hkern + if(iHkernElement) + { + iHkernElement->GetAttributeFloat( KAtrK, lK ); + } + TFloatFixPt currentPosOrigX(iPoint.iX); + + // Find the total width of the BBox + TFloatFixPt lTotalTextAdvance =GetTotalTextAdvance(lK,lUnitsPerEmInverse,lFontSize,lMissingGlyphHorzAdvX,lFontHorzAdvX); + + //Get the text-anchor + TInt8 lTextAnchor =(TInt8)( + ((CIntCssValueImpl *)(iSvgStyleProperties->operator[]( + KCSS_ATTR_TEXTANCHOR)))->Value()); + + if( lTextAnchor == 1 )//Middle + { + currentPosOrigX -= (lTotalTextAdvance * TFloatFixPt(.5f)); + } + + if( lTextAnchor == 2 )//End + { + currentPosOrigX -= lTotalTextAdvance; + } + + TFloatFixPt minusOne( -1 ); + + // (xMin1, yMin1) is the Top-left-corner and + // (xMax1, yMax1) is the bottom-right-corner + // of the final bounding box for the text + TFloatFixPt xMin1(KMAXFLOATFIX), yMin1(KMAXFLOATFIX), xMax1(KMINFLOATFIX), yMax1(KMINFLOATFIX); + TGfxRectangle2D lBbox; + const TDesC& ltext=*iText; + TInt ltextLength = ltext.Length(); + TInt glyphEleCnt = iGlyphElements.Count(); + + for (TInt i= 0; i < ltextLength && i < glyphEleCnt; i++) + { + CSvgElementImpl* lGlyphElement = (CSvgElementImpl*)iGlyphElements[i]; + + CGfxGeneralPath* lShape = NULL; + if(lGlyphElement||iMissingGlyphElement) + { + // Tranformation Matrix for positioning and scaling the BBox + TGfxAffineTransform myCurrentTM = aTransform; + + myCurrentTM.Translate( currentPosOrigX, iPoint.iY); + + myCurrentTM.Scale( lUnitsPerEmInverse, + minusOne * lUnitsPerEmInverse ); + myCurrentTM.Scale( lFontSize, lFontSize ); + + if(lGlyphElement) + { + TInt checkErrorShape = lGlyphElement->GetAttributePath( + KAtrData,lShape ); + + lGlyphElement->GetAttributeFloat( KAtrHorizAdvX, + lGlyphHorzAdvX ); + + + if ( lGlyphHorzAdvX == KZero ) + { + lGlyphHorzAdvX = /*(TFloatFixPt)lUnicodeLength **/ lFontHorzAdvX; + } + currentPosOrigX += ( lGlyphHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + } + else + { + TInt checkErrorShape = iMissingGlyphElement-> + GetAttributePath(KAtrData,lShape ); + + currentPosOrigX += ( lMissingGlyphHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + } + // Get the tranformed BBox for each glyph + lShape->GetBounds(myCurrentTM, lBbox); + + // Find the (xMin1,yMin1) and (xMax1, yMax1) for the total + // bounding box of text + if(lBbox.iXyMax1) yMax1=lBbox.iY+lBbox.iHeight; + if((lBbox.iX+lBbox.iWidth)>xMax1) xMax1=lBbox.iX+lBbox.iWidth; + } + + } + lBbox1.iX=xMin1; + lBbox1.iY=yMin1; + lBbox1.iWidth=xMax1-xMin1; + lBbox1.iHeight=yMax1-yMin1; + + aFourPointBbox.SetRectPoints(lBbox1); + return; + } + // End of fix for ANAE-739CPX + + lBbox.iHeight = lascent + ldescent; + lBbox.iWidth = TextAdvance(*iText); + + TReal32 lascentReal = (TReal32)lascent; + TReal32 ldescentReal = (TReal32)ldescent; + TReal32 liHeightReal = (TReal32)lBbox.iHeight; + TReal32 liWidthReal = (TReal32)lBbox.iWidth; + + //////////////////// rotate without scaling again ////////////////////// + lBbox.iX = iPoint.iX; + lBbox.iY = iPoint.iY - lascent; + + //at this point the bbox not scaled,translated but not rotated + + //should we create 1/scale factor or create with scale factor then get inverse + /*TGfxAffineTransform aScaleMat; + TReal32 inverseScale = 1.0/(TReal)iScale; + aScaleMat = TGfxAffineTransform::GetScaleInstance(inverseScale, inverseScale); + */ + + const TGfxAffineTransform& ctm = aTransform; + + TGfxPoint2D transformedPoint(lBbox.iX, lBbox.iY); + ctm.Transform(&transformedPoint, &transformedPoint, 1); + + TGfxPoint2D lTopLeftCorner(lBbox.iX, lBbox.iY); + TGfxPoint2D lTopRightCorner(lBbox.iX + lBbox.iWidth, lBbox.iY); + TGfxPoint2D lBottomLeftCorner(lBbox.iX, lBbox.iY + lBbox.iHeight); + TGfxPoint2D lBottomRightCorner(lBbox.iX + lBbox.iWidth, lBbox.iY + lBbox.iHeight); + + TGfxPoint2D lTransTopLeftCorner; + TGfxPoint2D lTransBottomLeftCorner; + TGfxPoint2D lTransTopRightCorner; + TGfxPoint2D lTransBottomRightCorner; + + ctm.Transform(&lTopLeftCorner, &lTransTopLeftCorner,1); + ctm.Transform(&lTopRightCorner, &lTransTopRightCorner,1); + ctm.Transform(&lBottomLeftCorner, &lTransBottomLeftCorner,1); + ctm.Transform(&lBottomRightCorner, &lTransBottomRightCorner,1); + + TFloatFixPt lXTranslation = transformedPoint.iX - lTransTopLeftCorner.iX; + TFloatFixPt lYTranslation = (transformedPoint.iY - lTransTopLeftCorner.iY ); //- ascent; + + // X position is affected by anchor + switch( TextAnchor() ) + { + case EStartAnchor: + //do nothing + break; + case EMiddleAnchor: + lXTranslation = lXTranslation - ( lBbox.iWidth / TFloatFixPt( 2 ) ); + break; + case EEndAnchor: + lXTranslation = lXTranslation - lBbox.iWidth; + break; + default: + //do nothing + break; + } + + lTransTopLeftCorner.iX = lTransTopLeftCorner.iX + lXTranslation; + lTransTopLeftCorner.iY = lTransTopLeftCorner.iY + lYTranslation; + + lTransTopRightCorner.iX = lTransTopRightCorner.iX + lXTranslation; + lTransTopRightCorner.iY = lTransTopRightCorner.iY + lYTranslation; + + lTransBottomLeftCorner.iX = lTransBottomLeftCorner.iX + lXTranslation; + lTransBottomLeftCorner.iY = lTransBottomLeftCorner.iY + lYTranslation; + + lTransBottomRightCorner.iX = lTransBottomRightCorner.iX + lXTranslation; + lTransBottomRightCorner.iY = lTransBottomRightCorner.iY + lYTranslation; + + //at this point I have the exact path coordinates of the bbox + aFourPointBbox.SetRectPoints(lTransTopLeftCorner, lTransTopRightCorner, lTransBottomLeftCorner, lTransBottomRightCorner); + + //aFourPointBbox.SetRectPoints(aTopLeftCorner, aTopRightCorner, aBottomLeftCorner, aBottomRightCorner); + +} + +void CSvgTextElementImpl::GetBBoxForSystemText( TGfxRectangle2D& aBbox ) +{ + //bbox for bitmap fonts + TSvgFourPointRect lFourPtRect; + GetBBoxForSystemText(lFourPtRect); + + lFourPtRect.GetTRect(aBbox); + +} + +void CSvgTextElementImpl::GetBBoxForSystemText( TSvgFourPointRect& aFourPointBbox ) +{ + //bbox for bitmap fonts + TGfxRectangle2D lBbox; + + iScale = GetCurrentScale(); + + if (iBoundingBox.iWidth == 0 && iBoundingBox.iHeight == 0) + { + iBoundingBox.iWidth = iBitmapFont->TextWidthInPixels(iText->Des()); + iBoundingBox.iHeight = iBitmapFont->FontMaxHeight(); + } + + //scaled already for bitmap text... + lBbox.iWidth = iBoundingBox.iWidth; + lBbox.iHeight = iBoundingBox.iHeight; + TFloatFixPt lascent = Ascent(); + TFloatFixPt ldescent = TFloatFixPt(iBoundingBox.iHeight) - Ascent(); + TReal32 linverseScale = 1.0/(TReal)iScale; + + TGfxAffineTransform lInitTranslationMat = TGfxAffineTransform::GetTranslateInstance(iPoint.iX,iPoint.iY); + TGfxAffineTransform lTotalMat = GetCTM(); + lTotalMat.Concatenate(lInitTranslationMat); + TGfxAffineTransform lInverseScaleMat = TGfxAffineTransform::GetScaleInstance(linverseScale, linverseScale); + lTotalMat.Concatenate(lInverseScaleMat); + TGfxAffineTransform lDescentCorrectionMat =TGfxAffineTransform::GetTranslateInstance(0,ldescent); + lTotalMat.Concatenate(lDescentCorrectionMat); + + TGfxPoint2D lTopLeftCorner(0, TFloatFixPt(0) - lBbox.iHeight ); + TGfxPoint2D lTopRightCorner(lBbox.iWidth , TFloatFixPt(0) - lBbox.iHeight ); + TGfxPoint2D lBottomLeftCorner(0, 0); + TGfxPoint2D lBottomRightCorner(lBbox.iWidth, 0 ); + + + TGfxPoint2D lTransTopLeftCorner; + TGfxPoint2D lTransBottomLeftCorner; + TGfxPoint2D lTransTopRightCorner; + TGfxPoint2D lTransBottomRightCorner; + + //applying current rotation transform without the scale. + lTotalMat.Transform(&lTopLeftCorner, &lTransTopLeftCorner,1); + lTotalMat.Transform(&lTopRightCorner, &lTransTopRightCorner,1); + lTotalMat.Transform(&lBottomLeftCorner, &lTransBottomLeftCorner,1); + lTotalMat.Transform(&lBottomRightCorner, &lTransBottomRightCorner,1); + + TFloatFixPt lXTranslation = 0; + //TFixPt lXTranslation = transformedPoint.iX - iPoint.iX; + + TFloatFixPt lYTranslation = 0; + //TFixPt lYTranslation = transformedPoint.iY - iPoint.iY; + + // X position is affected by anchor + switch( TextAnchor() ) + { + case EStartAnchor: + //do nothing + break; + case EMiddleAnchor: + lXTranslation = lXTranslation - ( lBbox.iWidth / TFloatFixPt( 2 ) ); + break; + case EEndAnchor: + lXTranslation = lXTranslation - lBbox.iWidth; + break; + default: + //do nothing + break; + } + + lTransTopLeftCorner.iX += lXTranslation; + lTransTopLeftCorner.iY += lYTranslation; + + lTransTopRightCorner.iX += lXTranslation; + lTransTopRightCorner.iY += lYTranslation; + + lTransBottomLeftCorner.iX += lXTranslation; + lTransBottomLeftCorner.iY += lYTranslation; + + lTransBottomRightCorner.iX += lXTranslation; + lTransBottomRightCorner.iY += lYTranslation; + + //at this point I have the exact path coordinates of the bbox + aFourPointBbox.SetRectPoints(lTransTopLeftCorner, lTransTopRightCorner, lTransBottomLeftCorner, lTransBottomRightCorner); +} + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::GetUnscaledBBox( TGfxRectangle2D& aBbox ) + { + if((iText->Des()).Length()==0) + { + aBbox.iHeight=0; + aBbox.iWidth=0; + aBbox.iX=0; + aBbox.iY=0; + return; + + } + // If both bitmap font and SVG font are not present then + // attempt to fetch SVG font. If that fails then + // try obtaining the bitmap font + if ( iSVGFont ) + { + TSvgFourPointRect lFourPtRect; + TGfxAffineTransform TM ; + GetBBoxForSVGText(lFourPtRect,TM); + + lFourPtRect.GetTRect(aBbox); + return; + } + + else + + { + + TRAPD( ErrCode , CreateSVGFontL()); + if( ErrCode != KErrNotFound) + { + //first en cache the glymph and then + //calculate total text advance + TSvgFourPointRect lFourPtRect; + TGfxAffineTransform TM ; + GetBBoxForSVGText(lFourPtRect,TM); + lFourPtRect.GetTRect(aBbox); + return; + } + + + else + { + UpdateCurrentScaledFont(); + iBoundingBox.iWidth = iBitmapFont->TextWidthInPixels(iText->Des()); + iBoundingBox.iHeight = iBitmapFont->FontMaxHeight(); + + //unscaled for bitmap text... + aBbox.iWidth = iBoundingBox.iWidth; + TFloatFixPt ascent = Ascent(); + //aBbox.iHeight = ascent + Descent(); + + aBbox.iHeight = iBoundingBox.iHeight; + + aBbox.iY = iPoint.iY - ascent; + + // X position is affected by anchor + switch( TextAnchor() ) + { + case EStartAnchor: + aBbox.iX = iPoint.iX; + break; + case EMiddleAnchor: + aBbox.iX = iPoint.iX - ( aBbox.iWidth / TFloatFixPt( 2 ) ); + break; + case EEndAnchor: + aBbox.iX = iPoint.iX - aBbox.iWidth; + break; + default: + aBbox.iX = iPoint.iX; + break; + } + + } + + } + + + } + + + + +void CSvgTextElementImpl::SetRotateArray(CArrayFixFlat*& aRotate) + { + if ( iArrayRotate ) + { + iArrayRotate->Reset(); + delete iArrayRotate; + iArrayRotate= NULL; + } + + iArrayRotate= aRotate; +/* TInt lCount= aRotate->Count(); + iArrayRotate = new ( ELeave ) CArrayFixFlat( lCount ); + + for (TInt i=0; iAppendL((TReal32)aRotate->operator[](i)); + } + */ + } + +void CSvgTextElementImpl::SetXYArray(TUint16 aAtrId, CArrayFixFlat*& aX ) + { + if (aAtrId== KAtrX) + { + if ( iArrayX ) + { + iArrayX->Reset(); + delete iArrayX; + iArrayX = NULL; + } + iArrayX= aX; + SetX(aX); + } + else + { + if ( iArrayY ) + { + iArrayY->Reset(); + delete iArrayY; + iArrayY = NULL; + } + iArrayY= aX; + SetY(aX); + } + } + +TFloatFixPt CSvgTextElementImpl::FontSize() +{ + CCssValue* cssValue = NULL; + FindProperty( KCSS_ATTR_FONTSIZE, cssValue, this ); + if ( cssValue ) + { + TFloatFixPt fontsize = ((CFloatCssValueImpl*)cssValue)->Value(); + if ( fontsize <= TFloatFixPt( 0 ) ) + fontsize = TFloatFixPt( 10 ); + return fontsize; + } + else + { + return 10; + } +} + +TFloatFixPt CSvgTextElementImpl::TextAdvance( const TDesC& aText, TInt aIndex ) +{ + if ( iBitmapFont ) + { + TInt advance = 0; + UpdateCurrentScaledFont(); + if ( iBitmapFont) + { + advance = ((CFbsFont*)iBitmapFont)->TextWidthInPixels(aText); + + return TFloatFixPt(advance); + } + + return 0; + } + else if ( iSVGFont ) + { + //if an svg font... + TReal32 fontHorzAdvX = 0.0; + TFloatFixPt advanceX = TFloatFixPt( 0 ); + + TInt textLength = aText.Length(); + TInt glyphEleCnt = iGlyphElements.Count(); + for (TInt i= aIndex; i < (aIndex+textLength) && (i< glyphEleCnt); i++) + { + //assuming that glyph element cache is a parallel vector here + CSvgElementImpl* lGlyphElement = (CSvgElementImpl*)iGlyphElements[i]; + + if (lGlyphElement != NULL) + { + lGlyphElement->GetAttributeFloat( KAtrHorizAdvX, advanceX ); + fontHorzAdvX += (TReal32)advanceX; + } + } + + TFloatFixPt lUnitsPerEm = TFloatFixPt(1000); + + if (iFontFaceElement) + { + iFontFaceElement->GetAttributeFloat( KAtrUnitsPerEm, lUnitsPerEm); + + if (lUnitsPerEm == TFloatFixPt(0)) + { + lUnitsPerEm = TFloatFixPt(1000); + } + } + + // Must use TReal to prevent overflow + TReal32 retValue = fontHorzAdvX * (TReal32)FontSize() / (TReal32)lUnitsPerEm; + return (TFloatFixPt)retValue; + } + else + { + //case where we dont have a bitmap font or an svg font + return 0; + } +} + + + +TFloatFixPt CSvgTextElementImpl::Ascent() +{ + + //check for the bbox issue + if ( iSVGFont ) + { + //if an svg font the ascent is this... + + TFloatFixPt lAscent, lUnitsPerEm; + TReal32 totalAscent = 0.0; + + if (iFontFaceElement) + { + iFontFaceElement->GetAttributeFloat( KAtrAscent, + lAscent ); + + iFontFaceElement->GetAttributeFloat( KAtrUnitsPerEm, lUnitsPerEm); + + if(lUnitsPerEm==TFloatFixPt(0)) + { + lUnitsPerEm=TFloatFixPt(1000); + } + totalAscent = (TReal32)lAscent * (TReal32)FontSize() / (TReal32)lUnitsPerEm; + + return (TFloatFixPt)totalAscent; + } + + //default value for ascent + return 0; + } + else if ( iBitmapFont ) + { + // if ( iBitmapFont ) + + UpdateCurrentScaledFont(); + //if a bitmap font the ascent is this.... + TInt ascent = 10; + + if (iBitmapFont) + { + //Tweak factor is needed as font not behaving correctly for + // all languages. + ascent = iBitmapFont->FontMaxAscent() + 1; + } + else + { + } + + return ( ascent >= 0 ) ? ascent : -ascent; + } + + else + { + //case where we dont have a bitmap font or svg font + return 0; + } + } + +const CFont* CSvgTextElementImpl::Font() const + { + return iBitmapFont; + } + +TFloatFixPt CSvgTextElementImpl::Descent() +{ + + //check for the bbox issue + if ( iSVGFont ) + { + //for svg fonts... + //if an svg font the descent is this... + + TFloatFixPt lDescent, lUnitsPerEm; + TReal32 totalDescent = 0.0; + + if (iFontFaceElement) + { + iFontFaceElement->GetAttributeFloat( KAtrDescent, + lDescent ); + + iFontFaceElement->GetAttributeFloat( KAtrUnitsPerEm, lUnitsPerEm); + + if(lUnitsPerEm==TFloatFixPt(0)) + { + lUnitsPerEm=TFloatFixPt(1000); + } + + totalDescent = (TReal32)lDescent * (TReal32)FontSize() / (TReal32)lUnitsPerEm; + + return ( totalDescent >= 0 ) ? (TFloatFixPt)totalDescent : (TFloatFixPt)-totalDescent; + } + + return 0; + } + else if ( iBitmapFont ) + { + UpdateCurrentScaledFont(); + //for bitmap fonts... + TInt descent = 10; + + if (iBitmapFont) + { + descent = iBitmapFont->DescentInPixels(); + } + else + { + } + + return ( descent >= 0 ) ? descent : -descent; + + } + else + { + //case where we dont have a bitmap font or svg font + return 0; + } +} + +TTextAnchor CSvgTextElementImpl::TextAnchor() +{ + + TInt anchor = ((CIntCssValueImpl*)((*iSvgStyleProperties)[KCSS_ATTR_TEXTANCHOR]))->Value(); + return ( anchor == -1 ) ? EStartAnchor : (TTextAnchor)anchor; +} + +TBool CSvgTextElementImpl::LoadExternalSVGFontL(const TDesC& aFontFamily) +{ + CSvgEngineImpl* lEngine = ((CSvgDocumentImpl*)iOwnerDocument)->Engine(); + CSvgDocumentImpl* lNewFontDoc = NULL; + + if (lEngine == NULL) + { + return EFalse; + } + + if ( lEngine->iFontHashMap->HasFontFamilyName(aFontFamily) ) + { + //already have that font + return EFalse; + } + else + { + CSvgBitmapFontProvider *tempBitmapFontProvider = ((CSvgDocumentImpl*)iOwnerDocument)->GetBitmapFontProvider(); + lNewFontDoc = CSvgDocumentImpl::NewL( tempBitmapFontProvider ); + lNewFontDoc->SetEngine(lEngine); + } + + if (aFontFamily.Length() > 0) + { + TBuf<256> myFontUrl; + myFontUrl.Copy(aFontFamily.Left(24)); + myFontUrl.Append(_L(".svg")); + + if (FetchSvgFontL(myFontUrl, lNewFontDoc)) + { + if ( lEngine->iFontHashMap->AddFontDocument(lNewFontDoc, aFontFamily) ) + { + return ETrue; + } + } + } + + //If basic latin use SVG DEFAULT FONT + if ( iUseDefaultSVGFont && !lEngine->iFontHashMap->HasFontFamilyName(aFontFamily)) + { + if (FetchSvgFontL(_L("defaultsvgfont.svg"), lNewFontDoc)) + { + TBool aReturn = lEngine->iFontHashMap->AddFontDocument(lNewFontDoc, KDefaultFont ); + + //this will overwrite whatever font family the element had set... + //remove this to let fonts fall through to bitmap their specified bitmap fonts + //SetFontFamilyL(_L("NokiaSansWide")); + if(!aReturn) + { + if(lNewFontDoc) + { + delete lNewFontDoc; + lNewFontDoc = NULL; + } + + } + return ETrue; + } + /*else if (LoadDefaultSvgFont(iNewFontDoc)) + { + if (iEngine->AddFontDocument(iNewFontDoc, aFontFamily)) + { + return ETrue; + } + }*/ + } + + delete lNewFontDoc; + lNewFontDoc = NULL; + return EFalse; +} + +TBool CSvgTextElementImpl::IsEditable() +{ + return iEditable; +} + +TBool CSvgTextElementImpl::FetchSvgFontL(const TDesC& aUri, CSvgDocumentImpl* newFontDocument) +{ + CSvgErrorImpl* lmyError = CSvgErrorImpl::NewL(); + + //do a fetchimage style fetch of the SVG font file here... + // Connect session + RFs lSession; + RFile fileHandle; + if ( lSession.Connect() == KErrNone ) + { + CSvgEngineImpl* lEngine = ((CSvgDocumentImpl*)iOwnerDocument)->Engine(); + + if (lEngine->FetchFont( aUri, lSession, fileHandle)) + { + TBuf<512> aName; + + fileHandle.Name(aName); + + if ( aName.CompareF(aUri) == 0) + { + //need to attach this to the real document and just once for all text elements + newFontDocument->Load( fileHandle, *lmyError ); + } + else + { + lSession.Close(); + delete lmyError; + return EFalse; + } + + if (lmyError->ErrorCode() == ESvgNoError) + { + lSession.Close(); + delete lmyError; + return ETrue; + } + } + else + { + lSession.Close(); + } + } + + delete lmyError; + return EFalse; +} + + +/*TBool CSvgTextElementImpl::LoadDefaultSvgFont(CSvgDocumentImpl* newFontDocument) +{ + CSvgErrorImpl* myError = CSvgErrorImpl::NewL(); + CSvgEngineImpl* iEngine = ((CSvgDocumentImpl*)iOwnerDocument)->Engine(); + + TPtrC8 svgfontdata( (TUint8*)strSVGFont, User::StringLength((TUint8*)strSVGFont) ); + iEngine->newFontDocument->Load( svgfontdata, *myError ); + + if (myError->ErrorCode() != ESvgNoError) + { + delete myError; + return EFalse; + } + + delete myError; + return ETrue; +}*/ + +/*** FROM MSvgMouseListener ***/ +// --------------------------------------------------------------------------- +// mouse entered +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::MouseEntered( RPointerArray& aElements, + TInt /*aX*/, TInt /*aY*/ ) +{ + CSvgEngineImpl* lEngine = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine(); + + TInt eleCnt = aElements.Count(); + for (TInt i = 0; i < eleCnt; i++ ) + { + if ( aElements[i] == this ) + { + lEngine->NotifyTextEntered(this); + return ETrue; + } + } + + return EFalse; +} + +// --------------------------------------------------------------------------- +// Notified when the mouse pointer exits a visible svg element. +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::MouseExited( RPointerArray& aElements, + TInt /*aX*/, TInt /*aY*/ ) +{ + CSvgEngineImpl* lEngine = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine(); + + TInt eleCnt = aElements.Count(); + for (TInt i = 0; i < eleCnt; i++ ) + { + if ( aElements[i] == this ) + { + lEngine->NotifyTextExited(this); + return ETrue; + } + } + + return EFalse; +} + +// --------------------------------------------------------------------------- +// Notified when the mouse pointer is moved inside a visible svg element. +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::MouseMoved( RPointerArray& /*aElements*/, + TInt /*aX*/, TInt /*aY*/ ) +{ + return EFalse; +} + +// --------------------------------------------------------------------------- +// Notified when the mouse pointer is pressed down on visible svg element. +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::MousePressed( RPointerArray& /*aElements*/, + TInt /*aX*/, TInt /*aY*/ ) +{ + return EFalse; +} + +// --------------------------------------------------------------------------- +// Notified when the mouse pointer is released on on visible svg element. +// --------------------------------------------------------------------------- +TBool CSvgTextElementImpl::MouseReleased( RPointerArray& aElements, + TInt /*aX*/, TInt /*aY*/ ) +{ + CSvgEngineImpl* lEngine = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine(); + + TInt eleCnt = aElements.Count(); + for (TInt i = 0; i < eleCnt; i++ ) + { + if ( aElements[i] == this ) + { + lEngine->NotifyTextActivated(this); + return ETrue; + } + } + + return EFalse; +} + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void CSvgTextElementImpl::SetEditable( const TDesC& aValue ) +{ + if (aValue.FindF(_L("simple")) == KErrNotFound && aValue.FindF(_L("true")) == KErrNotFound) + { + iEditable = EFalse; + } + else + { + iEditable = ETrue; + } +} + +void CSvgTextElementImpl::Print( TBool aIsEncodeOn ) +{ + if (!aIsEncodeOn) + { + #ifdef _DEBUG + RDebug::Printf("hmm", (int)iPoint.iX, (int)iPoint.iY, (int)IsEditable()/*, iText*/); + #endif + } +} + +void CSvgTextElementImpl::UpdateCurrentScaledFont() + { + + // Get latest scaling factor + TFloatFixPt scale = GetCurrentScale(); + + TFloatFixPt fontsize = (TFloatFixPt)FontSize(); + + TFloatFixPt fontHeight = scale * fontsize; + // RDebug::Printf("Requesting fontHeight: %d\n", (TInt)fontHeight); + + GetScaledFont( fontHeight, (*iFamilies)[0], iBitmapFont, iBitmapFontSpec ); + // RDebug::Printf("Ascent : %d\n", (TInt)iBitmapFont->AscentInPixels()); + // RDebug::Printf("Descent: %d\n", (TInt)iBitmapFont->DescentInPixels()); + } +// -------------------------------------------------------------------------- +// void CGfx2dGcOpenVG::GetSystemFontScaled(TFloatFixPt aHeight, +// const TDesC& aTypefaceName,// CFont*& aFont, +// TFontSpec& aFontSpec ) +// --------------------------------------------------------------------------- + void CSvgTextElementImpl::GetScaledFont( TFloatFixPt aHeight, + const TDesC& aTypefaceName, + CFont*& aFont, + TFontSpec& aFontSpec ) + { + if (aHeight >= TFloatFixPt(300)) + { + aHeight = TFloatFixPt(300); + } + + // Calculate twip size + TInt twipsSize; + if( aHeight > TFloatFixPt(0) ) + { + TInt xpixels,ypixels,xtwips,ytwips; + HAL::Get(HALData::EDisplayXPixels, xpixels); + HAL::Get(HALData::EDisplayYPixels, ypixels); + HAL::Get(HALData::EDisplayXTwips, xtwips); + HAL::Get(HALData::EDisplayYTwips, ytwips); + + if ( xpixels == 0 ) + { + return; + } + + TFloatFixPt ratio = TFloatFixPt(xtwips)/(TFloatFixPt)xpixels; + twipsSize = (TInt) (ratio * aHeight);//((float)ytwips/ypixel) is same + } + else + { + return; + } + + TFontStrokeWeight strokeWeight = EStrokeWeightNormal; + TFontPosture fontPosture = EPostureUpright ; + + // Get font-weight + TInt32 fontweight = 1; + CCssValue* weightValue = NULL; + FindProperty( KCSS_ATTR_FONTWEIGHT, weightValue, this ); + + if ( weightValue ) + { + fontweight = ((CIntCssValueImpl*)weightValue)->Value(); + } + + if ( ( fontweight == 1 ) || + ( fontweight == 2 ) || + ( fontweight == 9 ) || + ( fontweight == 10 ) || + ( fontweight == 11 ) || + ( fontweight == 12 ) ) // Bold + { + strokeWeight = EStrokeWeightBold; + } + else + { + strokeWeight = EStrokeWeightNormal; + } + + // Get font-style + TInt32 style = 1; + CCssValue* styleValue = NULL; + FindProperty( KCSS_ATTR_FONTSTYLE, styleValue, this ); + + if ( styleValue ) + { + style = ((CIntCssValueImpl*)styleValue)->Value(); + } + + if ( style == 1 ) + { + //Italic + fontPosture = EPostureItalic; + } + else + { + fontPosture = EPostureUpright; + } + + + TFontStyle fontStyle( fontPosture, strokeWeight, EPrintPosNormal ); + + // Get Latest required Font Spec. + TFontSpec tempFontSpec(aFontSpec); + tempFontSpec.iTypeface.iName = aTypefaceName.Left(24); + tempFontSpec.iHeight = twipsSize; + tempFontSpec.iFontStyle = fontStyle; + + CSvgBitmapFontProvider *tempBitmapFontProvider = ((CSvgDocumentImpl*)iOwnerDocument)->GetBitmapFontProvider(); + if( aFont ) + { + if(!(tempFontSpec == aFontSpec)) + { + aFontSpec = tempFontSpec; + tempBitmapFontProvider->ReleaseFont(aFont); + tempBitmapFontProvider->GetNearestFontToDesignHeightInTwips(aFont, aFontSpec); + } + } + else + { + aFontSpec = tempFontSpec; + tempBitmapFontProvider->GetNearestFontToDesignHeightInTwips(aFont, aFontSpec); + } + + } +// --------------------------------------------------------------------------- + // Calculate the exact total text advance instead of taking default per glyph + // advance which will approximate the value. +// --------------------------------------------------------------------------- + TFloatFixPt CSvgTextElementImpl::GetTotalTextAdvance(const TFloatFixPt& alK,const TFloatFixPt& alUnitsPerEmInverse,const TFloatFixPt& alFontSize,const TFloatFixPt& alMissingGlyphHorzAdvX,const TFloatFixPt& alFontHorzAdvX) + { + //Text Anchor related. + //lFontHorzAdvX = 400; + //lTotalTextAdvance = lFontHorzAdvX * (TFloatFixPt)iText->Length() * lUnitsPerEmInverse * lFontSize; + + + TFloatFixPt lGlyphHorzAdvX; + TInt langCodeFound( 0 ); + TInt8 lTextAnchor =(TInt8)(((CIntCssValueImpl *)(iSvgStyleProperties->operator[](KCSS_ATTR_TEXTANCHOR)))->Value()); + TPtrC16 lPrevGlyphName; + TPtrC16 lCurrGlyphName; + TFloatFixPt lK = alK; //kerning purpose.... + TFloatFixPt KZero; + TFloatFixPt lTotalTextAdvance ( KZero ); + TPtrC16 lUnicode; + TPtrC16 lLangCode; //ex: en-US or en-GB or ja-JP or zh-CN or en.... + TPtrC16 lPrevUnicode; + TPtrC16 lUnicodeRange; //Max.Length "U+00AB-00AF" + TFloatFixPt lUnitsPerEmInverse = alUnitsPerEmInverse; + TFloatFixPt lFontSize = alFontSize; + TFloatFixPt lFontHorzOrgX( 0 ); + TFloatFixPt lFontHorzAdvX = alFontHorzAdvX; + TFloatFixPt lMissingGlyphHorzAdvX = alMissingGlyphHorzAdvX; + + + TInt glyphEleCnt = iGlyphElements.Count(); + for (TInt i=0; i < glyphEleCnt; i++) + { + CSvgElementImpl* lGlyphElement = (CSvgElementImpl*)iGlyphElements[i]; + + if (lGlyphElement != NULL) + { + //have a valid glyph + TInt checkErrorUnicode = lGlyphElement->GetAttributeDes( KAtrUnicode, + lUnicode ); + //check the glyph name + TInt checkErrorGlyphName = lGlyphElement->GetAttributeDes( KAtrGlyphName, + lCurrGlyphName ); + if( checkErrorGlyphName == KErrNoAttribute ) + { + lCurrGlyphName.Set( KGlyphNameNone ); + } + + //check its language + TInt checkErrorLangCode = lGlyphElement->GetAttributeDes( KAtrLang, + lLangCode ); + TPtrC lXmlLangAttr(this->XMLLang()); + + if( checkErrorLangCode != KErrNoAttribute ) //if Lang code present + { + langCodeFound = lLangCode.CompareF( lXmlLangAttr );//compare xml:lang with Lang code. + } + + //if Lang code is matching && unicode attr. present, we are good. + if ( (checkErrorUnicode != KErrNoAttribute) && (langCodeFound == 0) ) + { + //Checking and Introducing kerning(adjusting spacing). + if( lPrevGlyphName.Length() > 0 ) + { + if( IsKerningRequired( lPrevGlyphName, lCurrGlyphName, lPrevUnicode, lUnicode )) + { + lTotalTextAdvance -= ( lK * lUnitsPerEmInverse ) * lFontSize; + } + } + + lGlyphElement->GetAttributeFloat( KAtrHorizAdvX, + lGlyphHorzAdvX ); + + #ifdef SVG_FLOAT_BUILD + if ( lGlyphHorzAdvX == TFloatFixPt( 0 ) ) + #else + if ( lGlyphHorzAdvX == TFloatFixPt( 0,ETrue ) ) + #endif + { + lGlyphHorzAdvX = /*(TFloatFixPt)lUnicodeLength **/ lFontHorzAdvX; + } + + + lTotalTextAdvance += ( lGlyphHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + + + } + + + } + else + { + //need to use missing glyph for this one... + + lTotalTextAdvance += ( lMissingGlyphHorzAdvX * lUnitsPerEmInverse ) * lFontSize; + + } + }//end-for + + + return lTotalTextAdvance ; + + }// End Function +void CSvgTextElementImpl::CreateSVGFontL() +{ + CCssValue* lCssValue = NULL; + + TPtrC lFontFamily; + //Getting font-family property + this->FindProperty( KCSS_ATTR_FONTFAMILY, lCssValue,this ); + if ( lCssValue && ((( CStrCssValueImpl * ) lCssValue )->Value()).Length() != 0) + { + lFontFamily.Set( ( ( CStrCssValueImpl * ) lCssValue )->Value() ); + SetFontFamilyL( lFontFamily ); + } + + //attempt to load svg font files of same font family name + //this boolean will be a problem if we want to be able to swap + //font-family names on the fly and use svg fonts. + if (!iTriedLoadingSVGFonts) + { + LoadExternalSVGFontL(lFontFamily); + iTriedLoadingSVGFonts = ETrue; + } + + //Retrieving Font Element Pointer from the Font Table + //if font in svg document + iSVGFont = NULL; + if ( iFamilies != NULL ) + { + TInt familiesCnt = iFamilies->Count(); + for (int i=0; i< familiesCnt; i++) + { + // In JSR-226 case, the engine may not have been created yet. + if ( ((CSvgDocumentImpl*)iOwnerDocument)->Engine() ) + { + iSVGFont = ( CSvgElementImpl * )((CSvgDocumentImpl*)iOwnerDocument)->Engine()->iFontHashMap->GetFontPtr(iFamilies->operator[]( i )); + } + + if (iSVGFont == NULL) + { + iSVGFont = ( CSvgElementImpl * )((CSvgDocumentImpl*)iOwnerDocument)->iFontHashMap->GetFontPtr(iFamilies->operator[]( i ) ); + } + + if (iSVGFont != NULL) + { + //found a font with that family name...continue + break; + } + } + } + +/**********************************************************/ +/* Checking for pre-defined SVG Fonts through the */ +/* retrieved pointer from the Font Table. */ +/* IF the Font is found (ptr!=NULL), SVG Fonts are used */ +/* ELSE Bitmap Font is used through DrawString() method */ +/**********************************************************/ + + if(!iSVGFont) + { + User::Leave(KErrNotFound); + } + + if ( iSVGFont != NULL && iSVGFont->HasChildNodes()) + { + //we found an svg font and are using it... + // iSVGFont->GetAttributeFloat( KAtrHorizOriginX, lFontHorzOrgX ); + // iSVGFont->GetAttributeFloat( KAtrHorizAdvX, lFontHorzAdvX ); + // lMissingGlyphHorzAdvX = lFontHorzAdvX; //Default Value + // TInt checkErrShapeMG = -1;//To keep a value other than KErrNone. Should this be replaced + CacheGlyphsForText(); + } + + + + + + +} +