svgtopt/SVG/SVGImpl/src/SVGTextAreaElementImpl.cpp
changeset 0 d46562c3d99d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/SVG/SVGImpl/src/SVGTextAreaElementImpl.cpp	Thu Jan 07 16:19:02 2010 +0200
@@ -0,0 +1,1031 @@
+/*
+* 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 <AknBidiTextUtils.h>
+
+#include "SVGTextAreaElementImpl.h"
+#include "SVGRectElementImpl.h"
+#include "SVGTextElementImpl.h"
+#include "SVGElementImpl.h"
+#include "SVGDocumentImpl.h"
+#include "SVGSchemaData.h"
+#include "SVGEngineImpl.h"
+#include "GfxAffineTransform.h"
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+CSvgTextAreaElementImpl* CSvgTextAreaElementImpl::NewL(  const TUint8 aElemID,
+												CSvgDocumentImpl* aDoc )
+{
+	CSvgTextAreaElementImpl*self    = new ( ELeave ) CSvgTextAreaElementImpl( aDoc );
+	CleanupStack::PushL( self );
+	self->ConstructL(  aElemID);
+	CleanupStack::Pop();
+
+	return self;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+CSvgTextAreaElementImpl* CSvgTextAreaElementImpl::NewLC(  const TUint8 aElemID,
+												 CSvgDocumentImpl* aDoc )
+{
+	CSvgTextAreaElementImpl*self    = new ( ELeave ) CSvgTextAreaElementImpl( aDoc );
+	CleanupStack::PushL( self );
+	self->ConstructL(  aElemID );
+
+	return self;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+CSvgTextAreaElementImpl::~CSvgTextAreaElementImpl()
+{
+    if ( iSvgStyleProperties )
+		{
+			iSvgStyleProperties->Close();
+			delete iSvgStyleProperties;
+			iSvgStyleProperties = NULL;
+		}
+
+		if ( iInnerRectangle )
+		{
+			this->RemoveChild(iInnerRectangle);
+			delete iInnerRectangle;
+			iInnerRectangle = NULL;
+		}
+
+		if ( iBorderRectangle )
+		{
+			this->RemoveChild(iBorderRectangle);
+			delete iBorderRectangle;
+			iBorderRectangle = NULL;
+		}
+
+		if (iTextElementsArray)
+		{
+			iTextElementsArray->Reset();
+			iTextElementsArray->Close();
+			delete iTextElementsArray;
+			iTextElementsArray = NULL;
+		}
+	if (iAllText)
+	{
+		delete iAllText;
+		iAllText = NULL;
+	}
+
+	((CSvgDocumentImpl*)OwnerDocument())->RemoveInternalMouseListener( this );
+
+}
+
+// *******************************************************
+// From SVG DOM
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgTextAreaElementImpl::X()
+{
+	if (!iInitialized)
+	{
+		return 0;
+	}
+
+    return iBorderRectangle->X();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgTextAreaElementImpl::Y()
+{
+	if (!iInitialized)
+	{
+		return 0;
+	}
+
+    return iBorderRectangle->Y();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgTextAreaElementImpl::Width()
+{
+	if (!iInitialized)
+	{
+		return 0;
+	}
+
+    return iBorderRectangle->Width();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgTextAreaElementImpl::Height()
+{
+	if (!iInitialized)
+	{
+		return 0;
+	}
+
+    return iBorderRectangle->Height();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgTextAreaElementImpl::Rx()
+{
+	if (!iInitialized)
+	{
+		return 0;
+	}
+
+    return iBorderRectangle->Rx();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgTextAreaElementImpl::Ry()
+{
+	if (!iInitialized)
+	{
+		return 0;
+	}
+
+    return iBorderRectangle->Ry();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::IsEditable()
+{
+    return iEditable;
+}
+
+
+// ---------------------------------------------------------------------------
+// For JSR support
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::SetTextAreaDimensions(TFloatFixPt aX, TFloatFixPt aY, TFloatFixPt aWidth, TFloatFixPt aHeight)
+{
+	if (!iInitialized)
+	{
+		TRAPD(err, InitializeL());
+    	if (err)
+    	    {
+		    #ifdef _DEBUG
+            _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in InitializeL()" );
+            RDebug::Print(KErrMsg);
+            #endif //_DEBUG
+    	    }
+	}
+
+	TRAPD(err, iBorderRectangle->SetAttributeFloatL(KAtrX, aX));
+	if (err)
+	    {
+	    #ifdef _DEBUG
+        _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" );
+        RDebug::Print(KErrMsg);
+        #endif //_DEBUG
+	    }
+
+	TRAP(err, iBorderRectangle->SetAttributeFloatL(KAtrY, aY));
+	if (err)
+	    {
+	    #ifdef _DEBUG
+        _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" );
+        RDebug::Print(KErrMsg);
+        #endif //_DEBUG
+	    }
+
+	TRAP(err, iBorderRectangle->SetAttributeFloatL(KAtrWidth, aWidth));
+	if (err)
+	    {
+	    #ifdef _DEBUG
+        _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" );
+        RDebug::Print(KErrMsg);
+        #endif //_DEBUG
+	    }
+
+	TRAP(err, iBorderRectangle->SetAttributeFloatL(KAtrHeight, aHeight));
+	if (err)
+	    {
+	    #ifdef _DEBUG
+        _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" );
+        RDebug::Print(KErrMsg);
+        #endif //_DEBUG
+	    }
+}
+
+// From MXmlElementOpt
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgTextAreaElementImpl::GetAttributeFloat( const TInt aNameId,
+                                             TFloatFixPt& aValue )
+{
+	if (!iInitialized)
+	{
+		TRAPD(err, InitializeL());
+    	if (err)
+    	    {
+		    #ifdef _DEBUG
+            _LIT( KErrMsg, "CSvgTextAreaElementImpl::GetAttributeFloat Error in InitializeL()" );
+            RDebug::Print(KErrMsg);
+            #endif //_DEBUG
+    	    }
+	}
+
+    switch ( aNameId )
+        {
+        case KAtrX:
+        case KAtrRefX:
+        		aValue = X();
+        break;
+        case KAtrY:
+        case KAtrRefY:
+        		aValue = Y();
+        break;
+        case KAtrWidth:
+        		aValue = Width();
+        break;
+        case KAtrHeight:
+        		aValue = Height();
+        break;
+		// added as a part of get and Set api updation
+		case KAtrRx:
+				aValue = Rx();
+		break;
+		case KAtrRy:
+				aValue = Ry();
+		break;
+        default:
+        		return CSvgElementImpl::GetAttributeFloat( aNameId, aValue );
+        }
+    return KErrNone;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgTextAreaElementImpl::SetAttributeFloatL( const TInt aNameId,
+                                              const TFloatFixPt aValue )
+{
+	if (!iInitialized)
+	{
+		InitializeL();
+	}
+
+    switch ( aNameId )
+        {
+        case KAtrX:
+			iBorderRectangle->SetAttributeFloatL(aNameId, aValue);
+			iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2));
+		break;
+        case KAtrY:
+			iBorderRectangle->SetAttributeFloatL(aNameId, aValue);
+			iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2));
+		break;
+		case KAtrRx:
+			iBorderRectangle->SetAttributeFloatL(aNameId, aValue);
+			//iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2));
+		break;
+		case KAtrRy:
+			iBorderRectangle->SetAttributeFloatL(aNameId, aValue);
+			//iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2));
+		break;
+        case KAtrWidth:
+			if(iReqAttrFlag == KAtrSVGRec)
+			{
+				iReqAttrFlag = KAtrHeight;
+			}
+			else
+			{
+				iReqAttrFlag = 0;
+			}
+
+			iBorderRectangle->SetAttributeFloatL(aNameId, aValue);
+			iInnerRectangle->SetAttributeFloatL(aNameId, aValue-TFloatFixPt(4));
+		break;
+
+        case KAtrHeight:
+					if(iReqAttrFlag == KAtrSVGRec)
+						{
+						iReqAttrFlag = KAtrWidth;
+						}
+					else
+						{
+						iReqAttrFlag = 0;
+						}
+					iBorderRectangle->SetAttributeFloatL(aNameId, aValue);
+			iInnerRectangle->SetAttributeFloatL(aNameId, aValue-TFloatFixPt(4));
+			        break;
+        default:
+        return CSvgElementImpl::SetAttributeFloatL( aNameId, aValue );
+        }
+    return KErrNone;
+}
+
+
+// *******************************************************
+// From MXmlElement
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgTextAreaElementImpl::SetAttributeL( const TDesC& aName,
+                                         const TDesC& aValue )
+{
+	if (!iInitialized)
+	{
+		InitializeL();
+	}
+
+		CSvgElementImpl::SetAttributeL(aName,aValue);
+    return KErrNone;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgTextAreaElementImpl::GetAttributeDes( const TInt aNameId, TPtrC16& aValue )
+    {
+    if (!iInitialized)
+	{
+		return KErrNone;
+	}
+
+    switch ( aNameId )
+        {
+        case KAtrCdata:
+        aValue.Set(*iAllText);
+        break;
+        default:
+        return CSvgElementImpl::GetAttributeDes( aNameId, aValue );
+        }
+    return KErrNone;
+    }
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgTextAreaElementImpl::SetAttributeDesL( const TInt aNameId,
+                                            const TDesC& aValue )
+    {
+    switch ( aNameId )
+        {
+        case KAtrCdata:
+        SetTextL( aValue );
+        break;
+
+        default:
+        return CSvgElementImpl::SetAttributeDesL( aNameId, aValue );
+        }
+    return KErrNone;
+    }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::SetEditable( const TDesC& aValue )
+{
+	if (aValue.FindF(_L("simple")) == KErrNotFound && aValue.FindF(_L("true")) == KErrNotFound)
+	{
+		iEditable = EFalse;
+	}
+	else
+	{
+		iEditable = ETrue;
+	}
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::LocalizedArrangeTextL( CGfx2dGc* /* aGc */ )
+    {
+	if (!iInitialized)
+	    {
+		return;
+	    }
+
+	//every time we call arrange text we will clear the previous text elements
+	//very expensive but easiest way to do this
+	if (iTextElementsArray)
+	    {
+		TInt textEleArrayCnt = iTextElementsArray->Count();
+		for (TInt i=0; i < textEleArrayCnt; i++)
+		    {
+			this->RemoveChild( iTextElementsArray->operator[](i) );
+			delete iTextElementsArray->operator[](i);
+		    }
+
+		iTextElementsArray->Reset();
+	    }
+    // If there is some text in the text area, we need to do the following operations
+    //      a. calculate number of lines that can fit in the inner rectangle of textArea 
+    //          i. For this we need to get the dimension of Inner Rectangle
+    //          ii. Then get the font corresponding to the current scale. This is obtained
+    //              by creating a dummy text element and updating its CTM.
+    //
+	if (iAllText && iAllText->Length() > 0)
+	    {
+		TFloatFixPt lInnerRectWidthF, lInnerRectHeightF;
+		iInnerRectangle->GetAttributeFloat( KAtrWidth, lInnerRectWidthF );
+		iInnerRectangle->GetAttributeFloat( KAtrHeight, lInnerRectHeightF );
+        
+        // Create a dummy text element to obtain the font
+      	CSvgTextElementImpl* lTextElement  = 
+      	    (CSvgTextElementImpl*)iOwnerDocument->CreateElementL(KSvgTextElement);
+      	CleanupStack::PushL(lTextElement);
+        lTextElement->SetAttributeDesL(KAtrCdata,iAllText->Des());
+        
+        this->AppendChildL(lTextElement);
+        CleanupStack::Pop(lTextElement);
+        lTextElement->UpdateCTM();
+        // Update the text element's font corresponding to the CTM.
+        lTextElement->UpdateCurrentScaledFont();
+
+        TFloatFixPt lScale = GetCurrentScale();
+        
+        //Taken the widest charactor to check against the dimensions of the text area.
+        //There is no point in going futher, If the area of text area elelment 
+        //is not big enough to fit the single char,
+        TChar ch('W');
+        if ( lScale == TFloatFixPt( 0 ) ||
+             ((TReal32)( lInnerRectWidthF * lScale)) < lTextElement->Font()->CharWidthInPixels( ch ) ||
+             ((TReal32)( lInnerRectHeightF * lScale)) < lTextElement->Font()->FontMaxHeight())
+            {
+            // Scale = 0 , means no drawing will take place.
+            // Cleanup the text element
+    		this->RemoveChild(lTextElement);
+			delete lTextElement;
+			lTextElement = NULL;
+            return;
+            }
+        
+        // Store the current font's ascent and descent
+        TInt lTextAscent = lTextElement->Font()->FontMaxAscent();
+        TInt lTextDescent = lTextElement->Font()->FontMaxDescent();
+
+	TReal32 lTextHeight = lTextAscent + lTextDescent;
+
+        if (lTextHeight == 0)
+	        {
+	    	//no text height so we need to not draw the text
+    		this->RemoveChild(lTextElement);
+			delete lTextElement;
+			lTextElement = NULL;
+	    	return;
+            }
+            
+        // Calculate gap between two consecutive lines of text
+        // CFont provides FontLineGap() which is Font Height + Line Gap
+        
+        TInt lLineGap = lTextElement->Font()->FontLineGap();
+        // Number of lines of text
+	    TInt lNumOflines = (TReal32)( lInnerRectHeightF * lScale)/( lLineGap ) ;
+
+        if( lNumOflines < 1)
+            {
+        	//text is taller than the rectangle
+    		this->RemoveChild(lTextElement);
+			delete lTextElement;
+			lTextElement = NULL;
+            return;
+            }
+        // Create a list of line widths and line texts to use with ConvertToVisualAndWrapToArrayL
+        CArrayFixFlat<TInt>* lLineWidthArray = new ( ELeave ) CArrayFixFlat<TInt>( lNumOflines );
+        CleanupStack::PushL(lLineWidthArray);
+        
+        //one px offset is taken on Left & right ends w.r. to inner rect width.
+        lLineWidthArray->AppendL((TInt)( lInnerRectWidthF * lScale ) - 2,lNumOflines);
+
+        CArrayFixFlat< TPtrC >*   lWrappedArray = new ( ELeave ) CArrayFixFlat<TPtrC>( lLineWidthArray->Count() );
+
+        CleanupStack::PushL(lWrappedArray);
+        
+        //ConvertToVisualAndWrapToArrayL requires KAknBidiExtraSpacePerLine. 
+        //Refer the help of AknBidiTextUtils::ConvertToVisualAndWrapToArrayL
+        HBufC *lBuf = HBufC::NewLC(iAllText->Length() + (lNumOflines) * KAknBidiExtraSpacePerLine);
+
+        TPtr buf = lBuf->Des();
+        buf.Copy(iAllText->Des());
+        // Below API fills the lWrappedArray with the lines of text. If no space 
+        // is available in textArea, then trailing ellipsis(...) will be displayed.
+        AknBidiTextUtils::ConvertToVisualAndWrapToArrayL(buf, *lLineWidthArray, 
+            *lTextElement->iBitmapFont, *lWrappedArray, ETrue);
+        
+        // Dummy text element is no longer required.
+		this->RemoveChild(lTextElement);
+		delete lTextElement;
+		lTextElement = NULL;
+		
+		// Calculating the y offset for first line of text. 
+		// Text is positioned wrt font baseline, hence the position =
+		//      Inner Rectangle 's Y Coordinate + Unscaled Font Ascent
+		// The scaling will be taken care of by UpdateCTM on the text elements.
+        TInt lTextCurrentY = TReal32(iInnerRectangle->Y()) + (lTextAscent / (TReal32)lScale );
+		TInt lWrappedArrayCnt = lWrappedArray->Count();
+		
+		// lWrappedArrayCnt is guaranteed to be less than lNumOfLines.
+		// This loop creates Text  elements as many as elements in lWrapppedArray.
+        // These elements are appended as child to the text area.
+		for( TInt i=0; i < lWrappedArrayCnt ; i++)
+		    {
+		    lTextElement = (CSvgTextElementImpl*)iOwnerDocument->CreateElementL(KSvgTextElement);
+            CleanupStack::PushL( lTextElement );
+            iTextElementsArray->Append(lTextElement);
+		    
+		    TPtrC lineText = lWrappedArray->At(i);
+		    lTextElement->SetAttributeDesL(KAtrCdata,lineText);
+		    
+		    //Text positioned from the inner rectangle's X- coordinate + 1 pixel gap 
+	    	lTextElement->SetAttributeFloatL(KAtrX, TFloatFixPt(iInnerRectangle->X() + TFloatFixPt(1)));
+
+            //need to set the next text element up to go down the height here too...
+            lTextElement->SetAttributeFloatL(KAtrY, TFloatFixPt(lTextCurrentY));
+
+			lTextElement->SetAttributeFloatL(KAtrWidth, TFloatFixPt(iInnerRectangle->Width() - TFloatFixPt(2)));
+			lTextElement->SetAttributeFloatL(KAtrHeight, lTextHeight);
+
+            this->AppendChildL(lTextElement);
+
+            lTextElement->UpdateCTM();
+            lTextElement->UpdateCurrentScaledFont();
+
+            //The subsequent position calculated as lTextHeight( Ascent + descent ) / unscaled line gap
+            lTextCurrentY +=  (TInt)(( lLineGap )/(TReal32)lScale);
+
+            CleanupStack::Pop( lTextElement );
+		    }
+
+		 //delete lBuf;
+		 CleanupStack::PopAndDestroy(lBuf);
+		 CleanupStack::Pop(lWrappedArray);
+		 delete lWrappedArray;
+		 CleanupStack::Pop(lLineWidthArray);
+		 delete lLineWidthArray;
+
+	}
+}
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgTextAreaElementImpl::GetLength()
+    {
+        return iAllText->Length();
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::GetText( TDes& allText )
+    {
+    if ( iAllText )
+        {
+    	if ( allText.MaxLength() < iAllText->Length() )
+    	    {
+    	    allText = iAllText->Left( allText.MaxLength() );
+    	    }
+    	    else
+    	        {
+    	        allText = *iAllText;
+    	        }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::SetTextL( const TDesC& aText )
+    {
+
+   	_LIT( KPreserve, "preserve" );
+    _LIT( KDefault, "default");
+    if ( iAllText )
+        {
+        delete iAllText;
+        iAllText = NULL;
+        }
+
+    iAllText = aText.AllocL();
+    TPtr textDes = iAllText->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.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);
+               	}
+            }
+        }
+         
+        iNeedTextRearrange = ETrue;
+
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::InitializeL()
+{
+	if (!iBorderRectangle && !iInnerRectangle)
+	{
+		iBorderRectangle = CSvgRectElementImpl::NewL(KSvgRectElement, (CSvgDocumentImpl*)iOwnerDocument);
+		this->AppendChildL(iBorderRectangle);
+		iInnerRectangle = CSvgRectElementImpl::NewL(KSvgRectElement, (CSvgDocumentImpl*)iOwnerDocument);
+		this->AppendChildL(iInnerRectangle);
+
+		iInnerRectangle->SetAttributeFloatL(KAtrRx, 2);
+		iInnerRectangle->SetAttributeFloatL(KAtrRy, 2);
+		iInnerRectangle->SetPropertyL(KCSS_ATTR_FILL, _L("none"));
+		iInnerRectangle->SetPropertyL(KCSS_ATTR_STROKEWIDTH, _L(".02"));
+		iInnerRectangle->SetPropertyL(KCSS_ATTR_STROKE, _L("black"));
+
+		iBorderRectangle->SetAttributeFloatL(KAtrRx, 2);
+		iBorderRectangle->SetAttributeFloatL(KAtrRy, 2);
+		iBorderRectangle->SetPropertyL(KCSS_ATTR_FILL, _L("none"));
+		iBorderRectangle->SetPropertyL(KCSS_ATTR_STROKEWIDTH, _L(".1"));
+		iBorderRectangle->SetPropertyL(KCSS_ATTR_STROKE, _L("black"));
+
+		iInitialized = ETrue;
+	}
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::DrawL( CGfx2dGc* aGc, CSvgElementImpl* aElement )
+{
+	if (iBorderRectangle->Width() <= TFloatFixPt(0) || iBorderRectangle->Height() <= TFloatFixPt(0))
+		{
+			return ETrue;
+		}
+
+    TFloatFixPt scale = GetCurrentScale();
+    TFloatFixPt width = iInnerRectangle->Width() * scale;
+    TFloatFixPt height = iInnerRectangle->Height() * scale;
+
+    if ( width != iLastBBox.iWidth || height != iLastBBox.iHeight )
+    {
+        iNeedTextRearrange = ETrue;
+        iLastBBox.iWidth = width;
+        iLastBBox.iHeight = height;
+    }
+
+    DrawTextElements( aGc, aElement );
+
+    return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::DrawTextElements( CGfx2dGc* aGc, CSvgElementImpl* /*aElement*/ )
+{
+	//draw text elements...readjust their positions according the width and height of the inner rectangle...
+    if (iNeedTextRearrange)
+    {
+    	//TRAPD(err, ArrangeTextL(aGc));
+    	TRAPD(err, LocalizedArrangeTextL(aGc));
+    	if (err)
+    	    {
+		    #ifdef _DEBUG
+            _LIT( KErrMsg, "CSvgTextAreaElementImpl::DrawTextElements Error in ArrangeTextL()" );
+            RDebug::Print(KErrMsg);
+            #endif //_DEBUG
+    	    }
+
+    	iNeedTextRearrange = EFalse;
+    }
+
+    //draw text until it reaches the inner border then start a new text element on the next line down
+    /*if (iTextElementsArray)
+    {
+    	 for (int i=0; i < iTextElementsArray->Count(); i++)
+    	{
+			//draw text elements here...
+			TRAPD(err, iTextElementsArray->operator[](i)->DrawL(aGc, aElement));
+        	if (err)
+        	    {
+    		    #ifdef _DEBUG
+                _LIT( KErrMsg, "CSvgTextAreaElementImpl::DrawTextElements Error in DrawL()" );
+                RDebug::Print(KErrMsg);
+                #endif //_DEBUG
+        	    }
+
+  		}
+    }*/
+
+  	return ETrue;
+}
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::ConstructL(  const TUint8 aElemID )
+{
+		CSvgElementImpl::InitializeL( aElemID );
+
+		iSvgStyleProperties = new(ELeave) RPointerArray<CCssValue>(KCSS_MAX_ATTR );
+
+    	User::LeaveIfError( iSvgStyleProperties->Append( NULL ) );
+    	iSvgStyleProperties->Remove( 0 );
+
+		iTextElementsArray = new (ELeave)RPointerArray<CSvgTextElementImpl> (1);
+		iTextElementsArray->Reset();
+
+  		iSvgTransformable = CSvgTransformableImpl::NewL();
+
+		iReqAttrFlag=KSVG_RECT_ELEMFLAG;
+
+		iBorderRectangle = NULL;
+		iInnerRectangle = NULL;
+
+		iNeedTextRearrange = ETrue;
+		iInitialized = EFalse;
+
+		iAllText = HBufC::NewL( 2 );
+
+  		iEditable = EFalse;
+
+  	// Add this as internal event receiver
+  	//((CSvgDocumentImpl*)iOwnerDocument)->AddToEventReceiverListL( this, KSvgEventMaskExternalUI);
+
+	((CSvgDocumentImpl*)OwnerDocument())->AddInternalMouseListener( this );
+
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+
+CSvgTextAreaElementImpl::CSvgTextAreaElementImpl( CSvgDocumentImpl* aDoc )
+{
+		SetOwnerDocument(aDoc);
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::GetBBox( TGfxRectangle2D& aBbox )
+{
+	if (!iInitialized)
+	{
+		TGfxRectangle2D myRect(0,0,0,0);
+		aBbox = myRect;
+		return;
+	}
+
+    iBorderRectangle->GetBBox( aBbox );
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::GetUnscaledBBox( TGfxRectangle2D& aBbox )
+{
+	if (!iInitialized)
+	{
+		TGfxRectangle2D myRect(0,0,0,0);
+		aBbox = myRect;
+		return;
+	}
+
+    iBorderRectangle->GetUnscaledBBox(aBbox);
+}
+
+// ---------------------------------------------------------------------------
+// perform a deep clone of this object
+// ---------------------------------------------------------------------------
+MXmlElement* CSvgTextAreaElementImpl::CloneL(MXmlElement* aParentElement)
+{
+    // create new text area
+	CSvgTextAreaElementImpl* newElement = CSvgTextAreaElementImpl::NewL(  this->ElemID(), ((CSvgDocumentImpl*)iOwnerDocument) );
+
+	newElement->iParentNode = aParentElement;
+    // copy everything over
+    this->CopyL(newElement);
+
+    return newElement;
+}
+
+// ---------------------------------------------------------------------------
+// perform a deep copy of this object
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::CopyL( CSvgTextAreaElementImpl* aDestElement )
+{
+    // copy stuff from superclass
+    this->CSvgElementImpl::CopyL(aDestElement);
+
+    // copy iRectangle items special to circle
+    aDestElement->iBorderRectangle = (CSvgRectElementImpl*)iBorderRectangle->CloneL((MXmlElement*)iBorderRectangle);
+    aDestElement->iInnerRectangle = (CSvgRectElementImpl*)iInnerRectangle->CloneL((MXmlElement*)iInnerRectangle);
+
+    if (iTextElementsArray)
+    {
+    	TInt textEleArrayCnt = iTextElementsArray->Count();
+   	 	for (int i=0; i < textEleArrayCnt; i++)
+    	{
+    		aDestElement->iTextElementsArray->Append((CSvgTextElementImpl*)iTextElementsArray->operator[](i)->CloneL((MXmlElement*)iTextElementsArray->operator[](i)));
+    	}
+    }
+
+    // copy the reference to idoc (CSvgDocumentImpl)
+    aDestElement->iOwnerDocument = this->iOwnerDocument;
+}
+
+/*** FROM MSvgMouseListener ***/
+// ---------------------------------------------------------------------------
+// mouse entered
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::MouseEntered( RPointerArray<CSvgElementImpl>& aElements,
+                                    TInt /*aX*/, TInt /*aY*/ )
+{
+	CSvgEngineImpl* engine  = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine();
+
+	TInt eleCnt = aElements.Count();
+	for (TInt i = 0; i < eleCnt; i++ )
+	{
+		if ( aElements[i] == this )
+		{
+			engine->NotifyTextAreaEntered(this);
+			return ETrue;
+		}
+    }
+
+	return EFalse;
+}
+
+// ---------------------------------------------------------------------------
+// Notified when the mouse pointer exits a visible svg element.
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::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->NotifyTextAreaExited(this);
+			return ETrue;
+		}
+    }
+
+	return EFalse;
+}
+
+// ---------------------------------------------------------------------------
+// Notified when the mouse pointer is pressed down on visible svg element.
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::MouseMoved( RPointerArray<CSvgElementImpl>& /*aElements*/,
+                                    TInt /*aX*/, TInt /*aY*/ )
+{
+    return EFalse;
+}
+// ---------------------------------------------------------------------------
+// Notified when the mouse pointer is pressed down on visible svg element.
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::MousePressed( RPointerArray<CSvgElementImpl>& /*aElements*/,
+                                    TInt /*aX*/, TInt /*aY*/ )
+{
+	return EFalse;
+}
+
+// ---------------------------------------------------------------------------
+// Notified when the mouse pointer is released on on visible svg element.
+// ---------------------------------------------------------------------------
+TBool CSvgTextAreaElementImpl::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->NotifyTextAreaActivated(this);
+			return ETrue;
+		}
+    }
+
+    return EFalse;
+}
+
+// ---------------------------------------------------------------------------
+// void CSvgTextAreaElementImpl::Print()
+// ---------------------------------------------------------------------------
+void CSvgTextAreaElementImpl::Print( TBool aIsEncodeOn )
+{
+	if (!aIsEncodeOn)
+	{
+		#ifdef _DEBUG
+		RDebug::Printf("<textarea x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" editable=\"%d\" >hmm</textarea>", (int)X(), (int)Y(), (int)Width(), (int)Height(), (int)iEditable/*, iAllText*/);
+		#endif
+	}
+}