--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/svgtopt/SVG/SVGImpl/src/SVGUseElementImpl.cpp Thu Jan 07 16:19:02 2010 +0200
@@ -0,0 +1,673 @@
+/*
+* 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 "SVGUseElementImpl.h"
+#include "SVGElementImpl.h"
+#include "SVGDocumentImpl.h"
+
+#include "GfxAffineTransform.h"
+
+#include "SVGImageElementImpl.h"
+
+_LIT( XLINKHREF, "xlink:href" );
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+
+CSvgUseElementImpl* CSvgUseElementImpl::NewL( const TUint8 aElemID,
+ CSvgDocumentImpl* aDoc )
+ {
+ CSvgUseElementImpl* self = new ( ELeave ) CSvgUseElementImpl( aDoc );
+ CleanupStack::PushL( self );
+ self->ConstructL( aElemID );
+
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+
+CSvgUseElementImpl* CSvgUseElementImpl::NewLC( const TUint8 aElemID,
+ CSvgDocumentImpl* aDoc )
+
+ {
+ CSvgUseElementImpl* self = new ( ELeave ) CSvgUseElementImpl( aDoc );
+ CleanupStack::PushL( self );
+ self->ConstructL( aElemID );
+
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgUseElementImpl::ConstructL( const TUint8 aElemID)
+ {
+ CSvgElementImpl::InitializeL( aElemID );
+
+ iSvgStyleProperties = new(ELeave) RPointerArray<CCssValue>(KCSS_MAX_ATTR);
+ User::LeaveIfError( iSvgStyleProperties->Append( NULL ) );
+ iSvgStyleProperties->Remove( 0 );
+ iSvgTransformable = CSvgTransformableImpl::NewL();
+ iSvgUriReferenceImpl = CSvgUriReferenceImpl::NewL();
+
+ #ifdef SVG_FLOAT_BUILD
+ iX = 0 ;
+ iY = 0 ;
+ #else
+ iX.operator = ( 0 );
+ iY.operator = ( 0 );
+ #endif
+ //iXSet = EFalse;
+ //iYSet = EFalse;
+
+ iReqAttrFlag = KAtrXlinkhref;
+ }
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+CSvgUseElementImpl::~CSvgUseElementImpl()
+ {
+
+ if ( iSvgUriReferenceImpl )
+ {
+ delete iSvgUriReferenceImpl;
+ iSvgUriReferenceImpl = NULL;
+ }
+
+ if ( iSvgStyleProperties )
+ {
+ iSvgStyleProperties->Close();
+ delete iSvgStyleProperties;
+ iSvgStyleProperties = NULL;
+ }
+ if ( iUseHRef )
+ {
+ delete iUseHRef;
+ iUseHRef = NULL;
+ }
+ }
+
+// *******************************************************
+// From SVG DOM
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgUseElementImpl::X()
+ {
+ return iX;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgUseElementImpl::Y()
+ {
+ return iY;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgUseElementImpl::Width()
+ {
+ return iWidth;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TFloatFixPt CSvgUseElementImpl::Height()
+ {
+ return iHeight;
+ }
+
+// *******************************************************
+// SVG Implementation
+
+
+// *******************************************************
+// From MXmlElement
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgUseElementImpl::SetAttributeL( const TDesC& aName,
+ const TDesC& aValue )
+ {
+
+ CSvgElementImpl::SetAttributeL(aName,aValue);
+ // Get the path from the xlink
+ _LIT( KXLink, "xlink:href" );
+ if ( aName == KXLink )
+ {
+ iReqAttrFlag = 0;
+
+ // STEP 1 - Get the reference element
+ // If the first char is '#' then remove it
+ // This is possible if coming from cXML parser and not CVG Decoder
+
+ TInt pos1 = aValue.Locate('/');
+
+ if ( pos1 != KErrNotFound)
+ {
+ if (iOwnerDocument)
+ {
+ _LIT( KMsg, "Non-local valid URI in <use> element" );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetIsWarning( ETrue );
+ }
+ }
+
+ TInt pos = aValue.Locate( '#' );
+ if ( pos != KErrNotFound && pos == 0 )
+ {
+ TPtrC ptr( &aValue[1], aValue.Length() - 1);
+
+ // Maintain one more class level member for JSR
+ // This member will contain the value starting with '#'
+ if ( iUseHRef )
+ {
+ delete iUseHRef;
+ iUseHRef = NULL;
+ }
+
+ iUseHRef = aValue.AllocL();
+
+ if ( this->SetXlinkAttributeL( aName, ptr ) )
+ {
+ ireferenceEl = NULL;
+ if ( iOwnerDocument )
+ {
+ ireferenceEl = (CSvgElementImpl*)((CSvgDocumentImpl*)iOwnerDocument)->GetElementById( ptr );
+
+ if ( ireferenceEl && ireferenceEl->ElemID() == KSvgUseElement)
+ {
+ ((CSvgUseElementImpl*)ireferenceEl)->iUseElementThatUsesThisUse = this;
+
+ if ( ((CSvgUseElementImpl*)ireferenceEl)->iUseElementThatUsesThisUse == iUseElementThatUsesThisUse )
+ {
+ //then there are use elements in recursion
+ // Set error in document
+ _LIT( KMsg, "URI in <use> causes recursion loop with another <use>: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetIsWarning( EFalse );
+
+ //get rid of the loop by removing this one
+ ireferenceEl = NULL;
+ }
+ }
+
+
+ }
+ if(ireferenceEl == NULL)
+ {
+ // Set error in document
+ if ( iOwnerDocument && ((CSvgDocumentImpl*)iOwnerDocument)->iFinishedParsing )
+ {
+ _LIT( KMsg, "Invalid URI in <use> element: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ }
+ return KErrReferencedElementNotFound; // failure in finding the referenced element
+ }
+ }
+ }
+ else if ( pos > 0 && iOwnerDocument && ((CSvgDocumentImpl*)iOwnerDocument)->iFinishedParsing )
+ {
+ // Set error in document
+ _LIT( KMsg, "Non-local valid URI in <use> element: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ }
+ else if( pos == KErrNotFound )
+ {
+
+ // Maintain one more class level member for JSR
+ // This member will contain the value starting with '#'
+ if ( iUseHRef )
+ {
+ delete iUseHRef;
+ iUseHRef = NULL;
+ }
+
+ iUseHRef = aValue.AllocL();
+ TPtrC ptr( &aValue[0], aValue.Length());
+ this->SetXlinkAttributeL( aName, ptr);
+ }
+ }
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgUseElementImpl::SetAttributeDesL( const TInt aNameId,
+ const TDesC& aValue )
+{
+ switch ( aNameId )
+ {
+ case KAtrXlinkhref:
+ {
+ iReqAttrFlag = 0;
+
+ // STEP 1 - Get the reference element
+ // If the first char is '#' then remove it
+ // This is possible if coming from cXML parser and not CVG Decoder
+ TInt pos1 = aValue.Locate('/');
+
+ if ( pos1 != KErrNotFound)
+ {
+ if (iOwnerDocument)
+ {
+ _LIT( KMsg, "Non-local valid URI in <use> element" );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetIsWarning( ETrue );
+ }
+ }
+
+
+ TInt pos = aValue.Locate( '#' );
+ if ( pos != KErrNotFound && pos == 0 )
+ {
+
+ TPtrC ptr( &aValue[1], aValue.Length() - 1);
+ // Maintain one more class level member for JSR
+ // This member will contain the value starting with '#'
+ if ( iUseHRef )
+ {
+ delete iUseHRef;
+ iUseHRef = NULL;
+ }
+ iUseHRef = aValue.AllocL();
+
+ if ( this->SetXlinkAttributeL( XLINKHREF, ptr ) )
+ {
+ ireferenceEl = NULL;
+ if ( iOwnerDocument )
+ {
+ ireferenceEl = (CSvgElementImpl*)((CSvgDocumentImpl*)iOwnerDocument)->GetElementById( ptr );
+
+ if (ireferenceEl && ireferenceEl->ElemID() == KSvgUseElement)
+ {
+ ((CSvgUseElementImpl*)ireferenceEl)->iUseElementThatUsesThisUse = this;
+
+ if ( ((CSvgUseElementImpl*)ireferenceEl)->iUseElementThatUsesThisUse == iUseElementThatUsesThisUse )
+ {
+ //then there are use elements in recursion
+ _LIT( KMsg, "URI in <use> causes recursion loop with another <use>: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetIsWarning( EFalse );
+
+ //get rid of the loop by removing this one
+ ireferenceEl = NULL;
+ }
+ }
+
+ }
+ if(ireferenceEl == NULL)
+ {
+ // Set error in document
+ if ( iOwnerDocument && ((CSvgDocumentImpl*)iOwnerDocument)->iFinishedParsing)
+ {
+ _LIT( KMsg, "Invalid URI in <use> element: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ }
+ return KErrReferencedElementNotFound; // failure in finding the referenced element
+ }
+ }
+ }
+ else if ( pos > 0 && iOwnerDocument && ((CSvgDocumentImpl*)iOwnerDocument)->iFinishedParsing )
+ {
+ // Set error in document
+ _LIT( KMsg, "Non-local valid URI in <use> element: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, aValue );
+ }
+ else if( pos == KErrNotFound )
+ {
+ // Maintain one more class level member for JSR
+ // This member will contain the value starting with '#'
+ if ( iUseHRef )
+ {
+ delete iUseHRef;
+ iUseHRef = NULL;
+ }
+
+ iUseHRef = aValue.AllocL();
+
+ TPtrC ptr( &aValue[0], aValue.Length());
+ this->SetXlinkAttributeL( XLINKHREF, ptr);
+ }
+ return KErrNone;
+ }
+
+ default:
+ {
+ return CSvgElementImpl::SetAttributeDesL( aNameId, aValue );
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgUseElementImpl::GetAttributeDes( const TInt aNameId, TPtrC16& aValue )
+ {
+
+ if ( aNameId == KAtrXlinkhref )
+ {
+ // iUseHRef contains value starting with '#'
+ if ( iUseHRef )
+ {
+ aValue.Set( *iUseHRef );
+ return KErrNone;
+ }
+
+ if ( iSvgUriReferenceImpl )
+ {
+ aValue.Set( iSvgUriReferenceImpl->Href());
+ return KErrNone;
+ }
+
+ }
+
+ return CSvgElementImpl::GetAttributeDes( aNameId, aValue );
+
+ }
+
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgUseElementImpl::SetAttributeFloatL( const TInt aNameId,
+ const TFloatFixPt aValue )
+ {
+ switch ( aNameId )
+ {
+ case KAtrX:
+ iX = aValue;
+ //iXSet = ETrue;
+ break;
+ case KAtrY:
+
+ iY = aValue;
+ //iYSet = ETrue;
+ break;
+ case KAtrWidth:
+ iWidth = aValue;
+ break;
+
+ case KAtrHeight:
+ iHeight = aValue;
+ break;
+ default:
+ return CSvgElementImpl::SetAttributeFloatL( aNameId, aValue );
+ }
+ return KErrNone;
+ }
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TInt CSvgUseElementImpl::GetAttributeFloat( const TInt aNameId,
+ TFloatFixPt& aValue )
+ {
+ switch ( aNameId )
+ {
+ case KAtrX:
+ aValue = iX ;
+ break;
+ case KAtrY:
+
+ aValue = iY ;
+ break;
+ case KAtrWidth:
+ aValue = iWidth ;
+ break;
+
+ case KAtrHeight:
+ aValue = iHeight ;
+ break;
+ default:
+ return CSvgElementImpl::GetAttributeFloat( aNameId, aValue );
+ }
+ return KErrNone;
+ }
+
+
+// *******************************************************
+// From MXmlElementOpt
+
+// *******************************************************
+// From CSvgElementImpl
+
+// perform a deep clone of this object
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+MXmlElement* CSvgUseElementImpl::CloneL(MXmlElement* aParentElement)
+ {
+
+ CSvgUseElementImpl* newElement = CSvgUseElementImpl::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 CSvgUseElementImpl::CopyL( CSvgUseElementImpl* aDestElement )
+ {
+ if(aDestElement)
+ {
+ // copy stuff from superclass
+ this->CSvgElementImpl::CopyL(aDestElement);
+
+ // copy iRectangle items special to circle
+ aDestElement->iX = this->iX;
+ aDestElement->iY = this->iY;
+ aDestElement->iHeight = this->iHeight;
+ aDestElement->iWidth = this->iWidth;
+
+ aDestElement->ireferenceEl = this->ireferenceEl;
+ aDestElement->iUseElementThatUsesThisUse = this->iUseElementThatUsesThisUse;
+
+ // copy the reference to idoc (CSvgDocumentImpl)
+ aDestElement->iOwnerDocument = this->iOwnerDocument;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+TBool CSvgUseElementImpl::DrawL( CGfx2dGc* /* aGc */,
+ CSvgElementImpl* /* aElement */ )
+ {
+ return ETrue;
+ }
+
+// *******************************************************
+// Private
+
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+CSvgUseElementImpl::CSvgUseElementImpl( CSvgDocumentImpl* aDoc )
+ {
+ SetOwnerDocument(aDoc);
+ }
+
+/*
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgUseElementImpl::DeepClone( MXmlElement* aReferenceEl )
+ {
+ CSvgElementImpl*aNewElement = ( CSvgElementImpl* )
+ aReferenceEl->FirstChild();
+ while ( aNewElement )
+ {
+ DeepClone( aNewElement );
+ aNewElement = ( CSvgElementImpl * ) aNewElement->NextSibling();
+ }
+ }
+*/
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+void CSvgUseElementImpl::SetReferenceElementL()
+ {
+ if( ireferenceEl != NULL )
+ {
+ CSvgElementImpl* theElement = (CSvgElementImpl *)ireferenceEl->CloneL((MXmlElement*)this);
+ CleanupStack::PushL(theElement);
+ this->CXmlElementImpl::AppendChildL(theElement);
+ CleanupStack::Pop();
+
+ //if reference element is a use element check for recursion loop
+ if (ireferenceEl->ElemID() == KSvgUseElement)
+ {
+ ((CSvgUseElementImpl*)ireferenceEl)->iUseElementThatUsesThisUse = this;
+
+ if ( ireferenceEl == iUseElementThatUsesThisUse )
+ {
+ //then there are use elements in recursion
+ _LIT( KMsg, "URI in <use> causes recursion loop with another <use>: " );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetError( KErrNotFound, KMsg, Href() );
+ ((CSvgDocumentImpl*)iOwnerDocument)->SetIsWarning( EFalse );
+
+ //get rid of the loop by removing this one
+ ireferenceEl = NULL;
+ }
+ }
+ }
+ }
+
+
+CSvgElementImpl* CSvgUseElementImpl::GetReferenceElementL()
+{
+ return ireferenceEl;
+}
+
+TInt CSvgUseElementImpl::SetRefElemById(const TDesC& aName)
+ {
+ ireferenceEl = ( CSvgElementImpl * )
+ ((CSvgDocumentImpl*)iOwnerDocument)->GetElementById( aName );
+ iReqAttrFlag = 0;
+
+ return ( ireferenceEl == NULL ) ? KErrNotFound : KErrNone;
+ }
+
+void CSvgUseElementImpl::GetUnscaledBBox( TGfxRectangle2D& aBbox )
+{
+ TGfxRectangle2D lReferenceBbox;
+ if (ireferenceEl != NULL)
+ {
+ ((CSvgElementImpl*)ireferenceEl)->GetUnscaledBBox(lReferenceBbox);
+ }
+
+ // width and height
+ aBbox.iX = lReferenceBbox.iX + X();
+ aBbox.iY = lReferenceBbox.iY + Y();
+ aBbox.iWidth = lReferenceBbox.iWidth;
+ aBbox.iHeight = lReferenceBbox.iHeight;
+}
+
+TBool CSvgUseElementImpl::IsViewable( )
+{
+ if (ireferenceEl)
+ {
+ return ireferenceEl->IsViewable();
+ }
+
+ return EFalse;
+}
+
+void CSvgUseElementImpl::GetBBox( TGfxRectangle2D& aBbox )
+{
+ TGfxRectangle2D lReferenceBbox;
+ if (ireferenceEl)
+ {
+ ((CSvgElementImpl*)ireferenceEl)->GetBBox(lReferenceBbox);
+ }
+
+ // width and height
+ aBbox.iX = lReferenceBbox.iX + X();
+ aBbox.iY = lReferenceBbox.iY + Y();
+ aBbox.iWidth = lReferenceBbox.iWidth;
+ aBbox.iHeight = lReferenceBbox.iHeight;
+
+}
+
+void CSvgUseElementImpl::Print( TBool aIsEncodeOn )
+{
+ if (!aIsEncodeOn)
+ {
+ #ifdef _DEBUG
+ RDebug::Printf("<use x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" xlink:href=\"hmm\">", (int)iX, (int)iY, (int)iWidth, (int)iHeight/*, Href()*/);
+ #endif
+ }
+}
+// new function
+void CSvgUseElementImpl::GetBoundingBox( TGfxRectangle2D& aBbox )
+{
+ TGfxRectangle2D lReferenceBbox;
+ if (ireferenceEl != NULL)
+ {
+ TGfxAffineTransform lTempCTM = ((CSvgElementImpl*)ireferenceEl)->GetCTM();
+ TGfxAffineTransform lElementCTM = ((CSvgElementImpl*)this)->GetCTM();
+ MSvgTransformList* trList;
+ TGfxAffineTransform lElementTransform;
+ ((CSvgElementImpl*)ireferenceEl)->GetTransform( trList);
+ lElementTransform = trList->Consolidate( ((CSvgElementImpl*)ireferenceEl)->IsOverwriteTransforms() );
+ lElementTransform.Concatenate(lElementCTM);
+
+ ((CSvgElementImpl*)ireferenceEl)->SetCTM(lElementTransform);
+ //((CSvgElementImpl*)ireferenceEl)->GetBBox(lReferenceBbox);
+ ((CSvgElementImpl*)ireferenceEl)->GetUnscaledBBox(lReferenceBbox);
+ lReferenceBbox.GetBounds(lElementTransform, lReferenceBbox);
+
+ ((CSvgElementImpl*)ireferenceEl)->SetCTM(lTempCTM);
+ }
+ // width and height
+ aBbox.iX = lReferenceBbox.iX + X();
+ aBbox.iY = lReferenceBbox.iY + Y();
+ aBbox.iWidth = lReferenceBbox.iWidth;
+ aBbox.iHeight = lReferenceBbox.iHeight;
+
+}