1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svx/EnhancedCustomShape2d.hxx"
21 #include <rtl/ustring.hxx>
22 #include <osl/diagnose.h>
23 #include <tools/fract.hxx>
25 // Makes parser a static resource,
26 // we're synchronized externally.
27 // But watch out, the parser might have
28 // state not visible to this code!
30 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
31 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
33 #define BOOST_SPIRIT_DEBUG
35 #include <boost/spirit/include/classic_core.hpp>
37 #if (OSL_DEBUG_LEVEL > 0)
45 using namespace EnhancedCustomShape
;
46 using namespace com::sun::star
;
47 using namespace com::sun::star::drawing
;
49 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter
& rSource
, const sal_Int32 nDestPara
, EnhancedCustomShapeEquation
& rDest
)
52 if ( rSource
.Value
.getValueTypeClass() == uno::TypeClass_DOUBLE
)
55 if ( rSource
.Value
>>= fValue
)
56 nValue
= (sal_Int32
)fValue
;
59 rSource
.Value
>>= nValue
;
61 switch( rSource
.Type
)
63 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION
:
65 if ( nValue
& 0x40000000 )
68 rDest
.nOperation
|= 0x20000000 << nDestPara
; // the bit is indicating that this value has to be adjusted later
73 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT
: nValue
+= DFF_Prop_adjustValue
; break;
74 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM
: nValue
= DFF_Prop_geoBottom
; break;
75 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT
: nValue
= DFF_Prop_geoRight
; break;
76 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP
: nValue
= DFF_Prop_geoTop
; break;
77 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT
: nValue
= DFF_Prop_geoLeft
; break;
79 if ( rSource
.Type
!= com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL
)
80 rDest
.nOperation
|= ( 0x2000 << nDestPara
);
81 rDest
.nPara
[ nDestPara
] = nValue
;
84 ExpressionNode::~ExpressionNode()
95 class ConstantValueExpression
: public ExpressionNode
101 ConstantValueExpression( double rValue
) :
105 virtual double operator()() const SAL_OVERRIDE
109 virtual bool isConstant() const SAL_OVERRIDE
113 virtual ExpressionFunct
getType() const SAL_OVERRIDE
117 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /* pOptionalArg */, sal_uInt32
/* nFlags */ ) SAL_OVERRIDE
119 EnhancedCustomShapeParameter aRet
;
120 Fraction
aFract( maValue
);
121 if ( aFract
.GetDenominator() == 1 )
123 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
124 aRet
.Value
<<= (sal_Int32
)aFract
.GetNumerator();
128 EnhancedCustomShapeEquation aEquation
;
129 aEquation
.nOperation
= 1;
130 aEquation
.nPara
[ 0 ] = 1;
131 aEquation
.nPara
[ 1 ] = (sal_Int16
)aFract
.GetNumerator();
132 aEquation
.nPara
[ 2 ] = (sal_Int16
)aFract
.GetDenominator();
133 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
134 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
135 rEquations
.push_back( aEquation
);
141 class AdjustmentExpression
: public ExpressionNode
144 const EnhancedCustomShape2d
& mrCustoShape
;
148 AdjustmentExpression( const EnhancedCustomShape2d
& rCustoShape
, sal_Int32 nIndex
)
150 , mrCustoShape( rCustoShape
)
154 virtual double operator()() const SAL_OVERRIDE
158 "$" << mnIndex
<< " --> "
159 << mrCustoShape
.GetAdjustValueAsDouble(mnIndex
) << " (angle: "
160 << 180.0*mrCustoShape
.GetAdjustValueAsDouble(mnIndex
)/10800000.0
162 return mrCustoShape
.GetAdjustValueAsDouble( mnIndex
);
164 virtual bool isConstant() const SAL_OVERRIDE
168 virtual ExpressionFunct
getType() const SAL_OVERRIDE
170 return ENUM_FUNC_ADJUSTMENT
;
172 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& /*rEquations*/, ExpressionNode
* /*pOptionalArg*/, sal_uInt32
/*nFlags*/ ) SAL_OVERRIDE
174 EnhancedCustomShapeParameter aRet
;
175 aRet
.Type
= EnhancedCustomShapeParameterType::ADJUSTMENT
;
176 aRet
.Value
<<= mnIndex
;
181 class EquationExpression
: public ExpressionNode
184 const EnhancedCustomShape2d
& mrCustoShape
;
188 EquationExpression( const EnhancedCustomShape2d
& rCustoShape
, sal_Int32 nIndex
)
190 , mrCustoShape( rCustoShape
)
193 virtual double operator()() const SAL_OVERRIDE
195 return mrCustoShape
.GetEquationValueAsDouble( mnIndex
);
197 virtual bool isConstant() const SAL_OVERRIDE
201 virtual ExpressionFunct
getType() const SAL_OVERRIDE
203 return ENUM_FUNC_EQUATION
;
205 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& /*rEquations*/, ExpressionNode
* /*pOptionalArg*/, sal_uInt32
/*nFlags*/ ) SAL_OVERRIDE
207 EnhancedCustomShapeParameter aRet
;
208 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
209 aRet
.Value
<<= mnIndex
| 0x40000000; // the bit is indicating that this equation needs to be adjusted later
214 class EnumValueExpression
: public ExpressionNode
216 const ExpressionFunct meFunct
;
217 const EnhancedCustomShape2d
& mrCustoShape
;
221 EnumValueExpression( const EnhancedCustomShape2d
& rCustoShape
, const ExpressionFunct eFunct
)
223 , mrCustoShape ( rCustoShape
)
226 static double getValue( const EnhancedCustomShape2d
& rCustoShape
, const ExpressionFunct eFunc
)
228 EnhancedCustomShape2d::EnumFunc eF
;
231 case ENUM_FUNC_PI
: eF
= EnhancedCustomShape2d::ENUM_FUNC_PI
; break;
232 case ENUM_FUNC_LEFT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_LEFT
; break;
233 case ENUM_FUNC_TOP
: eF
= EnhancedCustomShape2d::ENUM_FUNC_TOP
; break;
234 case ENUM_FUNC_RIGHT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_RIGHT
; break;
235 case ENUM_FUNC_BOTTOM
: eF
= EnhancedCustomShape2d::ENUM_FUNC_BOTTOM
; break;
236 case ENUM_FUNC_XSTRETCH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH
; break;
237 case ENUM_FUNC_YSTRETCH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH
; break;
238 case ENUM_FUNC_HASSTROKE
: eF
= EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE
; break;
239 case ENUM_FUNC_HASFILL
: eF
= EnhancedCustomShape2d::ENUM_FUNC_HASFILL
; break;
240 case ENUM_FUNC_WIDTH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_WIDTH
; break;
241 case ENUM_FUNC_HEIGHT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_HEIGHT
; break;
242 case ENUM_FUNC_LOGWIDTH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH
; break;
243 case ENUM_FUNC_LOGHEIGHT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT
; break;
248 return rCustoShape
.GetEnumFunc( eF
);
250 virtual double operator()() const SAL_OVERRIDE
252 #if OSL_DEBUG_LEVEL > 1
253 const char *funcName
;
256 case ENUM_FUNC_PI
: funcName
= "pi"; break;
257 case ENUM_FUNC_LEFT
: funcName
= "left"; break;
258 case ENUM_FUNC_TOP
: funcName
= "top"; break;
259 case ENUM_FUNC_RIGHT
: funcName
= "right"; break;
260 case ENUM_FUNC_BOTTOM
: funcName
= "bottom"; break;
261 case ENUM_FUNC_XSTRETCH
: funcName
= "xstretch"; break;
262 case ENUM_FUNC_YSTRETCH
: funcName
= "ystretch"; break;
263 case ENUM_FUNC_HASSTROKE
: funcName
= "hasstroke"; break;
264 case ENUM_FUNC_HASFILL
: funcName
= "hasfill"; break;
265 case ENUM_FUNC_WIDTH
: funcName
= "width"; break;
266 case ENUM_FUNC_HEIGHT
: funcName
= "height"; break;
267 case ENUM_FUNC_LOGWIDTH
: funcName
= "logwidth"; break;
268 case ENUM_FUNC_LOGHEIGHT
: funcName
= "logheight"; break;
269 default: funcName
= "???"; break;
272 OSL_TRACE(" %s --> %f (angle: %f)", funcName
, getValue( mrCustoShape
, meFunct
), 180.0*getValue( mrCustoShape
, meFunct
)/10800000.0);
275 return getValue( mrCustoShape
, meFunct
);
277 virtual bool isConstant() const SAL_OVERRIDE
281 virtual ExpressionFunct
getType() const SAL_OVERRIDE
285 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
) SAL_OVERRIDE
287 EnhancedCustomShapeParameter aRet
;
289 sal_Int32 nDummy
= 1;
290 aRet
.Value
<<= nDummy
;
294 case ENUM_FUNC_WIDTH
: // TODO: do not use this as constant value
295 case ENUM_FUNC_HEIGHT
:
296 case ENUM_FUNC_LOGWIDTH
:
297 case ENUM_FUNC_LOGHEIGHT
:
300 ConstantValueExpression
aConstantValue( getValue( mrCustoShape
, meFunct
) );
301 aRet
= aConstantValue
.fillNode( rEquations
, NULL
, nFlags
);
304 case ENUM_FUNC_LEFT
: aRet
.Type
= EnhancedCustomShapeParameterType::LEFT
; break;
305 case ENUM_FUNC_TOP
: aRet
.Type
= EnhancedCustomShapeParameterType::TOP
; break;
306 case ENUM_FUNC_RIGHT
: aRet
.Type
= EnhancedCustomShapeParameterType::RIGHT
; break;
307 case ENUM_FUNC_BOTTOM
: aRet
.Type
= EnhancedCustomShapeParameterType::BOTTOM
; break;
309 // not implemented so far
310 case ENUM_FUNC_XSTRETCH
:
311 case ENUM_FUNC_YSTRETCH
:
312 case ENUM_FUNC_HASSTROKE
:
313 case ENUM_FUNC_HASFILL
: aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
; break;
322 /** ExpressionNode implementation for unary
323 function over one ExpressionNode
325 class UnaryFunctionExpression
: public ExpressionNode
327 const ExpressionFunct meFunct
;
328 ExpressionNodeSharedPtr mpArg
;
331 UnaryFunctionExpression( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rArg
) :
336 static double getValue( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rArg
)
341 case UNARY_FUNC_ABS
: fRet
= fabs( (*rArg
)() ); break;
342 case UNARY_FUNC_SQRT
: fRet
= sqrt( (*rArg
)() ); break;
343 case UNARY_FUNC_SIN
: fRet
= sin( (*rArg
)() ); break;
344 case UNARY_FUNC_COS
: fRet
= cos( (*rArg
)() ); break;
345 case UNARY_FUNC_TAN
: fRet
= tan( (*rArg
)() ); break;
346 case UNARY_FUNC_ATAN
: fRet
= atan( (*rArg
)() ); break;
347 case UNARY_FUNC_NEG
: fRet
= ::std::negate
<double>()( (*rArg
)() ); break;
353 virtual double operator()() const SAL_OVERRIDE
355 return getValue( meFunct
, mpArg
);
357 virtual bool isConstant() const SAL_OVERRIDE
359 return mpArg
->isConstant();
361 virtual ExpressionFunct
getType() const SAL_OVERRIDE
365 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* pOptionalArg
, sal_uInt32 nFlags
) SAL_OVERRIDE
367 EnhancedCustomShapeParameter aRet
;
370 case UNARY_FUNC_ABS
:
372 EnhancedCustomShapeEquation aEquation
;
373 aEquation
.nOperation
|= 3;
374 FillEquationParameter( mpArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
375 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
376 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
377 rEquations
.push_back( aEquation
);
380 case UNARY_FUNC_SQRT
:
382 EnhancedCustomShapeEquation aEquation
;
383 aEquation
.nOperation
|= 13;
384 FillEquationParameter( mpArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
385 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
386 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
387 rEquations
.push_back( aEquation
);
390 case UNARY_FUNC_SIN
:
392 EnhancedCustomShapeEquation aEquation
;
393 aEquation
.nOperation
|= 9;
395 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
397 aEquation
.nPara
[ 0 ] = 1;
399 EnhancedCustomShapeParameter
aSource( mpArg
->fillNode( rEquations
, NULL
, nFlags
| EXPRESSION_FLAG_SUMANGLE_MODE
) );
400 if ( aSource
.Type
== EnhancedCustomShapeParameterType::NORMAL
)
401 { // sumangle needed :-(
402 EnhancedCustomShapeEquation _aEquation
;
403 _aEquation
.nOperation
|= 0xe; // sumangle
404 FillEquationParameter( aSource
, 1, _aEquation
);
405 aSource
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
406 aSource
.Value
<<= (sal_Int32
)rEquations
.size();
407 rEquations
.push_back( _aEquation
);
409 FillEquationParameter( aSource
, 1, aEquation
);
410 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
411 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
412 rEquations
.push_back( aEquation
);
415 case UNARY_FUNC_COS
:
417 EnhancedCustomShapeEquation aEquation
;
418 aEquation
.nOperation
|= 10;
420 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
422 aEquation
.nPara
[ 0 ] = 1;
424 EnhancedCustomShapeParameter
aSource( mpArg
->fillNode( rEquations
, NULL
, nFlags
| EXPRESSION_FLAG_SUMANGLE_MODE
) );
425 if ( aSource
.Type
== EnhancedCustomShapeParameterType::NORMAL
)
426 { // sumangle needed :-(
427 EnhancedCustomShapeEquation aTmpEquation
;
428 aTmpEquation
.nOperation
|= 0xe; // sumangle
429 FillEquationParameter( aSource
, 1, aTmpEquation
);
430 aSource
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
431 aSource
.Value
<<= (sal_Int32
)rEquations
.size();
432 rEquations
.push_back( aTmpEquation
);
434 FillEquationParameter( aSource
, 1, aEquation
);
435 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
436 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
437 rEquations
.push_back( aEquation
);
440 case UNARY_FUNC_TAN
:
442 EnhancedCustomShapeEquation aEquation
;
443 aEquation
.nOperation
|= 16;
445 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
447 aEquation
.nPara
[ 0 ] = 1;
449 EnhancedCustomShapeParameter
aSource( mpArg
->fillNode( rEquations
, NULL
, nFlags
| EXPRESSION_FLAG_SUMANGLE_MODE
) );
450 if ( aSource
.Type
== EnhancedCustomShapeParameterType::NORMAL
)
451 { // sumangle needed :-(
452 EnhancedCustomShapeEquation aTmpEquation
;
453 aTmpEquation
.nOperation
|= 0xe; // sumangle
454 FillEquationParameter( aSource
, 1, aTmpEquation
);
455 aSource
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
456 aSource
.Value
<<= (sal_Int32
)rEquations
.size();
457 rEquations
.push_back( aTmpEquation
);
459 FillEquationParameter( aSource
, 1, aEquation
);
460 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
461 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
462 rEquations
.push_back( aEquation
);
465 case UNARY_FUNC_ATAN
:
468 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
473 EnhancedCustomShapeEquation aEquation
;
474 aEquation
.nOperation
|= 1;
475 aEquation
.nPara
[ 1 ] = -1;
476 aEquation
.nPara
[ 2 ] = 1;
477 FillEquationParameter( mpArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
478 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
479 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
480 rEquations
.push_back( aEquation
);
490 /** ExpressionNode implementation for unary
491 function over two ExpressionNodes
493 class BinaryFunctionExpression
: public ExpressionNode
495 const ExpressionFunct meFunct
;
496 ExpressionNodeSharedPtr mpFirstArg
;
497 ExpressionNodeSharedPtr mpSecondArg
;
501 BinaryFunctionExpression( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rFirstArg
, const ExpressionNodeSharedPtr
& rSecondArg
) :
503 mpFirstArg( rFirstArg
),
504 mpSecondArg( rSecondArg
)
507 static double getValue( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rFirstArg
, const ExpressionNodeSharedPtr
& rSecondArg
)
512 case BINARY_FUNC_PLUS
: fRet
= (*rFirstArg
)() + (*rSecondArg
)(); break;
513 case BINARY_FUNC_MINUS
: fRet
= (*rFirstArg
)() - (*rSecondArg
)(); break;
514 case BINARY_FUNC_MUL
: fRet
= (*rFirstArg
)() * (*rSecondArg
)(); break;
515 case BINARY_FUNC_DIV
: fRet
= (*rFirstArg
)() / (*rSecondArg
)(); break;
516 case BINARY_FUNC_MIN
: fRet
= ::std::min( (*rFirstArg
)(), (*rSecondArg
)() ); break;
517 case BINARY_FUNC_MAX
: fRet
= ::std::max( (*rFirstArg
)(), (*rSecondArg
)() ); break;
518 case BINARY_FUNC_ATAN2
: fRet
= atan2( (*rFirstArg
)(), (*rSecondArg
)() ); break;
524 virtual double operator()() const SAL_OVERRIDE
526 return getValue( meFunct
, mpFirstArg
, mpSecondArg
);
528 virtual bool isConstant() const SAL_OVERRIDE
530 return mpFirstArg
->isConstant() && mpSecondArg
->isConstant();
532 virtual ExpressionFunct
getType() const SAL_OVERRIDE
536 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
) SAL_OVERRIDE
538 EnhancedCustomShapeParameter aRet
;
541 case BINARY_FUNC_PLUS
:
543 if ( nFlags
& EXPRESSION_FLAG_SUMANGLE_MODE
)
545 if ( mpFirstArg
->getType() == ENUM_FUNC_ADJUSTMENT
)
547 EnhancedCustomShapeEquation aEquation
;
548 aEquation
.nOperation
|= 0xe; // sumangle
549 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
550 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
551 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
552 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
553 rEquations
.push_back( aEquation
);
555 else if ( mpSecondArg
->getType() == ENUM_FUNC_ADJUSTMENT
)
557 EnhancedCustomShapeEquation aEquation
;
558 aEquation
.nOperation
|= 0xe; // sumangle
559 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
560 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
561 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
562 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
563 rEquations
.push_back( aEquation
);
567 EnhancedCustomShapeEquation aSumangle1
;
568 aSumangle1
.nOperation
|= 0xe; // sumangle
569 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
&~EXPRESSION_FLAG_SUMANGLE_MODE
), 1, aSumangle1
);
570 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
571 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
572 rEquations
.push_back( aSumangle1
);
574 EnhancedCustomShapeEquation aSumangle2
;
575 aSumangle2
.nOperation
|= 0xe; // sumangle
576 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
&~EXPRESSION_FLAG_SUMANGLE_MODE
), 1, aSumangle2
);
577 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
578 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
579 rEquations
.push_back( aSumangle2
);
581 EnhancedCustomShapeEquation aEquation
;
582 aEquation
.nOperation
|= 0;
583 aEquation
.nPara
[ 0 ] = ( rEquations
.size() - 2 ) | 0x400;
584 aEquation
.nPara
[ 1 ] = ( rEquations
.size() - 1 ) | 0x400;
585 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
586 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
587 rEquations
.push_back( aEquation
);
592 bool bFirstIsEmpty
= mpFirstArg
->isConstant() && ( (*mpFirstArg
)() == 0 );
593 bool bSecondIsEmpty
= mpSecondArg
->isConstant() && ( (*mpSecondArg
)() == 0 );
596 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
597 else if ( bSecondIsEmpty
)
598 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
601 EnhancedCustomShapeEquation aEquation
;
602 aEquation
.nOperation
|= 0;
603 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
604 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
605 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
606 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
607 rEquations
.push_back( aEquation
);
612 case BINARY_FUNC_MINUS
:
614 EnhancedCustomShapeEquation aEquation
;
615 aEquation
.nOperation
|= 0;
616 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
617 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 2, aEquation
);
618 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
619 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
620 rEquations
.push_back( aEquation
);
623 case BINARY_FUNC_MUL
:
625 // in the dest. format the cos function is using integer as result :-(
626 // so we can't use the generic algorithm
627 if ( ( mpFirstArg
->getType() == UNARY_FUNC_SIN
) || ( mpFirstArg
->getType() == UNARY_FUNC_COS
) || ( mpFirstArg
->getType() == UNARY_FUNC_TAN
) )
628 aRet
= mpFirstArg
->fillNode( rEquations
, mpSecondArg
.get(), nFlags
);
629 else if ( ( mpSecondArg
->getType() == UNARY_FUNC_SIN
) || ( mpSecondArg
->getType() == UNARY_FUNC_COS
) || ( mpSecondArg
->getType() == UNARY_FUNC_TAN
) )
630 aRet
= mpSecondArg
->fillNode( rEquations
, mpFirstArg
.get(), nFlags
);
633 if ( mpFirstArg
->isConstant() && (*mpFirstArg
)() == 1 )
634 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
635 else if ( mpSecondArg
->isConstant() && (*mpSecondArg
)() == 1 )
636 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
637 else if ( ( mpFirstArg
->getType() == BINARY_FUNC_DIV
) // don't care of (pi/180)
638 && ( static_cast<BinaryFunctionExpression
*>(mpFirstArg
.get())->mpFirstArg
.get()->getType() == ENUM_FUNC_PI
)
639 && ( static_cast<BinaryFunctionExpression
*>(mpFirstArg
.get())->mpSecondArg
.get()->getType() == FUNC_CONST
) )
641 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
643 else if ( ( mpSecondArg
->getType() == BINARY_FUNC_DIV
) // don't care of (pi/180)
644 && ( static_cast<BinaryFunctionExpression
*>(mpSecondArg
.get())->mpFirstArg
.get()->getType() == ENUM_FUNC_PI
)
645 && ( static_cast<BinaryFunctionExpression
*>(mpSecondArg
.get())->mpSecondArg
.get()->getType() == FUNC_CONST
) )
647 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
651 EnhancedCustomShapeEquation aEquation
;
652 aEquation
.nOperation
|= 1;
653 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
654 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
655 aEquation
.nPara
[ 2 ] = 1;
656 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
657 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
658 rEquations
.push_back( aEquation
);
663 case BINARY_FUNC_DIV
:
665 EnhancedCustomShapeEquation aEquation
;
666 aEquation
.nOperation
|= 1;
667 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
668 aEquation
.nPara
[ 1 ] = 1;
669 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 2, aEquation
);
670 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
671 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
672 rEquations
.push_back( aEquation
);
675 case BINARY_FUNC_MIN
:
677 EnhancedCustomShapeEquation aEquation
;
678 aEquation
.nOperation
|= 4;
679 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
680 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
681 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
682 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
683 rEquations
.push_back( aEquation
);
686 case BINARY_FUNC_MAX
:
688 EnhancedCustomShapeEquation aEquation
;
689 aEquation
.nOperation
|= 5;
690 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
691 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
692 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
693 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
694 rEquations
.push_back( aEquation
);
697 case BINARY_FUNC_ATAN2
:
699 EnhancedCustomShapeEquation aEquation
;
700 aEquation
.nOperation
|= 8;
701 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
702 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
703 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
704 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
705 rEquations
.push_back( aEquation
);
715 class IfExpression
: public ExpressionNode
717 ExpressionNodeSharedPtr mpFirstArg
;
718 ExpressionNodeSharedPtr mpSecondArg
;
719 ExpressionNodeSharedPtr mpThirdArg
;
723 IfExpression( const ExpressionNodeSharedPtr
& rFirstArg
,
724 const ExpressionNodeSharedPtr
& rSecondArg
,
725 const ExpressionNodeSharedPtr
& rThirdArg
) :
726 mpFirstArg( rFirstArg
),
727 mpSecondArg( rSecondArg
),
728 mpThirdArg( rThirdArg
)
731 virtual bool isConstant() const SAL_OVERRIDE
734 mpFirstArg
->isConstant() &&
735 mpSecondArg
->isConstant() &&
736 mpThirdArg
->isConstant();
738 virtual double operator()() const SAL_OVERRIDE
740 return (*mpFirstArg
)() > 0 ? (*mpSecondArg
)() : (*mpThirdArg
)();
742 virtual ExpressionFunct
getType() const SAL_OVERRIDE
744 return TERNARY_FUNC_IF
;
746 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
) SAL_OVERRIDE
748 EnhancedCustomShapeParameter aRet
;
749 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
750 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
752 EnhancedCustomShapeEquation aEquation
;
753 aEquation
.nOperation
|= 6;
754 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
755 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
756 FillEquationParameter( mpThirdArg
->fillNode( rEquations
, NULL
, nFlags
), 2, aEquation
);
757 rEquations
.push_back( aEquation
);
769 typedef const sal_Char
* StringIteratorT
;
773 typedef ::std::stack
< ExpressionNodeSharedPtr
> OperandStack
;
775 // stores a stack of not-yet-evaluated operands. This is used
776 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
777 // arguments from. If all arguments to an operator are constant,
778 // the operator pushes a precalculated result on the stack, and
779 // a composite ExpressionNode otherwise.
780 OperandStack maOperandStack
;
782 const EnhancedCustomShape2d
* mpCustoShape
;
786 typedef std::shared_ptr
< ParserContext
> ParserContextSharedPtr
;
788 /** Generate parse-dependent-but-then-constant value
790 class DoubleConstantFunctor
792 ParserContextSharedPtr mxContext
;
795 DoubleConstantFunctor( const ParserContextSharedPtr
& rContext
) :
796 mxContext( rContext
)
799 void operator()( double n
) const
801 mxContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n
) ) );
807 const ExpressionFunct meFunct
;
809 ParserContextSharedPtr mxContext
;
813 EnumFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
)
816 , mxContext( rContext
)
819 void operator()( StringIteratorT rFirst
, StringIteratorT rSecond
) const
821 /*double nVal = mnValue;*/
824 case ENUM_FUNC_ADJUSTMENT
:
826 OUString
aVal( rFirst
+ 1, rSecond
- rFirst
, RTL_TEXTENCODING_UTF8
);
827 mxContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mxContext
->mpCustoShape
, aVal
.toInt32() ) ) );
830 case ENUM_FUNC_EQUATION
:
832 OUString
aVal( rFirst
+ 1, rSecond
- rFirst
, RTL_TEXTENCODING_UTF8
);
833 mxContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new EquationExpression( *mxContext
->mpCustoShape
, aVal
.toInt32() ) ) );
837 mxContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mxContext
->mpCustoShape
, meFunct
) ) );
842 class UnaryFunctionFunctor
844 const ExpressionFunct meFunct
;
845 ParserContextSharedPtr mxContext
;
849 UnaryFunctionFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
) :
851 mxContext( rContext
)
854 void operator()( StringIteratorT
, StringIteratorT
) const
856 ParserContext::OperandStack
& rNodeStack( mxContext
->maOperandStack
);
858 if( rNodeStack
.size() < 1 )
859 throw ParseError( "Not enough arguments for unary operator" );
861 // retrieve arguments
862 ExpressionNodeSharedPtr
pArg( rNodeStack
.top() );
865 if( pArg
->isConstant() ) // check for constness
866 rNodeStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct
, pArg
) ) ) );
867 else // push complex node, that calcs the value on demand
868 rNodeStack
.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct
, pArg
) ) );
872 /** Implements a binary function over two ExpressionNodes
875 Generator functor, to generate an ExpressionNode of
879 class BinaryFunctionFunctor
881 const ExpressionFunct meFunct
;
882 ParserContextSharedPtr mxContext
;
886 BinaryFunctionFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
) :
888 mxContext( rContext
)
892 void operator()( StringIteratorT
, StringIteratorT
) const
894 ParserContext::OperandStack
& rNodeStack( mxContext
->maOperandStack
);
896 if( rNodeStack
.size() < 2 )
897 throw ParseError( "Not enough arguments for binary operator" );
899 // retrieve arguments
900 ExpressionNodeSharedPtr
pSecondArg( rNodeStack
.top() );
902 ExpressionNodeSharedPtr
pFirstArg( rNodeStack
.top() );
905 // create combined ExpressionNode
906 ExpressionNodeSharedPtr pNode
= ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct
, pFirstArg
, pSecondArg
) );
907 // check for constness
908 if( pFirstArg
->isConstant() && pSecondArg
->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
909 rNodeStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode
)() ) ) );
910 else // push complex node, that calcs the value on demand
911 rNodeStack
.push( pNode
);
917 ParserContextSharedPtr mxContext
;
921 IfFunctor( const ParserContextSharedPtr
& rContext
) :
922 mxContext( rContext
)
925 void operator()( StringIteratorT
, StringIteratorT
) const
927 ParserContext::OperandStack
& rNodeStack( mxContext
->maOperandStack
);
929 if( rNodeStack
.size() < 3 )
930 throw ParseError( "Not enough arguments for ternary operator" );
932 // retrieve arguments
933 ExpressionNodeSharedPtr
pThirdArg( rNodeStack
.top() );
935 ExpressionNodeSharedPtr
pSecondArg( rNodeStack
.top() );
937 ExpressionNodeSharedPtr
pFirstArg( rNodeStack
.top() );
940 // create combined ExpressionNode
941 ExpressionNodeSharedPtr
pNode( new IfExpression( pFirstArg
, pSecondArg
, pThirdArg
) );
942 // check for constness
943 if( pFirstArg
->isConstant() && pSecondArg
->isConstant() && pThirdArg
->isConstant() )
944 rNodeStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode
)() ) ) ); // call the operator() at pNode, store result in constant value ExpressionNode.
946 rNodeStack
.push( pNode
); // push complex node, that calcs the value on demand
950 // Workaround for MSVC compiler anomaly (stack trashing)
952 // The default ureal_parser_policies implementation of parse_exp
953 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
954 // that the real_parser_impl::parse_main() call of parse_exp()
955 // overwrites the frame pointer _on the stack_ (EBP of the calling
956 // function gets overwritten while lying on the stack).
958 // For the time being, our parser thus can only read the 1.0E10
959 // notation, not the 1.0e10 one.
961 // TODO(F1): Also handle the 1.0e10 case here.
962 template< typename T
> struct custom_real_parser_policies
: public ::boost::spirit::ureal_parser_policies
<T
>
964 template< typename ScannerT
>
965 static typename ::boost::spirit::parser_result
< ::boost::spirit::chlit
<>, ScannerT
>::type
966 parse_exp(ScannerT
& scan
)
968 // as_lower_d somehow breaks MSVC7
969 return ::boost::spirit::ch_p('E').parse(scan
);
973 /* This class implements the following grammar (more or
974 less literally written down below, only slightly
975 obfuscated by the parser actions):
977 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
979 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
984 function '(' additive_expression ')' |
985 '(' additive_expression ')'
988 '-' basic_expression |
991 multiplicative_expression =
992 unary_expression ( ( '*' unary_expression )* |
993 ( '/' unary_expression )* )
995 additive_expression =
996 multiplicative_expression ( ( '+' multiplicative_expression )* |
997 ( '-' multiplicative_expression )* )
1001 class ExpressionGrammar
: public ::boost::spirit::grammar
< ExpressionGrammar
>
1004 /** Create an arithmetic expression grammar
1006 @param rParserContext
1007 Contains context info for the parser
1009 ExpressionGrammar( const ParserContextSharedPtr
& rParserContext
) :
1010 mpParserContext( rParserContext
)
1014 template< typename ScannerT
> class definition
1017 // grammar definition
1018 definition( const ExpressionGrammar
& self
)
1020 using ::boost::spirit::str_p
;
1021 using ::boost::spirit::range_p
;
1022 using ::boost::spirit::lexeme_d
;
1023 using ::boost::spirit::real_parser
;
1024 using ::boost::spirit::chseq_p
;
1027 str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI
, self
.getContext() ) ]
1028 | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT
, self
.getContext() ) ]
1029 | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP
, self
.getContext() ) ]
1030 | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT
, self
.getContext() ) ]
1031 | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM
, self
.getContext() ) ]
1032 | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH
, self
.getContext() ) ]
1033 | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH
, self
.getContext() ) ]
1034 | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE
, self
.getContext() ) ]
1035 | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL
, self
.getContext() ) ]
1036 | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH
, self
.getContext() ) ]
1037 | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT
, self
.getContext() ) ]
1038 | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH
, self
.getContext() ) ]
1039 | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT
, self
.getContext() ) ]
1043 (str_p( "abs" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS
, self
.getContext()) ]
1044 | (str_p( "sqrt" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT
, self
.getContext()) ]
1045 | (str_p( "sin" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN
, self
.getContext()) ]
1046 | (str_p( "cos" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS
, self
.getContext()) ]
1047 | (str_p( "tan" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN
, self
.getContext()) ]
1048 | (str_p( "atan" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN
, self
.getContext()) ]
1052 (str_p( "min" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN
, self
.getContext()) ]
1053 | (str_p( "max" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX
, self
.getContext()) ]
1054 | (str_p( "atan2") >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2
,self
.getContext()) ]
1058 (str_p( "if" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ IfFunctor( self
.getContext() ) ]
1062 lexeme_d
[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1065 (str_p( "?" ) >> funcRef_decl
)[ EnumFunctor( ENUM_FUNC_EQUATION
, self
.getContext() ) ];
1068 lexeme_d
[ +( range_p('0','9') ) ];
1071 (str_p( "$" ) >> modRef_decl
)[ EnumFunctor( ENUM_FUNC_ADJUSTMENT
, self
.getContext() ) ];
1074 real_parser
<double, custom_real_parser_policies
<double> >()[ DoubleConstantFunctor(self
.getContext()) ]
1081 | '(' >> additiveExpression
>> ')'
1085 ('-' >> basicExpression
)[ UnaryFunctionFunctor( UNARY_FUNC_NEG
, self
.getContext()) ]
1089 multiplicativeExpression
=
1091 >> *( ('*' >> unaryExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_MUL
, self
.getContext()) ]
1092 | ('/' >> unaryExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_DIV
, self
.getContext()) ]
1096 additiveExpression
=
1097 multiplicativeExpression
1098 >> *( ('+' >> multiplicativeExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS
, self
.getContext()) ]
1099 | ('-' >> multiplicativeExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS
, self
.getContext()) ]
1103 BOOST_SPIRIT_DEBUG_RULE(additiveExpression
);
1104 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression
);
1105 BOOST_SPIRIT_DEBUG_RULE(unaryExpression
);
1106 BOOST_SPIRIT_DEBUG_RULE(basicExpression
);
1107 BOOST_SPIRIT_DEBUG_RULE(unaryFunction
);
1108 BOOST_SPIRIT_DEBUG_RULE(binaryFunction
);
1109 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction
);
1110 BOOST_SPIRIT_DEBUG_RULE(identifier
);
1113 const ::boost::spirit::rule
< ScannerT
>& start() const
1115 return additiveExpression
;
1119 // the constituents of the Spirit arithmetic expression grammar.
1120 // For the sake of readability, without 'ma' prefix.
1121 ::boost::spirit::rule
< ScannerT
> additiveExpression
;
1122 ::boost::spirit::rule
< ScannerT
> multiplicativeExpression
;
1123 ::boost::spirit::rule
< ScannerT
> unaryExpression
;
1124 ::boost::spirit::rule
< ScannerT
> basicExpression
;
1125 ::boost::spirit::rule
< ScannerT
> unaryFunction
;
1126 ::boost::spirit::rule
< ScannerT
> binaryFunction
;
1127 ::boost::spirit::rule
< ScannerT
> ternaryFunction
;
1128 ::boost::spirit::rule
< ScannerT
> funcRef_decl
;
1129 ::boost::spirit::rule
< ScannerT
> functionReference
;
1130 ::boost::spirit::rule
< ScannerT
> modRef_decl
;
1131 ::boost::spirit::rule
< ScannerT
> modifierReference
;
1132 ::boost::spirit::rule
< ScannerT
> identifier
;
1135 const ParserContextSharedPtr
& getContext() const
1137 return mpParserContext
;
1141 ParserContextSharedPtr mpParserContext
; // might get modified during parsing
1144 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1145 const ParserContextSharedPtr
& getParserContext()
1147 static ParserContextSharedPtr
lcl_parserContext( new ParserContext() );
1149 // clear node stack (since we reuse the static object, that's
1150 // the whole point here)
1151 while( !lcl_parserContext
->maOperandStack
.empty() )
1152 lcl_parserContext
->maOperandStack
.pop();
1154 return lcl_parserContext
;
1160 namespace EnhancedCustomShape
{
1164 ExpressionNodeSharedPtr
FunctionParser::parseFunction( const OUString
& rFunction
, const EnhancedCustomShape2d
& rCustoShape
)
1166 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1167 // gives better conversion robustness here (we might want to map space
1168 // etc. to ASCII space here)
1169 const OString
& rAsciiFunction(
1170 OUStringToOString( rFunction
, RTL_TEXTENCODING_ASCII_US
) );
1172 StringIteratorT
aStart( rAsciiFunction
.getStr() );
1173 StringIteratorT
aEnd( rAsciiFunction
.getStr()+rAsciiFunction
.getLength() );
1175 ParserContextSharedPtr pContext
;
1177 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1178 // static parser context, because the actual
1179 // Spirit parser is also a static object
1180 pContext
= getParserContext();
1182 pContext
.reset( new ParserContext() );
1184 pContext
->mpCustoShape
= &rCustoShape
;
1186 ExpressionGrammar
aExpressionGrammer( pContext
);
1187 const ::boost::spirit::parse_info
<StringIteratorT
> aParseInfo(
1188 ::boost::spirit::parse( aStart
,
1190 aExpressionGrammer
>> ::boost::spirit::end_p
,
1191 ::boost::spirit::space_p
) );
1193 #if (OSL_DEBUG_LEVEL > 0)
1194 ::std::cout
.flush(); // needed to keep stdout and cout in sync
1197 // input fully congested by the parser?
1198 if( !aParseInfo
.full
)
1199 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1201 // parser's state stack now must contain exactly _one_ ExpressionNode,
1202 // which represents our formula.
1203 if( pContext
->maOperandStack
.size() != 1 )
1204 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1207 return pContext
->maOperandStack
.top();
1213 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */