diff -r 000000000000 -r 88edb906c587 svgtopt/SVG/SVGImpl/src/SVGPathDataParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgtopt/SVG/SVGImpl/src/SVGPathDataParser.cpp Wed Nov 03 18:56:10 2010 +0200 @@ -0,0 +1,409 @@ +/* +* 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 "SVGPathDataParser.h" +#include "SVGPointLexer.h" + +#include "GfxFloatFixPt.h" +#include "GfxAffineTransform.h" +#include "GfxFlatteningPathIterator.h" + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void TSvgPathDataParser::ParsePathData( const TDesC& aData, + CGfxGeneralPath* aPath ) + { + + TRAPD( error, ParsePathDataL( aData, aPath ) ); + if ( error != KErrNone ) + { + // error processing + return; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void TSvgPathDataParser::ParsePathDataL( const TDesC& aData, + CGfxGeneralPath* aPath ) + { + TUint8 lPrevCom = '\0'; + TFloatFixPt xy[6]; + TInt32 rslt = ETrue; + TUint8 com; + TUint8 lPrevCom2 = '\0'; + + TSvgPointLexer svgplex( aData ); + + TFloatFixPt KZero; + TFloatFixPt KMinVal = 0.01f; + TFloatFixPt KOne( KFloatFixOne ); + + while ( svgplex.GetCommand ( com ) ) + { + + // Reset for command procesing + if( com == '\0' ) + { + if( lPrevCom == 'z' ||lPrevCom == 'Z' ) + { + aPath->Reset(); + break ; + } + // As per 1.2 spec 8.3.2 The "moveto" commands + // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands, + // the subsequent pairs shall be treated as implicit 'lineto' commands. + + else if( lPrevCom == 'm') + { + com = 'l'; + } + else if( lPrevCom == 'M' ) + { + com = 'L'; + } + else + { + com = lPrevCom; + } + } + else + { + lPrevCom = com; + } + + switch ( com ) + { + case 'M': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (2) ); + if (rslt && lPrevCom2 == 'M') + { + //AJD do we want to remove this + // i.e. d="M 20 20 M 10 10 L 15 15 + // has a bounding box of 5,5,10,10 or 10,10,10,10 + //aPath->RemoveLastPathCommand(); + } + if(rslt) + { + aPath->MoveToL( xy[0], xy[1], ETrue ); + } + break; + case 'm': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (2) ); + // added to change values from 0.0 to 0.01f if both the co-oridnates + // are having value 0.0. + // fix for bug "CGSR-78X9V2" + if(xy[0] == KZero && xy[1] == KZero) + { + xy[0] = KMinVal; + xy[1] = KMinVal; + } + if(rslt) + { + aPath->MoveToL( xy[0], xy[1], EFalse ); + } + + break; + case 'L': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (2) ); + if(rslt) + { + aPath->LineToL( xy[0], xy[1], ETrue ); + } + break; + case 'H': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (1) ); + if(rslt) + { + aPath->HorizonToL( xy[0], ETrue ); + } + break; + case 'V': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (1) ); + if(rslt) + { + aPath->VertToL( xy[0], ETrue ); + } + break; + case 'l': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (2) ); + // added to change values from 0.0 to 0.01f if both the co-oridnates + // are having value 0.0. + // fix for bug "CGSR-78X9V2" + if(xy[0] == KZero && xy[1] == KZero) + { + xy[0] = KMinVal; + xy[1] = KMinVal; + } + if(rslt) + { + aPath->LineToL( xy[0], xy[1], EFalse ); + } + break; + case 'h': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (1) ); + // added to change values from 0.0 to 0.01f if both the co-oridnates + // are having value 0.0. + // fix for bug "CGSR-78X9V2" + if(xy[0] == KZero && xy[1] == KZero) + { + xy[0] = KMinVal; + xy[1] = KMinVal; + } + if(rslt) + { + aPath->HorizonToL( xy[0], EFalse ); + } + + break; + case 'v': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (1) ); + // added to change values from 0.0 to 0.01f if both the co-oridnates + // are having value 0.0. + // fix for bug "CGSR-78X9V2" + if(xy[0] == KZero && xy[1] == KZero) + { + xy[0] = KMinVal; + xy[1] = KMinVal; + } + if(rslt) + { + aPath->VertToL( xy[0], EFalse ); + } + + break; + case 'C': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (6) ); + if( rslt ) + { + aPath->CubicToL( xy[0], + xy[1], + xy[2], + xy[3], + xy[4], + xy[5], + ETrue ); + } + break; + case 'c': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (6) ); + if(rslt) + { + aPath->CubicToL( xy[0], + xy[1], + xy[2], + xy[3], + xy[4], + xy[5], + EFalse ); + } + break; + case 'S': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (4) ); + if(rslt) + { + aPath->ShortCubicToL( xy[0], + xy[1], + xy[2], + xy[3], + ETrue ); + } + break; + case 's': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (4) ); + if(rslt) + { + aPath->ShortCubicToL( xy[0], + xy[1], + xy[2], + xy[3], + EFalse ); + } + break; + case 'Q': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (4) ); + if( rslt ) + { + aPath->QuadToL( xy[0], + xy[1], + xy[2], + xy[3], + ETrue ); + } + break; + case 'T': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (2) ); + if(rslt) + { + + // If there is no previous command or if + // the previous command was not a Q, q, T or t, the control point shall be current point. + if ( lPrevCom2 !='Q' && lPrevCom2 != 'q' && lPrevCom2 != 'T' + && lPrevCom2 != 't' ) + { + aPath->QuadToLWithNoControlPoint( xy[0], xy[1] ); + } + else + { + aPath->ShortQuadToL( xy[0], xy[1], ETrue ); + } + } + break; + case 'q': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (4) ); + if(rslt) + { + aPath->QuadToL( xy[0], + xy[1], + xy[2], + xy[3], + EFalse ); + } + break; + case 't': + rslt = svgplex.GetNextWithNumOfPoints( xy ,TInt (2) ); + if(xy[0] != KZero || xy[1] != KZero) + { + if(rslt) + { + aPath->ShortQuadToL( xy[0], xy[1], EFalse ); + } + } + break; + case 'Z': + case 'z': + aPath->ClosePathL(); + break; + + default: + rslt=0; + break; + + }// switch(lPrevCom) + + if( !rslt ) + { + // This is a failing path case reset. + aPath->Reset(); + break ; + } + + lPrevCom2 = com; + } + svgplex.Cleanup(); + } + +// +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +void TSvgPathDataParser::ParsePointDataL( const TDesC& aData, + CGfxGeneralPath* aPath ) + { + TSvgPointLexer svgplex( aData ); + TBool first = ETrue; + while ( !svgplex.IsDone() ) + { + TChar com; + TFloatFixPt x, y; + TInt32 rslt = svgplex.GetNextPoint( com, x, y ); + + if ( rslt != KErrNone ) + { + aPath->Reset(); + break; + } + if ( first ) + { + aPath->MoveToL( x, y, ETrue ); + first = EFalse; + } + else + { + aPath->LineToL( x, y, ETrue ); + } + } + svgplex.Cleanup(); + } + +// +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +TFloatFixPt TSvgPathDataParser::PathLengthL( CGfxGeneralPath* aPath ) + { + CGfxFlatteningPathIterator* pitr; + TGfxAffineTransform ident; + pitr = CGfxFlatteningPathIterator::NewL( aPath, & ident, 3 ); + + + CleanupStack::PushL( pitr ); + + TFloatFixPt len; + TFloatFixPt lx, ly; + TFloatFixPt dx, dy, int0x7f( KMAXFLOATFIX ); + TFloatFixPt tmpcoords[6]; + while ( !pitr->IsDone() ) + { + switch ( pitr->CurrentSegment( tmpcoords ) ) + { + case EGfxSegMoveTo: + lx = tmpcoords[0]; + ly = tmpcoords[1]; + break; + case EGfxSegLineTo: + dx = lx - tmpcoords[0]; + dy = ly - tmpcoords[1]; + if ( dx > int0x7f || dy > int0x7f ) + { + // calculate as integer + TInt32 tmplen, tx, ty; + tx = ( TInt32 ) dx; + ty = ( TInt32 ) dy; + #ifdef SVG_FLOAT_BUILD + tmplen = TFloatFixPt::Sqrt(tx * tx + ty * ty); + #else + tmplen = TFloatFixPt::FixedSqrtGeneral( tx * tx + ty * ty, 0 ); + #endif + len += TFloatFixPt( tmplen ); + } + else + { + // calculate as TFixPt + + len += TFloatFixPt::Sqrt( dx * dx + dy * dy ); + } + lx = tmpcoords[0]; + ly = tmpcoords[1]; + break; + case EGfxSegClose: + ;// Not support multiple path length + break; + default: + break; + } + pitr->NextL(); + } + + CleanupStack::PopAndDestroy( 1 ); + + return len; + }