svgtopt/gfx2d/src/GfxGeom/GfxFlatteningPathIterator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 07 Jan 2010 16:19:02 +0200
changeset 0 d46562c3d99d
permissions -rw-r--r--
Revision: 200951 Kit: 201001

/*
* Copyright (c) 2002 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:  Graphics Extension Library source file
*
*/


#include "GfxFlatteningPathIterator.h"
#include "GfxShape.h"
#include "GfxAffineTransform.h"


// ---------------------------------------------------------------------------
// Constructors
// ---------------------------------------------------------------------------
CGfxFlatteningPathIterator::CGfxFlatteningPathIterator( TInt32 aLimit )
    : iIdx( 0 ),
      iSegType( EGfxSegClose ),
      iIsDone( EFalse ),
      iLimit( aLimit )
    {
    }


// ---------------------------------------------------------------------------
// Create a new instance.
// ---------------------------------------------------------------------------
// --------------------------------------------------------------------------
//  CGfxFlatteningPathIterator* CGfxFlatteningPathIterator::NewL( MGfxShape* aSrc,
// ---------------------------------------------------------------------------
 CGfxFlatteningPathIterator* CGfxFlatteningPathIterator::NewL( MGfxShape* aSrc,
                                                                       TGfxAffineTransform* aAt,
                                                                       TInt32 aLimit )
    {
    CGfxFlatteningPathIterator* self = new ( ELeave )
                                       CGfxFlatteningPathIterator( aLimit );

    CleanupStack::PushL( self );
    self->ConstructL( aSrc, aAt );
    CleanupStack::Pop();
    return self;
    }

// ---------------------------------------------------------------------------
// Second phase in constructing this object.
// ---------------------------------------------------------------------------
void CGfxFlatteningPathIterator::ConstructL( MGfxShape* aSrc,
                                             TGfxAffineTransform* aAt )
    {
    aSrc->GetPathIteratorL( aAt, iSrc );
    iCoords = new ( ELeave ) RArray<TFloatFixPt>( 10 );
    iCoords->AppendL( NULL );
    iCoords->Remove(0);
    NextL();
    }

// ---------------------------------------------------------------------------
// Destructor.
// ---------------------------------------------------------------------------
// --------------------------------------------------------------------------
//  CGfxFlatteningPathIterator::~CGfxFlatteningPathIterator()
// ---------------------------------------------------------------------------
 CGfxFlatteningPathIterator::~CGfxFlatteningPathIterator()
    {
	if ( iSrc )
		{
		delete iSrc;
		iSrc = NULL;
		}
	if ( iCoords )
		{
		iCoords->Close();
		delete iCoords;
		iCoords = NULL;
		}
    }


// --------------------------------------------------------------------------
//  TGfxSegType CGfxFlatteningPathIterator::CurrentSegment( TFloatFixPt* aCoords )
// ---------------------------------------------------------------------------
 TGfxSegType CGfxFlatteningPathIterator::CurrentSegment( TFloatFixPt* aCoords )
    {
    if ( iCoords->Count() > 0 && iCoords->Count() > iIdx )
        {
        aCoords[0] = ( *iCoords )[iIdx];
        aCoords[1] = ( *iCoords )[iIdx + 1];
        }

    return iSegType;
    }


// --------------------------------------------------------------------------
//  TBool CGfxFlatteningPathIterator::IsDone()
// ---------------------------------------------------------------------------
 TBool CGfxFlatteningPathIterator::IsDone()
    {
    return iIsDone;
    }


