svgtopt/SVG/SVGImpl/src/SVGGElementImpl.cpp
changeset 0 d46562c3d99d
equal deleted inserted replaced
-1:000000000000 0:d46562c3d99d
       
     1 /*
       
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  SVG Implementation source file
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #if !defined(__E32BASE_H__)
       
    20 #include <e32base.h>
       
    21 #endif
       
    22 #include "SVGGElementImpl.h"
       
    23 #include "SVGElementImpl.h"
       
    24 #include "SVGDocumentImpl.h"
       
    25 #include "SVGSchemaData.h"
       
    26 
       
    27 #include "GfxAffineTransform.h"
       
    28 
       
    29 #include "SVGUseElementImpl.h"
       
    30 _LIT(DISPLAY, "display");
       
    31 _LIT(NONE, "none");
       
    32 
       
    33 // ---------------------------------------------------------------------------
       
    34 //
       
    35 // ---------------------------------------------------------------------------
       
    36 CSvgGElementImpl* CSvgGElementImpl::NewL(  const TUint8 aElemID,
       
    37                                           CSvgDocumentImpl* aDoc )
       
    38     {
       
    39     CSvgGElementImpl*   self    = new ( ELeave ) CSvgGElementImpl( aDoc );
       
    40     CleanupStack::PushL( self );
       
    41     self->ConstructL(  aElemID );
       
    42     CleanupStack::Pop();
       
    43 
       
    44     return self;
       
    45     }
       
    46 
       
    47 // ---------------------------------------------------------------------------
       
    48 //
       
    49 // ---------------------------------------------------------------------------
       
    50 CSvgGElementImpl* CSvgGElementImpl::NewLC(  const TUint8 aElemID,
       
    51                                            CSvgDocumentImpl* aDoc )
       
    52     {
       
    53     CSvgGElementImpl*   self    = new ( ELeave ) CSvgGElementImpl( aDoc );
       
    54     CleanupStack::PushL( self );
       
    55     self->ConstructL(  aElemID );
       
    56 
       
    57     return self;
       
    58     }
       
    59 
       
    60 
       
    61 
       
    62 
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 // ---------------------------------------------------------------------------
       
    66 CSvgGElementImpl::~CSvgGElementImpl()
       
    67     {
       
    68 	if ( iSvgStyleProperties )
       
    69 		{
       
    70 		iSvgStyleProperties->Close();
       
    71 		delete iSvgStyleProperties;
       
    72 		iSvgStyleProperties = NULL;
       
    73 		}
       
    74 
       
    75     }
       
    76 
       
    77 
       
    78 // Private
       
    79 // ---------------------------------------------------------------------------
       
    80 //
       
    81 // ---------------------------------------------------------------------------
       
    82 
       
    83 void CSvgGElementImpl::ConstructL(  const TUint8 aElemID )
       
    84     {
       
    85     CSvgElementImpl::InitializeL( aElemID );
       
    86 
       
    87 	iSvgStyleProperties = new(ELeave) RPointerArray<CCssValue>(KCSS_MAX_ATTR);
       
    88 	User::LeaveIfError( iSvgStyleProperties->Append( NULL ) );
       
    89 iSvgStyleProperties->Remove( 0 );
       
    90 
       
    91     iSvgTransformable = CSvgTransformableImpl::NewL();
       
    92 
       
    93     if (this->ElemID() >= KSvgAllGElemsSubStartIndex &&
       
    94     	this->ElemID() <= KSvgAllGElemsEndIndex )
       
    95         {
       
    96         // Set display to "none"
       
    97         // Otherwise it will be rendered
       
    98 		SetAttributeL(DISPLAY, NONE);
       
    99         }
       
   100     }
       
   101 
       
   102 
       
   103 
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 // ---------------------------------------------------------------------------
       
   107 
       
   108 CSvgGElementImpl::CSvgGElementImpl( CSvgDocumentImpl* aDoc )
       
   109     {
       
   110 	SetOwnerDocument(aDoc);
       
   111     }
       
   112 
       
   113 
       
   114 // *******************************************************
       
   115 // From MXmlElement
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 //
       
   119 // ---------------------------------------------------------------------------
       
   120 TInt CSvgGElementImpl::SetAttributeL( const TDesC& aName, const TDesC& aValue )
       
   121     {
       
   122 	CSvgElementImpl::SetAttributeL(aName,aValue);
       
   123     return KErrNone;
       
   124     }
       
   125 
       
   126 
       
   127 // From MXmlElementOpt
       
   128 
       
   129 // ---------------------------------------------------------------------------
       
   130 //
       
   131 // ---------------------------------------------------------------------------
       
   132 TInt CSvgGElementImpl::GetAttributeFloat( const TInt aNameId, TFloatFixPt& aValue )
       
   133     {
       
   134     switch ( aNameId )
       
   135         {
       
   136         case KAtrRefX:
       
   137             {
       
   138             TFloatFixPt          xmin( KMAXFLOATFIX ), x; // 0x7fff is the maximum integer in TFixPt
       
   139             CSvgElementImpl*lNewElement = ( CSvgElementImpl* ) FirstChild();
       
   140             while ( lNewElement != NULL )
       
   141                 {
       
   142                 lNewElement->GetAttributeFloat( KAtrRefX, x );
       
   143                 if ( x < xmin )
       
   144                     xmin = x;
       
   145                 lNewElement = ( CSvgElementImpl * )
       
   146                               lNewElement->NextSibling();
       
   147                 }
       
   148             aValue = xmin;
       
   149             }
       
   150         break;
       
   151         case KAtrRefY:
       
   152             {
       
   153             TFloatFixPt          ymin( KMAXFLOATFIX ), y; // 0x7fff is the maximum integer in TFixPt
       
   154             CSvgElementImpl*lNewElement = ( CSvgElementImpl* ) FirstChild();
       
   155             while ( lNewElement != NULL )
       
   156                 {
       
   157                 lNewElement->GetAttributeFloat( KAtrRefY, y );
       
   158                 if ( y < ymin )
       
   159                     ymin = y;
       
   160                 lNewElement = ( CSvgElementImpl * )
       
   161                               lNewElement->NextSibling();
       
   162                 }
       
   163             aValue = ymin;
       
   164             }
       
   165         break;
       
   166         default:
       
   167         return CSvgElementImpl::GetAttributeFloat( aNameId, aValue );
       
   168         }
       
   169     return KErrNone;
       
   170     }
       
   171 
       
   172 // *******************************************************
       
   173 // From CSvgElementImpl
       
   174 
       
   175 // ---------------------------------------------------------------------------
       
   176 //
       
   177 // ---------------------------------------------------------------------------
       
   178 TBool CSvgGElementImpl::DrawL( CGfx2dGc* /* aGc */,
       
   179                                CSvgElementImpl* /* aElement */ )
       
   180     {
       
   181 
       
   182 	if (	this->ElemID() >= KSvgAllGElemsStartIndex &&
       
   183 			this->ElemID() <= KSvgAllGElemsEndIndex
       
   184 	   )
       
   185 
       
   186 
       
   187         {
       
   188         return EFalse;
       
   189         }
       
   190     else
       
   191         {
       
   192         return ETrue;
       
   193         }
       
   194 
       
   195     }
       
   196 
       
   197 
       
   198 // *******************************************************
       
   199 // Utilities
       
   200 // Get group bounding box
       
   201 // ---------------------------------------------------------------------------
       
   202 //
       
   203 // ---------------------------------------------------------------------------
       
   204 void CSvgGElementImpl::GetGroupBounding( TGfxRectangle2D& aBbox,
       
   205                                          CSvgElementImpl* aStartElement )
       
   206     {
       
   207     TFloatFixPt  xMin( KMAXFLOATFIX ), yMin( KMAXFLOATFIX ), xMax( KMINFLOATFIX ), yMax( KMINFLOATFIX );
       
   208 
       
   209     GetGroupBoundingInternal( xMin, yMin, xMax, yMax, aStartElement );
       
   210     aBbox.iX = xMin;
       
   211     aBbox.iY = yMin;
       
   212     aBbox.iWidth = xMax - xMin;
       
   213     aBbox.iHeight = yMax - yMin;
       
   214     }
       
   215 
       
   216 // ---------------------------------------------------------------------------
       
   217 //
       
   218 // ---------------------------------------------------------------------------
       
   219 void CSvgGElementImpl::GetGroupBoundingInternal( TFloatFixPt& aXmin,
       
   220                                                  TFloatFixPt& aYmin,
       
   221                                                  TFloatFixPt& aXmax,
       
   222                                                  TFloatFixPt& aYmax,
       
   223                                                  CSvgElementImpl* aStartElement )
       
   224     {
       
   225    	TInt    position= aStartElement->ElemID();
       
   226 	if(  position > KSvgNoBoundBoxElemsEndIndex )
       
   227 
       
   228         {
       
   229         TFloatFixPt          zero    ( 0 );
       
   230         TGfxRectangle2D bbox;
       
   231         TInt32 displayValue;
       
   232         aStartElement->GetBBox( bbox );
       
   233 
       
   234         TRAP_IGNORE( aStartElement->GetAttributeIntL( KCSS_ATTR_DISPLAY, displayValue ) );
       
   235 
       
   236     	// Ignore area-less elements and dispay="none" elements
       
   237         if ( (bbox.iWidth > zero || bbox.iHeight > zero) && displayValue !=  KDisplayEnumNone)
       
   238         {
       
   239             if ( bbox.iX < aXmin )
       
   240                 aXmin = bbox.iX;
       
   241             if ( bbox.iY < aYmin )
       
   242                 aYmin = bbox.iY;
       
   243             if ( bbox.iX + bbox.iWidth > aXmax )
       
   244                 aXmax = bbox.iX + bbox.iWidth;
       
   245             if ( bbox.iY + bbox.iHeight > aYmax )
       
   246                 aYmax = bbox.iY + bbox.iHeight;
       
   247             }
       
   248         }
       
   249 
       
   250     CSvgElementImpl*element = ( CSvgElementImpl* )
       
   251                               aStartElement->FirstChild();
       
   252     while ( element != NULL )
       
   253         {
       
   254         GetGroupBoundingInternal( aXmin, aYmin, aXmax, aYmax, element );
       
   255         element = ( CSvgElementImpl * ) element->NextSibling();
       
   256         }
       
   257     }
       
   258 
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 // ---------------------------------------------------------------------------
       
   262 void CSvgGElementImpl::GetGroupBoundingUnscaled( TGfxRectangle2D& aBbox,
       
   263                                                  CSvgElementImpl* aStartElement )
       
   264     {
       
   265     TFloatFixPt  xMin( KMAXFLOATFIX ), yMin( KMAXFLOATFIX ), xMax( KMINFLOATFIX ), yMax( KMINFLOATFIX );
       
   266 
       
   267     GetGroupBoundingInternalUnscaled( xMin, yMin, xMax, yMax, aStartElement );
       
   268     aBbox.iX = xMin;
       
   269     aBbox.iY = yMin;
       
   270     aBbox.iWidth = xMax - xMin;
       
   271     aBbox.iHeight = yMax - yMin;
       
   272     }
       
   273 
       
   274 // ---------------------------------------------------------------------------
       
   275 //
       
   276 // ---------------------------------------------------------------------------
       
   277 void CSvgGElementImpl::GetGroupBoundingInternalUnscaled( TFloatFixPt& aXmin,
       
   278                                                          TFloatFixPt& aYmin,
       
   279                                                          TFloatFixPt& aXmax,
       
   280                                                          TFloatFixPt& aYmax,
       
   281                                                          CSvgElementImpl* aStartElement )
       
   282 {
       
   283     TInt    position= aStartElement->ElemID();
       
   284     if(  position > KSvgNoBoundBoxElemsEndIndex )
       
   285 
       
   286         {
       
   287         TFloatFixPt          zero    ( 0 );
       
   288         TGfxRectangle2D bbox;
       
   289         TInt32 displayValue;
       
   290 
       
   291         //solving the case where a <g><rect transform="translate(10,10)"></g>
       
   292         //the rect elements transform must be reflected on the G
       
   293         //but we dont want the scaled bbox of the rect with the entire CTM scaling
       
   294 
       
   295         if( aStartElement->IsTransformable() )
       
   296             {
       
   297             MSvgTransformList*  trList;
       
   298 
       
   299         	TGfxAffineTransform lElementTransform;
       
   300 
       
   301             aStartElement->GetTransform( trList );
       
   302             lElementTransform = trList->Consolidate( aStartElement->IsOverwriteTransforms() );
       
   303 
       
   304             TGfxAffineTransform lTempCTM = aStartElement->GetCTM();
       
   305 
       
   306             //use only the transform on the child element and not the entire CTM
       
   307             aStartElement->SetCTM( lElementTransform );
       
   308 			if (KSvgUseElement == (( CSvgElementImpl* )aStartElement)->ElemID())
       
   309             {
       
   310               ((CSvgUseElementImpl*)aStartElement)->GetBoundingBox( bbox);
       
   311             }
       
   312             else
       
   313             	aStartElement->GetBBox( bbox );
       
   314 
       
   315             //set the original entire CTM back on to the element
       
   316             aStartElement->SetCTM(lTempCTM);
       
   317 
       
   318             }
       
   319 
       
   320         TRAP_IGNORE( aStartElement->GetAttributeIntL( KCSS_ATTR_DISPLAY, displayValue ) );
       
   321 		
       
   322 		//TBool iDisplayNoneFlag  = aStartElement->IsInherited(KCSS_ATTR_DISPLAY);
       
   323 		// if the display attribute is inherited, consider it for bounding box calculation
       
   324         if ( (bbox.iWidth > zero || bbox.iHeight > zero) && ( displayValue !=  KDisplayEnumNone ) )    // Ignore area-less elements
       
   325         {
       
   326             if ( bbox.iX < aXmin )
       
   327                 aXmin = bbox.iX;
       
   328             if ( bbox.iY < aYmin )
       
   329                 aYmin = bbox.iY;
       
   330             if ( bbox.iX + bbox.iWidth > aXmax )
       
   331                 aXmax = bbox.iX + bbox.iWidth;
       
   332             if ( bbox.iY + bbox.iHeight > aYmax )
       
   333                 aYmax = bbox.iY + bbox.iHeight;
       
   334             }
       
   335         }
       
   336       if (KSvgUseElement == (( CSvgElementImpl* )aStartElement)->ElemID()) 
       
   337       return;
       
   338 
       
   339     CSvgElementImpl*element = ( CSvgElementImpl* )
       
   340                               aStartElement->FirstChild();
       
   341     TFloatFixPt tempXMin ;
       
   342     TFloatFixPt tempYMin ;
       
   343     TFloatFixPt tempXMax ;
       
   344     TFloatFixPt tempYMax ;
       
   345     
       
   346     while ( element != NULL )
       
   347     {
       
   348                     
       
   349         //Apply group level transformation if the group is not the original element. 
       
   350         if( KSvgGElement == element->ElemID() )
       
   351         {
       
   352  			TFloatFixPt  xMin( KMAXFLOATFIX ), yMin( KMAXFLOATFIX ), xMax( KMINFLOATFIX ), yMax( KMINFLOATFIX );
       
   353         	
       
   354         	tempXMin = KMAXFLOATFIX ;
       
   355         	tempYMin = KMAXFLOATFIX ;
       
   356         	tempXMax = KMINFLOATFIX ;
       
   357         	tempYMax = KMINFLOATFIX ;
       
   358         	
       
   359         	GetGroupBoundingInternalUnscaled( tempXMin, tempYMin, tempXMax, tempYMax, element );	
       
   360            	if((tempXMax > tempXMin)&&(tempYMax > tempYMin)) 
       
   361            	    {
       
   362            	    TGfxRectangle2D rect(tempXMin, tempYMin, tempXMax - tempXMin, tempYMax - tempYMin);
       
   363         	
       
   364         	    MSvgTransformList*  trList;
       
   365 
       
   366         	    TGfxAffineTransform lElementTransform;
       
   367 
       
   368                 element->GetTransform( trList );
       
   369                 lElementTransform = trList->Consolidate( element->IsOverwriteTransforms() );
       
   370 
       
   371         	    rect.GetBounds(lElementTransform, rect);
       
   372         	
       
   373         	    tempXMin = rect.iX ;
       
   374         	    tempYMin = rect.iY ;
       
   375         	    tempXMax = rect.iX + rect.iWidth ;
       
   376         	    tempYMax = rect.iY + rect.iHeight ; 
       
   377         	
       
   378         	    if( tempXMin < aXmin )
       
   379         		    aXmin = tempXMin ;
       
   380         	    if( tempYMin < aYmin )
       
   381         		    aYmin = tempYMin ;
       
   382         	    if( tempXMax > aXmax )
       
   383         		    aXmax = tempXMax ;
       
   384         	    if( tempYMax > aYmax )
       
   385         		    aYmax = tempYMax ;
       
   386            	    }
       
   387         }
       
   388         else
       
   389         {
       
   390         	GetGroupBoundingInternalUnscaled( aXmin, aYmin, aXmax, aYmax, element );	
       
   391         }
       
   392         
       
   393         element = ( CSvgElementImpl * ) element->NextSibling();
       
   394     }
       
   395         
       
   396 }
       
   397 
       
   398 // perform a deep clone of this object
       
   399 // ---------------------------------------------------------------------------
       
   400 //
       
   401 // ---------------------------------------------------------------------------
       
   402 MXmlElement* CSvgGElementImpl::CloneL(MXmlElement* aParentElement)
       
   403     {
       
   404     // create new g element
       
   405 // ---------------------------------------------------------------------------
       
   406 //
       
   407 // ---------------------------------------------------------------------------
       
   408 	CSvgGElementImpl* newElement = CSvgGElementImpl::NewL(  this->ElemID(), ((CSvgDocumentImpl*)iOwnerDocument) );
       
   409 
       
   410 
       
   411 	CleanupStack::PushL(newElement);
       
   412 	newElement->iParentNode = aParentElement;
       
   413 
       
   414     // copy everything over
       
   415     this->CopyL(newElement);
       
   416 	CleanupStack::Pop();
       
   417     return newElement;
       
   418     }
       
   419 
       
   420 // perform a deep copy of this object
       
   421 // ---------------------------------------------------------------------------
       
   422 //
       
   423 // ---------------------------------------------------------------------------
       
   424 void CSvgGElementImpl::CopyL( CSvgGElementImpl* aDestElement )
       
   425     {
       
   426     if(aDestElement)
       
   427 	    {
       
   428 	    // copy stuff from superclass
       
   429 	    this->CSvgElementImpl::CopyL(aDestElement);
       
   430 	    // copy the reference to idoc (CSvgDocumentImpl)
       
   431 	    aDestElement->iOwnerDocument = this->iOwnerDocument;
       
   432 	    }
       
   433     }
       
   434 
       
   435 // ---------------------------------------------------------------------------
       
   436 //
       
   437 // ---------------------------------------------------------------------------
       
   438 void CSvgGElementImpl::GetBBox( TGfxRectangle2D& aBbox )
       
   439     {
       
   440 
       
   441     // if there are not any children then the bbox should be NULL
       
   442     if (!HasChildNodes())
       
   443     {
       
   444     	return;
       
   445     }
       
   446 
       
   447     CSvgGElementImpl::GetGroupBounding( aBbox, this );
       
   448     }
       
   449 
       
   450 // ---------------------------------------------------------------------------
       
   451 //
       
   452 // ---------------------------------------------------------------------------
       
   453 void CSvgGElementImpl::GetUnscaledBBox( TGfxRectangle2D& aBbox )
       
   454     {
       
   455 
       
   456     // if there are not any children then the bbox should be NULL
       
   457     if (!HasChildNodes())
       
   458     {
       
   459     	return;
       
   460     }
       
   461 
       
   462     CSvgGElementImpl::GetGroupBoundingUnscaled( aBbox, this );
       
   463     }
       
   464 
       
   465 // ---------------------------------------------------------------------------
       
   466 //
       
   467 // ---------------------------------------------------------------------------
       
   468 void CSvgGElementImpl::Print( TBool aIsEncodeOn )
       
   469 {
       
   470 	if (!aIsEncodeOn)
       
   471 	{
       
   472 		#ifdef _DEBUG
       
   473 		RDebug::Printf("<g>");
       
   474 		#endif
       
   475 	}
       
   476 }