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;
|
com::sun::star::uno::Sequence< rtl::OUString > seqEquations;
|
||||||
std::vector< ::boost::shared_ptr< EnhancedCustomShape::ExpressionNode > > vNodesSharedPtr;
|
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::EnhancedCustomShapeSegment > seqSegments;
|
||||||
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
|
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
|
||||||
|
@ -824,14 +824,18 @@ EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
|
|||||||
if ( nLength )
|
if ( nLength )
|
||||||
{
|
{
|
||||||
vNodesSharedPtr.resize( nLength );
|
vNodesSharedPtr.resize( nLength );
|
||||||
|
vEquationResults.resize( nLength );
|
||||||
for ( i = 0; i < seqEquations.getLength(); i++ )
|
for ( i = 0; i < seqEquations.getLength(); i++ )
|
||||||
{
|
{
|
||||||
|
vEquationResults[ i ].bReady = sal_False;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
|
vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
|
||||||
}
|
}
|
||||||
catch ( EnhancedCustomShape::ParseError& )
|
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 EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
|
||||||
{
|
{
|
||||||
double fNumber = 0.0;
|
double fNumber = 0.0;
|
||||||
|
#if OSL_DEBUG_LEVEL > 1
|
||||||
|
static sal_uInt32 nLevel = 0;
|
||||||
|
#endif
|
||||||
if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
|
if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
|
||||||
{
|
{
|
||||||
if ( vNodesSharedPtr[ nIndex ].get() )
|
if ( vNodesSharedPtr[ nIndex ].get() ) {
|
||||||
try
|
#if OSL_DEBUG_LEVEL > 1
|
||||||
{
|
nLevel ++;
|
||||||
fNumber = (*vNodesSharedPtr[ nIndex ])();
|
#endif
|
||||||
if ( !rtl::math::isFinite( fNumber ) )
|
try
|
||||||
fNumber = 0.0;
|
{
|
||||||
}
|
if ( vEquationResults[ nIndex ].bReady )
|
||||||
catch ( ... )
|
fNumber = vEquationResults[ nIndex ].fValue;
|
||||||
{
|
else {
|
||||||
/* sal_Bool bUps = sal_True; */
|
// 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;
|
return fNumber;
|
||||||
}
|
}
|
||||||
sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
|
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 )
|
if ( rSrcPt < nCoordSize )
|
||||||
{
|
{
|
||||||
const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
|
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()));
|
aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1591,11 +1625,19 @@ void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegm
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QUADRATICCURVETO : // TODO
|
||||||
|
for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
|
||||||
|
{
|
||||||
|
rSrcPt += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case LINETO :
|
case LINETO :
|
||||||
{
|
{
|
||||||
for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
|
for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
|
||||||
{
|
{
|
||||||
const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
|
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()));
|
aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1638,6 +1680,54 @@ void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegm
|
|||||||
}
|
}
|
||||||
break;
|
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 ELLIPTICALQUADRANTX :
|
||||||
case ELLIPTICALQUADRANTY :
|
case ELLIPTICALQUADRANTY :
|
||||||
{
|
{
|
||||||
|
@ -163,6 +163,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual double operator()() const
|
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 );
|
return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
|
||||||
}
|
}
|
||||||
virtual bool isConstant() const
|
virtual bool isConstant() const
|
||||||
@ -253,6 +254,29 @@ public:
|
|||||||
}
|
}
|
||||||
virtual double operator()() const
|
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 );
|
return getValue( mrCustoShape, meFunct );
|
||||||
}
|
}
|
||||||
virtual bool isConstant() const
|
virtual bool isConstant() const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user