// --------------------------------------------------------------------------
//  void CGfxFlatteningPathIterator::Next()
// ---------------------------------------------------------------------------
 void CGfxFlatteningPathIterator::NextL()
    {
    iIdx += 2;

    if ( iCoords->Count() <= 0 || iCoords->Count() <= iIdx )
        {
        TFloatFixPt tmpcoords[6];
        TInt i;

        iCoords->Reset();
        iIdx = 0;
        if ( iSrc->IsDone() )
            {
            iIsDone = ETrue;
            }
        else
            {
            iSegType = iSrc->CurrentSegment( tmpcoords );
            switch ( iSegType )
                {
                case EGfxSegMoveTo:
                    iLastX = tmpcoords[0];
                    iLastY = tmpcoords[1];
                    iCoords->AppendL( iLastX );
                    iCoords->AppendL( iLastY );
                    break;
                case EGfxSegLineTo:
                    iLastX = tmpcoords[0];
                    iLastY = tmpcoords[1];
                    iCoords->AppendL( iLastX );
                    iCoords->AppendL( iLastY );
                    break;
                case EGfxSegQuadTo:
                    iCoords->AppendL( iLastX );
                    iCoords->AppendL( iLastY );
                    iCoords->AppendL( tmpcoords[0] );
                    iCoords->AppendL( tmpcoords[1] );
                    iCoords->AppendL( tmpcoords[2] );
                    iCoords->AppendL( tmpcoords[3] );

                    for ( i = 0; i < iLimit; i++ )
                        CreateSubcurveQuadL( iCoords );
                    //CreateSubcurveQuad(iCoords);
                    //CreateSubcurveQuad(iCoords);
                    //CreateSubcurveQuad(iCoords);

                    iIdx = 2;
                    iLastX = tmpcoords[2];
                    iLastY = tmpcoords[3];
                    iSegType = EGfxSegLineTo;
                    break;
                case EGfxSegCubicTo:
                    iCoords->AppendL( iLastX );
                    iCoords->AppendL( iLastY );
                    iCoords->AppendL( tmpcoords[0] );
                    iCoords->AppendL( tmpcoords[1] );
                    iCoords->AppendL( tmpcoords[2] );
                    iCoords->AppendL( tmpcoords[3] );
                    iCoords->AppendL( tmpcoords[4] );
                    iCoords->AppendL( tmpcoords[5] );

                    for ( i = 0; i < iLimit; i++ )
                        CreateSubcurveCubicL( iCoords );

                    iIdx = 2;
                    iLastX = tmpcoords[4];
                    iLastY = tmpcoords[5];
                    iSegType = EGfxSegLineTo;
                    break;
                case EGfxSegClose:              // (cdm)
                    iLastX = tmpcoords[0];
                    iLastY = tmpcoords[1];
                    iCoords->AppendL( iLastX );
                    iCoords->AppendL( iLastY );
                    break;

                 default:
                    break;
                }
            iSrc->NextL();
            }
        }
    }

// --------------------------------------------------------------------------
//  void CGfxFlatteningPathIterator::SetFlatness( TFloatFixPt& aFlatness )
// ---------------------------------------------------------------------------
 void CGfxFlatteningPathIterator::SetFlatness( TFloatFixPt& aFlatness )
    {
    iFlatness = aFlatness;
    }

// --------------------------------------------------------------------------
//  void CGfxFlatteningPathIterator::SetRecursionLimit( TInt32 aLimit )
// ---------------------------------------------------------------------------
 void CGfxFlatteningPathIterator::SetRecursionLimit( TInt32 aLimit )
    {
    iLimit = aLimit;
    }

// --------------------------------------------------------------------------
//  TFloatFixPt CGfxFlatteningPathIterator::Flatness()
// ---------------------------------------------------------------------------
 TFloatFixPt CGfxFlatteningPathIterator::Flatness()
    {
    return iFlatness;
    }

// --------------------------------------------------------------------------
//  TInt32 CGfxFlatteningPathIterator::RecursionLimit()
// ---------------------------------------------------------------------------
 TInt32 CGfxFlatteningPathIterator::RecursionLimit()
    {
    return iLimit;
    }




// --------------------------------------------------------------------------
// void CGfxFlatteningPathIterator::CreateSubcurveQuad( RArray<TFloatFixPt>* aCtrlPoints )
// ---------------------------------------------------------------------------
void CGfxFlatteningPathIterator::CreateSubcurveQuadL( RArray<TFloatFixPt>* aCtrlPoints )
    {
    TInt32 ix = 0;
    TFloatFixPt x0, y0, xm, ym, x1, y1;
	TInt32 lCount;

    while ( ix + 5 < aCtrlPoints->Count() )
        {
		lCount = ix;
        x0 = ( *aCtrlPoints )[lCount++];
        y0 = ( *aCtrlPoints )[lCount++];
        xm = ( *aCtrlPoints )[lCount++];
        ym = ( *aCtrlPoints )[lCount++];
        x1 = ( *aCtrlPoints )[lCount++];
        y1 = ( *aCtrlPoints )[lCount++];
	#ifdef SVG_FLOAT_BUILD
        x0 = ( x0 + xm ) * .5f;
        y0 = ( y0 + ym ) * .5f;
        x1 = ( x1 + xm ) * .5f;
        y1 = ( y1 + ym ) * .5f;
        xm = ( x0 + x1 ) * .5f;
        ym = ( y0 + y1 ) * .5f;
	#else
        x0 = ( x0 + xm ) >> 1;
        y0 = ( y0 + ym ) >> 1;
        x1 = ( x1 + xm ) >> 1;
        y1 = ( y1 + ym ) >> 1;
        xm = ( x0 + x1 ) >> 1;
        ym = ( y0 + y1 ) >> 1;
	#endif
		lCount=ix + 2;
        ( *aCtrlPoints )[lCount] = xm;
        ( *aCtrlPoints )[lCount + 1] = ym;
        aCtrlPoints->InsertL( TFloatFixPt( x0 ), lCount++);
        aCtrlPoints->InsertL( TFloatFixPt( y0 ), lCount );
        aCtrlPoints->InsertL( TFloatFixPt( x1 ), ix + 6 );
        aCtrlPoints->InsertL( TFloatFixPt( y1 ), ix + 7 );
        ix += 8;
        }
    }

