added ARCANGLETO command implementation, optimization, fixes, debug
- added new ARCANGLETO command needed for PPTX custom shapes import - added added placeholder for unimplemented QUADRATICCURVETO command, skip it's data at least so that we don't break other things for now - cache equations results to optimize custom shapes calculation PPTX import creates such equations that made system busy for long time, this removes that issue - added lot of debug output to help with debugging of complex imported custom shapes
This commit is contained in:
parent
1c0ae973dd
commit
fcdc9c4fa0
@ -103,9 +103,13 @@ class EnhancedCustomShape2d : public SfxItemSet
|
||||
/*
|
||||
|
||||
*/
|
||||
struct EquationResult {
|
||||
sal_Bool bReady;
|
||||
double fValue;
|
||||
};
|
||||
com::sun::star::uno::Sequence< rtl::OUString > seqEquations;
|
||||
std::vector< ::boost::shared_ptr< EnhancedCustomShape::ExpressionNode > > vNodesSharedPtr;
|
||||
|
||||
std::vector< EquationResult > vEquationResults;
|
||||
|
||||
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > seqSegments;
|
||||
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
|
||||
|
@ -824,14 +824,18 @@ EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
|
||||
if ( nLength )
|
||||
{
|
||||
vNodesSharedPtr.resize( nLength );
|
||||
vEquationResults.resize( nLength );
|
||||
for ( i = 0; i < seqEquations.getLength(); i++ )
|
||||
{
|
||||
vEquationResults[ i ].bReady = sal_False;
|
||||
try
|
||||
{
|
||||
vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
|
||||
}
|
||||
catch ( EnhancedCustomShape::ParseError& )
|
||||
{
|
||||
OSL_TRACE("error: equation number: %d, parser failed ( %s )",
|
||||
i, OUStringToOString( seqEquations[ i ], RTL_TEXTENCODING_ASCII_US ).getStr());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -876,20 +880,49 @@ double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex ) c
|
||||
double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
|
||||
{
|
||||
double fNumber = 0.0;
|
||||
#if OSL_DEBUG_LEVEL > 1
|
||||
static sal_uInt32 nLevel = 0;
|
||||
#endif
|
||||
if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
|
||||
{
|
||||
if ( vNodesSharedPtr[ nIndex ].get() )
|
||||
try
|
||||
{
|
||||
fNumber = (*vNodesSharedPtr[ nIndex ])();
|
||||
if ( !rtl::math::isFinite( fNumber ) )
|
||||
fNumber = 0.0;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
/* sal_Bool bUps = sal_True; */
|
||||
if ( vNodesSharedPtr[ nIndex ].get() ) {
|
||||
#if OSL_DEBUG_LEVEL > 1
|
||||
nLevel ++;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
if ( vEquationResults[ nIndex ].bReady )
|
||||
fNumber = vEquationResults[ nIndex ].fValue;
|
||||
else {
|
||||
// cast to non const, so that we can optimize by caching
|
||||
// equation results, without changing all the const in the stack
|
||||
struct EquationResult &aResult = ((EnhancedCustomShape2d*)this)->vEquationResults[ nIndex ];
|
||||
|
||||
fNumber = aResult.fValue = (*vNodesSharedPtr[ nIndex ])();
|
||||
aResult.bReady = sal_True;
|
||||
|
||||
if ( !rtl::math::isFinite( fNumber ) )
|
||||
fNumber = 0.0;
|
||||
#if OSL_DEBUG_LEVEL > 1
|
||||
OSL_TRACE("equation %d (level: %d): %s --> %f (angle: %f)", nIndex,
|
||||
nLevel, OUStringToOString( seqEquations[ nIndex ],
|
||||
RTL_TEXTENCODING_ASCII_US ).getStr(), fNumber, 180.0*fNumber/10800000.0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
/* sal_Bool bUps = sal_True; */
|
||||
OSL_TRACE("error: EnhancedCustomShape2d::GetEquationValueAsDouble failed");
|
||||
}
|
||||
#if OSL_DEBUG_LEVEL > 1
|
||||
nLevel --;
|
||||
#endif
|
||||
}
|
||||
OSL_TRACE(" ?%d --> %f (angle: %f)", nIndex,
|
||||
fNumber, 180.0*fNumber/10800000.0);
|
||||
}
|
||||
|
||||
return fNumber;
|
||||
}
|
||||
sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
|
||||
@ -1457,6 +1490,7 @@ void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegm
|
||||
if ( rSrcPt < nCoordSize )
|
||||
{
|
||||
const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
|
||||
OSL_TRACE("moveTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
|
||||
aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
|
||||
}
|
||||
}
|
||||
@ -1591,11 +1625,19 @@ void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegm
|
||||
}
|
||||
break;
|
||||
|
||||
case QUADRATICCURVETO : // TODO
|
||||
for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
|
||||
{
|
||||
rSrcPt += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case LINETO :
|
||||
{
|
||||
for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
|
||||
{
|
||||
const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
|
||||
OSL_TRACE("lineTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
|
||||
aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
|
||||
}
|
||||
}
|
||||
@ -1638,6 +1680,54 @@ void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegm
|
||||
}
|
||||
break;
|
||||
|
||||
case ARCANGLETO :
|
||||
{
|
||||
double fWR, fHR, fStartAngle, fSwingAngle;
|
||||
|
||||
for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
|
||||
{
|
||||
GetParameter ( fWR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].First, sal_True, sal_False );
|
||||
GetParameter ( fHR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].Second, sal_False, sal_True );
|
||||
|
||||
GetParameter ( fStartAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1) ].First, sal_False, sal_False );
|
||||
GetParameter ( fSwingAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1 ) ].Second, sal_False, sal_False );
|
||||
|
||||
fWR *= fXScale;
|
||||
fHR *= fYScale;
|
||||
|
||||
fStartAngle *= F_PI180;
|
||||
fSwingAngle *= F_PI180;
|
||||
|
||||
OSL_TRACE("ARCANGLETO scale: %f x %f angles: %f, %f", fWR, fHR, fStartAngle, fSwingAngle);
|
||||
|
||||
sal_Bool bClockwise = fSwingAngle >= 0.0;
|
||||
|
||||
if (aNewB2DPolygon.count() > 0)
|
||||
{
|
||||
basegfx::B2DPoint aStartPointB2D( aNewB2DPolygon.getB2DPoint(aNewB2DPolygon.count() - 1 ) );
|
||||
Point aStartPoint( aStartPointB2D.getX(), aStartPointB2D.getY() );
|
||||
|
||||
double fT = atan2((fWR*sin(fStartAngle)), (fHR*cos(fStartAngle)));
|
||||
double fTE = atan2((fWR*sin(fStartAngle + fSwingAngle)), fHR*cos(fStartAngle + fSwingAngle));
|
||||
|
||||
OSL_TRACE("ARCANGLETO angles: %f, %f --> parameters: %f, %f", fStartAngle, fSwingAngle, fT, fTE );
|
||||
|
||||
Rectangle aRect ( Point ( aStartPoint.getX() - fWR*cos(fT) - fWR, aStartPoint.getY() - fHR*sin(fT) - fHR ),
|
||||
Point ( aStartPoint.getX() - fWR*cos(fT) + fWR, aStartPoint.getY() - fHR*sin(fT) + fHR) );
|
||||
|
||||
Point aEndPoint ( aStartPoint.getX() - fWR*(cos(fT) - cos(fTE)), aStartPoint.getY() - fHR*(sin(fT) - sin(fTE)) );
|
||||
|
||||
OSL_TRACE("ARCANGLETO rect: %d, %d x %d, %d start: %d, %d end: %d, %d clockwise: %d",
|
||||
aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom(),
|
||||
aStartPoint.X(), aStartPoint.Y(), aEndPoint.X(), aEndPoint.Y(), bClockwise);
|
||||
aNewB2DPolygon.append(CreateArc( aRect, bClockwise ? aEndPoint : aStartPoint, bClockwise ? aStartPoint : aEndPoint, bClockwise));
|
||||
}
|
||||
|
||||
rSrcPt += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ELLIPTICALQUADRANTX :
|
||||
case ELLIPTICALQUADRANTY :
|
||||
{
|
||||
|
@ -163,6 +163,7 @@ public:
|
||||
}
|
||||
virtual double operator()() const
|
||||
{
|
||||
OSL_TRACE(" $%d --> %f (angle: %f)", mnIndex, mrCustoShape.GetAdjustValueAsDouble( mnIndex ), 180.0*mrCustoShape.GetAdjustValueAsDouble( mnIndex )/10800000.0);
|
||||
return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
|
||||
}
|
||||
virtual bool isConstant() const
|
||||
@ -253,6 +254,29 @@ public:
|
||||
}
|
||||
virtual double operator()() const
|
||||
{
|
||||
#if OSL_DEBUG_LEVEL > 1
|
||||
const char *funcName;
|
||||
|
||||
switch (meFunct) {
|
||||
case ENUM_FUNC_PI : funcName = "pi"; break;
|
||||
case ENUM_FUNC_LEFT : funcName = "left"; break;
|
||||
case ENUM_FUNC_TOP : funcName = "top"; break;
|
||||
case ENUM_FUNC_RIGHT : funcName = "right"; break;
|
||||
case ENUM_FUNC_BOTTOM : funcName = "bottom"; break;
|
||||
case ENUM_FUNC_XSTRETCH : funcName = "xstretch"; break;
|
||||
case ENUM_FUNC_YSTRETCH : funcName = "ystretch"; break;
|
||||
case ENUM_FUNC_HASSTROKE : funcName = "hasstroke"; break;
|
||||
case ENUM_FUNC_HASFILL : funcName = "hasfill"; break;
|
||||
case ENUM_FUNC_WIDTH : funcName = "width"; break;
|
||||
case ENUM_FUNC_HEIGHT : funcName = "height"; break;
|
||||
case ENUM_FUNC_LOGWIDTH : funcName = "logwidth"; break;
|
||||
case ENUM_FUNC_LOGHEIGHT : funcName = "logheight"; break;
|
||||
default: funcName = "???"; break;
|
||||
}
|
||||
|
||||
OSL_TRACE(" %s --> %f (angle: %f)", funcName, getValue( mrCustoShape, meFunct ), 180.0*getValue( mrCustoShape, meFunct )/10800000.0);
|
||||
#endif
|
||||
|
||||
return getValue( mrCustoShape, meFunct );
|
||||
}
|
||||
virtual bool isConstant() const
|
||||
|
Loading…
x
Reference in New Issue
Block a user