svgtopt/SVG/SVGImpl/src/SVGGradientElementImpl.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:46 +0100
branchRCL_3
changeset 18 1902ade171ab
parent 0 d46562c3d99d
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201026 Kit: 201035

/*
* 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
 *
*/


#include "SVGGradientElementImpl.h"
#include "SVGDocumentImpl.h"

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgGradientElementImpl::CSvgGradientElementImpl( CSvgDocumentImpl* aDoc )
	{
	SetOwnerDocument(aDoc);
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgGradientElementImpl::ConstructL(const TUint8 aElemID)
	{
    CSvgElementImpl::InitializeL( aElemID );

    iSvgStyleProperties = new(ELeave) RPointerArray<CCssValue>(KCSS_MAX_ATTR);
    User::LeaveIfError( iSvgStyleProperties->Append( NULL ) );
    iSvgStyleProperties->Remove( 0 );
	iSvgUriReferenceImpl = CSvgUriReferenceImpl::NewL();

    iSvgTransformable = CSvgTransformableImpl::NewL();
    iSvgStopElementArray = new( ELeave ) RPointerArray<CSvgStopElementImpl> ( 1 );

    iStopElementData = new(ELeave) RArray<TSvgStopData> (1);
    iStopElementData->Reset();
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgGradientElementImpl::~CSvgGradientElementImpl()
    {
    if(iSvgStopElementArray)
		{
        iSvgStopElementArray->Close();
        delete iSvgStopElementArray;
		iSvgStopElementArray = NULL;
		}

	if ( iSvgStyleProperties )
		{
		iSvgStyleProperties->Close();
		delete iSvgStyleProperties;
		iSvgStyleProperties = NULL;
		}

	if ( iSvgUriReferenceImpl )
		{
		delete iSvgUriReferenceImpl;
		iSvgUriReferenceImpl = NULL;
		}

	if(iStopElementData)
		{
		iStopElementData->Close();
		delete iStopElementData;
		iStopElementData = NULL;
		}
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
TInt CSvgGradientElementImpl::SetAttributeL( const TDesC& aName,const TDesC& aValue )
	{
	CSvgElementImpl::SetAttributeL(aName,aValue);

    if(aName==_L("gradientUnits")||aName==_L("patternUnits"))
		{
        if(aValue==_L("userSpaceOnUse"))
            iGradientPaint->iGradientUnits = KuserSpaceOnUse;
        else if(aValue==_L("objectBoundingBox"))
            iGradientPaint->iGradientUnits = KobjectBoundingBox;
		}
    else if(aName==_L("spreadMethod"))
		{
        if(aValue==_L("pad"))
			iGradientPaint->iSpreadMethod = KspreadMethodPad;
        else if(aValue==_L("reflect"))
			iGradientPaint->iSpreadMethod = KspreadMethodReflect;
        else if(aValue==_L("repeat"))
			iGradientPaint->iSpreadMethod = KspreadMethodRepeat;
		}
	return KErrNone;
	}

TInt CSvgGradientElementImpl::SetAttributeIntL( const TInt aNameId,
                                        const TInt32 aValue )
{
	if(aNameId == KAtrSpreadMethods)
	{

			iGradientPaint->iSpreadMethod = (TUint16) aValue;
	}

	else if(aNameId == KAtrGradientUnits)
		{
		iGradientPaint->iGradientUnits = (TUint16) aValue;
		}

	else
		CSvgElementImpl::SetAttributeIntL (aNameId,aValue);
	return 0;
}
TInt CSvgGradientElementImpl::GetAttributeIntL( const TInt aNameId, TInt32& aValue )
{
	if(aNameId == KAtrSpreadMethods)
	{
		aValue = iGradientPaint->iSpreadMethod ;
	}

	else if(aNameId == KAtrGradientUnits)
		{
		aValue = iGradientPaint->iGradientUnits ;
		}

	else
		CSvgElementImpl::GetAttributeIntL (aNameId,aValue);
	return 0;
}

// ---------------------------------------------------------------------------
// Adjusts the offset values of all the previously added elements such that
// each gradient offset value is greater than the previous gradient stop's
// offset value.
// ---------------------------------------------------------------------------
void CSvgGradientElementImpl::UpdateOffsetValues(CSvgStopElementImpl *aStopEl)
{
    TInt count = iSvgStopElementArray->Count();
    
    if (count == 1)
        {
    	return;
        }
    
    TFloatFixPt aNewOffset = aStopEl->iOffset;
    
    //Since the Stop Element is already added, The loop runs for "count - 1" times.
    for (TInt i=0; i < count - 1; i++)
	     {
		 TFloatFixPt OldOffset = iSvgStopElementArray->operator[](i)->iOffset;
		
		 if ( OldOffset >= aNewOffset )
		     {
		     //set this latter value up so it has at least as high a value as the
			 //previous stop offsets
			 aStopEl->iOffset = OldOffset;
			 
			 if (aStopEl->iOffset == TFloatFixPt(0))
				 {
				 aStopEl->iOffset += TFloatFixPt(.001f);
				 }
				else
				 {
				 //two stop offsets have the same value now so make the one before ever so slightly less
				 //the latter one will control the "overlap point"
				 OldOffset -= TFloatFixPt(.001f);
				 }
				
			 iSvgStopElementArray->operator[](i)->iOffset = OldOffset;
		     }
	     }
    	
}

// ---------------------------------------------------------------------------
// The function not only adds the element in Stop element array but also
// adjusts the offset values of all the previously added elements such that
// each gradient offset value is greater than the previous gradient stop's
// offset value.
// ---------------------------------------------------------------------------
void CSvgGradientElementImpl::AddStopElementInArray(CSvgStopElementImpl *aStopEl)
	{
	
	TBool lFound = EFalse;
	
	TInt err = iSvgStopElementArray->Find(aStopEl);
	
	if( err != KErrNotFound )
	   {
	   lFound = ETrue;
	   }
		
	if(!lFound)
	   {
	   iSvgStopElementArray->Append(aStopEl);
	   UpdateOffsetValues(aStopEl);
	   }
	
	}

void CSvgGradientElementImpl::SetGradientTransMatrix(SVGReal aMatrix[2][3])
	{
	TGfxAffineTransform tempTransform;
    MSvgTransformList*  trList;
    GetTransform( trList );
    TGfxAffineTransform originalTransform   = trList->GetItem( 0 );
    tempTransform.iM00.iValue = aMatrix[0][0];
    tempTransform.iM01.iValue = aMatrix[0][1];
    tempTransform.iM02.iValue = aMatrix[0][2];
    tempTransform.iM10.iValue = aMatrix[1][0];
    tempTransform.iM11.iValue = aMatrix[1][1];
	tempTransform.iM12.iValue = aMatrix[1][2];

    TUint32 lTransType = KTransformIdentity;

    TFloatFixPt KZero;
    TFloatFixPt KOne( KFloatFixOne );
    if ( tempTransform.iM02 != KZero || tempTransform.iM12 != KZero )
        lTransType |= KTransformTranslate;

    if ( tempTransform.iM00 != KZero || tempTransform.iM11 != KZero )
        lTransType |= KTransformScale;

    if ( tempTransform.iM01 != KZero || tempTransform.iM10 != KZero )
        lTransType |= KTransformShear;

    if ( (int)lTransType == KTransformScale &&
                    tempTransform.iM00 == KOne && tempTransform.iM11 == KOne )
         lTransType = KTransformIdentity;

	tempTransform.iTransType = lTransType;

    originalTransform.Concatenate( tempTransform );
    trList->ReplaceItem( originalTransform, 0 );
	}