--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/SVG/SVGImpl/src/SVGTextElementImpl.cpp Thu Jan 07 16:19:02 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 <e32base.h>
+#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<TFloatFixPt>( 1 );
+ iArrayY = new ( ELeave ) CArrayFixFlat<TFloatFixPt>( 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<CCssValue>(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<TFloatFixPt>* aX )
+ {
+ if (aX->Count() > 0)
+ {
+ aX->At( 0 ) = iPoint.iX;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextElementImpl::GetY( CArrayFix<TFloatFixPt>* 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<TReal32>( 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<TFloatFixPt>* 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<TFloatFixPt>( 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<TFloatFixPt>* aX )
+ {
+ if (aX->Count() > 0)
+ {
+ iPoint.iX = aX->At( 0 );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextElementImpl::SetY( CArrayFix<TFloatFixPt>* 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<TFloatFixPt>( 1 );
+ }
+
+ iArrayX->Reset();
+ iArrayX->AppendL((TFloatFixPt)aValue);
+ }
+ break;
+ case KAtrY:
+ {
+ iPoint.iY = aValue;
+ if(!iArrayY)
+ {
+ iArrayY= new ( ELeave ) CArrayFixFlat<TFloatFixPt>( 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; i<lCount; i++)
+ {
+ TPtrC lPtr= (this->iFamilies)->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<TFloatFixPt>( 1 );
+ for(TInt i=0; i<lCount; i++)
+ {
+ TFloatFixPt lFix= (this->iArrayX)->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<TFloatFixPt>( 1 );
+ for(TInt i=0; i<lCount; i++)
+ {
+ TFloatFixPt lFix= (this->iArrayY)->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<TReal32>( 1 );
+ for(TInt i=0; i<lCount; i++)
+ {
+ TReal32 lFix= (this->iArrayRotate)->operator[](i);
+ aDestElement->iArrayRotate->AppendL(lFix);
+ }
+ }
+ }
+
+///////////////////Cloning the glyph elements///////////////////////
+ TInt lCount= (this->iGlyphElements).Count();
+ if(lCount)
+ {
+ for(TInt i=0; i<lCount; i++)
+ {
+ CSvgElementImpl* element = (this->iGlyphElements).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 <text> 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) && (i<iArrayY->Count() ) )
+ {
+ 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) && (i<iArrayY->Count() ) )
+ {
+ 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.iX<xMin1) xMin1=lBbox.iX;
+ if(lBbox.iY<yMin1) yMin1=lBbox.iY;
+ if((lBbox.iY+lBbox.iHeight)>yMax1) 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<TReal32>*& aRotate)
+ {
+ if ( iArrayRotate )
+ {
+ iArrayRotate->Reset();
+ delete iArrayRotate;
+ iArrayRotate= NULL;
+ }
+
+ iArrayRotate= aRotate;
+/* TInt lCount= aRotate->Count();
+ iArrayRotate = new ( ELeave ) CArrayFixFlat<TReal32>( lCount );
+
+ for (TInt i=0; i<lCount; i++)
+ {
+ iArrayRotate->AppendL((TReal32)aRotate->operator[](i));
+ }
+ */
+ }
+
+void CSvgTextElementImpl::SetXYArray(TUint16 aAtrId, CArrayFixFlat<TFloatFixPt>*& 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<CSvgElementImpl>& 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<CSvgElementImpl>& 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<CSvgElementImpl>& /*aElements*/,
+ TInt /*aX*/, TInt /*aY*/ )
+{
+ return EFalse;
+}
+
+// ---------------------------------------------------------------------------
+// Notified when the mouse pointer is pressed down on visible svg element.
+// ---------------------------------------------------------------------------
+TBool CSvgTextElementImpl::MousePressed( RPointerArray<CSvgElementImpl>& /*aElements*/,
+ TInt /*aX*/, TInt /*aY*/ )
+{
+ return EFalse;
+}
+
+// ---------------------------------------------------------------------------
+// Notified when the mouse pointer is released on on visible svg element.
+// ---------------------------------------------------------------------------
+TBool CSvgTextElementImpl::MouseReleased( RPointerArray<CSvgElementImpl>& 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("<text x=\"%d\" y=\"%d\" editable=\"%d\" >hmm</text>", (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();
+ }
+
+
+
+
+
+
+}
+