--- /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
+ }
+}