// --------------------------------------------------------------------------
// void CGfxFlatteningPathIterator::CreateSubcurveCubic( RArray<TFloatFixPt>* aCtrlPoints )
// ---------------------------------------------------------------------------
void CGfxFlatteningPathIterator::CreateSubcurveCubicL( RArray<TFloatFixPt>* aCtrlPoints )
    {
    TInt32 ix = 0;
    TFloatFixPt x0, y0, xm, ym, xm1, ym1, xm2, ym2, x1, y1;
	TInt32 lCount;
    while ( ix + 7 < aCtrlPoints->Count() )
        {
		lCount = ix;
        x0 = ( *aCtrlPoints )[lCount++];
        y0 = ( *aCtrlPoints )[lCount++];
        xm1 = ( *aCtrlPoints )[lCount++];
        ym1 = ( *aCtrlPoints )[lCount++];
        xm2 = ( *aCtrlPoints )[lCount++];
        ym2 = ( *aCtrlPoints )[lCount++];
        x1 = ( *aCtrlPoints )[lCount++];
        y1 = ( *aCtrlPoints )[lCount ];

	#ifdef SVG_FLOAT_BUILD
        x0 = ( x0 + xm1 ) * .5f;
        y0 = ( y0 + ym1 ) * .5f;
        x1 = ( x1 + xm2 ) * .5f;
        y1 = ( y1 + ym2 ) * .5f;
        xm = ( xm1 + xm2 ) * .5f;
        ym = ( ym1 + ym2 ) * .5f;
        xm1 = ( x0 + xm ) * .5f;
        ym1 = ( y0 + ym ) * .5f;
        xm2 = ( x1 + xm ) * .5f;
        ym2 = ( y1 + ym ) * .5f;
        xm = ( xm1 + xm2 ) * .5f;
        ym = ( ym1 + ym2 ) * .5f;
	#else
        x0 = ( x0 + xm1 ) >> 1;
        y0 = ( y0 + ym1 ) >> 1;
        x1 = ( x1 + xm2 ) >> 1;
        y1 = ( y1 + ym2 ) >> 1;
        xm = ( xm1 + xm2 ) >> 1;
        ym = ( ym1 + ym2 ) >> 1;
        xm1 = ( x0 + xm ) >> 1;
        ym1 = ( y0 + ym ) >> 1;
        xm2 = ( x1 + xm ) >> 1;
        ym2 = ( y1 + ym ) >> 1;
        xm = ( xm1 + xm2 ) >> 1;
        ym = ( ym1 + ym2 ) >> 1;
	#endif
		lCount=ix + 2;
        ( *aCtrlPoints )[lCount++] = x0;
        ( *aCtrlPoints )[lCount++] = y0;
        ( *aCtrlPoints )[lCount++] = xm1;
        ( *aCtrlPoints )[lCount++] = ym1;

        aCtrlPoints->InsertL( TFloatFixPt( y1 ), lCount);
        aCtrlPoints->InsertL( TFloatFixPt( x1 ), lCount );
        aCtrlPoints->InsertL( TFloatFixPt( ym2 ), lCount );
        aCtrlPoints->InsertL( TFloatFixPt( xm2 ), lCount );
        aCtrlPoints->InsertL( TFloatFixPt( ym ), lCount );
        aCtrlPoints->InsertL( TFloatFixPt( xm ), lCount );
        ix += 12;
        }
    }


// --------------------------------------------------------------------------
//  void CGfxFlatteningPathIterator::PolygonizeL( CGfxEdgeListP* /* aRenderer */, TInt /* aFlatness */ )
// ---------------------------------------------------------------------------
 void CGfxFlatteningPathIterator::PolygonizeL( CGfxEdgeListP* /* aRenderer */, TInt /* aFlatness */ )
{
}