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 <tools/fract.hxx>
24 // Makes parser a static resource,
25 // we're synchronized externally.
26 // But watch out, the parser might have
27 // state not visible to this code!
29 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
30 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
32 #define BOOST_SPIRIT_DEBUG
34 #include <boost/spirit/include/classic_core.hpp>
36 #if (OSL_DEBUG_LEVEL > 0)
43 #include <math.h> // fabs, sqrt, sin, cos, tan, atan, atan2
44 using namespace EnhancedCustomShape
;
45 using namespace com::sun::star
;
46 using namespace com::sun::star::drawing
;
48 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter
& rSource
, const sal_Int32 nDestPara
, EnhancedCustomShapeEquation
& rDest
)
51 if ( rSource
.Value
.getValueTypeClass() == uno::TypeClass_DOUBLE
)
54 if ( rSource
.Value
>>= fValue
)
55 nValue
= (sal_Int32
)fValue
;
58 rSource
.Value
>>= nValue
;
60 switch( rSource
.Type
)
62 case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION
:
64 if ( nValue
& 0x40000000 )
67 rDest
.nOperation
|= 0x20000000 << nDestPara
; // the bit is indicating that this value has to be adjusted later
72 case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT
: nValue
+= DFF_Prop_adjustValue
; break;
73 case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM
: nValue
= DFF_Prop_geoBottom
; break;
74 case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT
: nValue
= DFF_Prop_geoRight
; break;
75 case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP
: nValue
= DFF_Prop_geoTop
; break;
76 case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT
: nValue
= DFF_Prop_geoLeft
; break;
78 if ( rSource
.Type
!= com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL
)
79 rDest
.nOperation
|= ( 0x2000 << nDestPara
);
80 rDest
.nPara
[ nDestPara
] = nValue
;
83 ExpressionNode::~ExpressionNode()
89 //////////////////////
90 //////////////////////
92 //////////////////////
93 //////////////////////
94 class ConstantValueExpression
: public ExpressionNode
100 ConstantValueExpression( double rValue
) :
104 virtual double operator()() const
108 virtual bool isConstant() const
112 virtual ExpressionFunct
getType() const
116 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /* pOptionalArg */, sal_uInt32
/* nFlags */ )
118 EnhancedCustomShapeParameter aRet
;
119 Fraction
aFract( maValue
);
120 if ( aFract
.GetDenominator() == 1 )
122 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
123 aRet
.Value
<<= (sal_Int32
)aFract
.GetNumerator();
127 EnhancedCustomShapeEquation aEquation
;
128 aEquation
.nOperation
= 1;
129 aEquation
.nPara
[ 0 ] = 1;
130 aEquation
.nPara
[ 1 ] = (sal_Int16
)aFract
.GetNumerator();
131 aEquation
.nPara
[ 2 ] = (sal_Int16
)aFract
.GetDenominator();
132 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
133 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
134 rEquations
.push_back( aEquation
);
140 class AdjustmentExpression
: public ExpressionNode
143 const EnhancedCustomShape2d
& mrCustoShape
;
147 AdjustmentExpression( const EnhancedCustomShape2d
& rCustoShape
, sal_Int32 nIndex
)
149 , mrCustoShape( rCustoShape
)
153 virtual double operator()() const
155 OSL_TRACE(" $%d --> %f (angle: %f)", mnIndex
, mrCustoShape
.GetAdjustValueAsDouble( mnIndex
), 180.0*mrCustoShape
.GetAdjustValueAsDouble( mnIndex
)/10800000.0);
156 return mrCustoShape
.GetAdjustValueAsDouble( mnIndex
);
158 virtual bool isConstant() const
162 virtual ExpressionFunct
getType() const
164 return ENUM_FUNC_ADJUSTMENT
;
166 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& /*rEquations*/, ExpressionNode
* /*pOptionalArg*/, sal_uInt32
/*nFlags*/ )
168 EnhancedCustomShapeParameter aRet
;
169 aRet
.Type
= EnhancedCustomShapeParameterType::ADJUSTMENT
;
170 aRet
.Value
<<= mnIndex
;
175 class EquationExpression
: public ExpressionNode
178 const EnhancedCustomShape2d
& mrCustoShape
;
182 EquationExpression( const EnhancedCustomShape2d
& rCustoShape
, sal_Int32 nIndex
)
184 , mrCustoShape( rCustoShape
)
187 virtual double operator()() const
189 return mrCustoShape
.GetEquationValueAsDouble( mnIndex
);
191 virtual bool isConstant() const
195 virtual ExpressionFunct
getType() const
197 return ENUM_FUNC_EQUATION
;
199 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& /*rEquations*/, ExpressionNode
* /*pOptionalArg*/, sal_uInt32
/*nFlags*/ )
201 EnhancedCustomShapeParameter aRet
;
202 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
203 aRet
.Value
<<= mnIndex
| 0x40000000; // the bit is indicating that this equation needs to be adjusted later
208 class EnumValueExpression
: public ExpressionNode
210 const ExpressionFunct meFunct
;
211 const EnhancedCustomShape2d
& mrCustoShape
;
215 EnumValueExpression( const EnhancedCustomShape2d
& rCustoShape
, const ExpressionFunct eFunct
)
217 , mrCustoShape ( rCustoShape
)
220 static double getValue( const EnhancedCustomShape2d
& rCustoShape
, const ExpressionFunct eFunc
)
222 EnhancedCustomShape2d::EnumFunc eF
;
225 case ENUM_FUNC_PI
: eF
= EnhancedCustomShape2d::ENUM_FUNC_PI
; break;
226 case ENUM_FUNC_LEFT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_LEFT
; break;
227 case ENUM_FUNC_TOP
: eF
= EnhancedCustomShape2d::ENUM_FUNC_TOP
; break;
228 case ENUM_FUNC_RIGHT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_RIGHT
; break;
229 case ENUM_FUNC_BOTTOM
: eF
= EnhancedCustomShape2d::ENUM_FUNC_BOTTOM
; break;
230 case ENUM_FUNC_XSTRETCH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH
; break;
231 case ENUM_FUNC_YSTRETCH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH
; break;
232 case ENUM_FUNC_HASSTROKE
: eF
= EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE
; break;
233 case ENUM_FUNC_HASFILL
: eF
= EnhancedCustomShape2d::ENUM_FUNC_HASFILL
; break;
234 case ENUM_FUNC_WIDTH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_WIDTH
; break;
235 case ENUM_FUNC_HEIGHT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_HEIGHT
; break;
236 case ENUM_FUNC_LOGWIDTH
: eF
= EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH
; break;
237 case ENUM_FUNC_LOGHEIGHT
: eF
= EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT
; break;
242 return rCustoShape
.GetEnumFunc( eF
);
244 virtual double operator()() const
246 #if OSL_DEBUG_LEVEL > 1
247 const char *funcName
;
250 case ENUM_FUNC_PI
: funcName
= "pi"; break;
251 case ENUM_FUNC_LEFT
: funcName
= "left"; break;
252 case ENUM_FUNC_TOP
: funcName
= "top"; break;
253 case ENUM_FUNC_RIGHT
: funcName
= "right"; break;
254 case ENUM_FUNC_BOTTOM
: funcName
= "bottom"; break;
255 case ENUM_FUNC_XSTRETCH
: funcName
= "xstretch"; break;
256 case ENUM_FUNC_YSTRETCH
: funcName
= "ystretch"; break;
257 case ENUM_FUNC_HASSTROKE
: funcName
= "hasstroke"; break;
258 case ENUM_FUNC_HASFILL
: funcName
= "hasfill"; break;
259 case ENUM_FUNC_WIDTH
: funcName
= "width"; break;
260 case ENUM_FUNC_HEIGHT
: funcName
= "height"; break;
261 case ENUM_FUNC_LOGWIDTH
: funcName
= "logwidth"; break;
262 case ENUM_FUNC_LOGHEIGHT
: funcName
= "logheight"; break;
263 default: funcName
= "???"; break;
266 OSL_TRACE(" %s --> %f (angle: %f)", funcName
, getValue( mrCustoShape
, meFunct
), 180.0*getValue( mrCustoShape
, meFunct
)/10800000.0);
269 return getValue( mrCustoShape
, meFunct
);
271 virtual bool isConstant() const
275 virtual ExpressionFunct
getType() const
279 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
)
281 EnhancedCustomShapeParameter aRet
;
283 sal_Int32 nDummy
= 1;
284 aRet
.Value
<<= nDummy
;
288 case ENUM_FUNC_WIDTH
: // TODO: do not use this as constant value
289 case ENUM_FUNC_HEIGHT
:
290 case ENUM_FUNC_LOGWIDTH
:
291 case ENUM_FUNC_LOGHEIGHT
:
294 ConstantValueExpression
aConstantValue( getValue( mrCustoShape
, meFunct
) );
295 aRet
= aConstantValue
.fillNode( rEquations
, NULL
, nFlags
);
298 case ENUM_FUNC_LEFT
: aRet
.Type
= EnhancedCustomShapeParameterType::LEFT
; break;
299 case ENUM_FUNC_TOP
: aRet
.Type
= EnhancedCustomShapeParameterType::TOP
; break;
300 case ENUM_FUNC_RIGHT
: aRet
.Type
= EnhancedCustomShapeParameterType::RIGHT
; break;
301 case ENUM_FUNC_BOTTOM
: aRet
.Type
= EnhancedCustomShapeParameterType::BOTTOM
; break;
303 // not implemented so far
304 case ENUM_FUNC_XSTRETCH
:
305 case ENUM_FUNC_YSTRETCH
:
306 case ENUM_FUNC_HASSTROKE
:
307 case ENUM_FUNC_HASFILL
: aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
; break;
316 /** ExpressionNode implementation for unary
317 function over one ExpressionNode
319 class UnaryFunctionExpression
: public ExpressionNode
321 const ExpressionFunct meFunct
;
322 ExpressionNodeSharedPtr mpArg
;
325 UnaryFunctionExpression( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rArg
) :
330 static double getValue( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rArg
)
335 case UNARY_FUNC_ABS
: fRet
= fabs( (*rArg
)() ); break;
336 case UNARY_FUNC_SQRT
: fRet
= sqrt( (*rArg
)() ); break;
337 case UNARY_FUNC_SIN
: fRet
= sin( (*rArg
)() ); break;
338 case UNARY_FUNC_COS
: fRet
= cos( (*rArg
)() ); break;
339 case UNARY_FUNC_TAN
: fRet
= tan( (*rArg
)() ); break;
340 case UNARY_FUNC_ATAN
: fRet
= atan( (*rArg
)() ); break;
341 case UNARY_FUNC_NEG
: fRet
= ::std::negate
<double>()( (*rArg
)() ); break;
347 virtual double operator()() const
349 return getValue( meFunct
, mpArg
);
351 virtual bool isConstant() const
353 return mpArg
->isConstant();
355 virtual ExpressionFunct
getType() const
359 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* pOptionalArg
, sal_uInt32 nFlags
)
361 EnhancedCustomShapeParameter aRet
;
364 case UNARY_FUNC_ABS
:
366 EnhancedCustomShapeEquation aEquation
;
367 aEquation
.nOperation
|= 3;
368 FillEquationParameter( mpArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
369 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
370 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
371 rEquations
.push_back( aEquation
);
374 case UNARY_FUNC_SQRT
:
376 EnhancedCustomShapeEquation aEquation
;
377 aEquation
.nOperation
|= 13;
378 FillEquationParameter( mpArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
379 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
380 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
381 rEquations
.push_back( aEquation
);
384 case UNARY_FUNC_SIN
:
386 EnhancedCustomShapeEquation aEquation
;
387 aEquation
.nOperation
|= 9;
389 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
391 aEquation
.nPara
[ 0 ] = 1;
393 EnhancedCustomShapeParameter
aSource( mpArg
->fillNode( rEquations
, NULL
, nFlags
| EXPRESSION_FLAG_SUMANGLE_MODE
) );
394 if ( aSource
.Type
== EnhancedCustomShapeParameterType::NORMAL
)
395 { // sumangle needed :-(
396 EnhancedCustomShapeEquation _aEquation
;
397 _aEquation
.nOperation
|= 0xe; // sumangle
398 FillEquationParameter( aSource
, 1, _aEquation
);
399 aSource
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
400 aSource
.Value
<<= (sal_Int32
)rEquations
.size();
401 rEquations
.push_back( _aEquation
);
403 FillEquationParameter( aSource
, 1, aEquation
);
404 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
405 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
406 rEquations
.push_back( aEquation
);
409 case UNARY_FUNC_COS
:
411 EnhancedCustomShapeEquation aEquation
;
412 aEquation
.nOperation
|= 10;
414 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
416 aEquation
.nPara
[ 0 ] = 1;
418 EnhancedCustomShapeParameter
aSource( mpArg
->fillNode( rEquations
, NULL
, nFlags
| EXPRESSION_FLAG_SUMANGLE_MODE
) );
419 if ( aSource
.Type
== EnhancedCustomShapeParameterType::NORMAL
)
420 { // sumangle needed :-(
421 EnhancedCustomShapeEquation aTmpEquation
;
422 aTmpEquation
.nOperation
|= 0xe; // sumangle
423 FillEquationParameter( aSource
, 1, aTmpEquation
);
424 aSource
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
425 aSource
.Value
<<= (sal_Int32
)rEquations
.size();
426 rEquations
.push_back( aTmpEquation
);
428 FillEquationParameter( aSource
, 1, aEquation
);
429 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
430 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
431 rEquations
.push_back( aEquation
);
434 case UNARY_FUNC_TAN
:
436 EnhancedCustomShapeEquation aEquation
;
437 aEquation
.nOperation
|= 16;
439 FillEquationParameter( pOptionalArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
441 aEquation
.nPara
[ 0 ] = 1;
443 EnhancedCustomShapeParameter
aSource( mpArg
->fillNode( rEquations
, NULL
, nFlags
| EXPRESSION_FLAG_SUMANGLE_MODE
) );
444 if ( aSource
.Type
== EnhancedCustomShapeParameterType::NORMAL
)
445 { // sumangle needed :-(
446 EnhancedCustomShapeEquation aTmpEquation
;
447 aTmpEquation
.nOperation
|= 0xe; // sumangle
448 FillEquationParameter( aSource
, 1, aTmpEquation
);
449 aSource
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
450 aSource
.Value
<<= (sal_Int32
)rEquations
.size();
451 rEquations
.push_back( aTmpEquation
);
453 FillEquationParameter( aSource
, 1, aEquation
);
454 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
455 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
456 rEquations
.push_back( aEquation
);
459 case UNARY_FUNC_ATAN
:
462 aRet
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
467 EnhancedCustomShapeEquation aEquation
;
468 aEquation
.nOperation
|= 1;
469 aEquation
.nPara
[ 1 ] = -1;
470 aEquation
.nPara
[ 2 ] = 1;
471 FillEquationParameter( mpArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
472 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
473 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
474 rEquations
.push_back( aEquation
);
484 /** ExpressionNode implementation for unary
485 function over two ExpressionNodes
487 class BinaryFunctionExpression
: public ExpressionNode
489 const ExpressionFunct meFunct
;
490 ExpressionNodeSharedPtr mpFirstArg
;
491 ExpressionNodeSharedPtr mpSecondArg
;
495 BinaryFunctionExpression( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rFirstArg
, const ExpressionNodeSharedPtr
& rSecondArg
) :
497 mpFirstArg( rFirstArg
),
498 mpSecondArg( rSecondArg
)
501 static double getValue( const ExpressionFunct eFunct
, const ExpressionNodeSharedPtr
& rFirstArg
, const ExpressionNodeSharedPtr
& rSecondArg
)
506 case BINARY_FUNC_PLUS
: fRet
= (*rFirstArg
)() + (*rSecondArg
)(); break;
507 case BINARY_FUNC_MINUS
: fRet
= (*rFirstArg
)() - (*rSecondArg
)(); break;
508 case BINARY_FUNC_MUL
: fRet
= (*rFirstArg
)() * (*rSecondArg
)(); break;
509 case BINARY_FUNC_DIV
: fRet
= (*rFirstArg
)() / (*rSecondArg
)(); break;
510 case BINARY_FUNC_MIN
: fRet
= ::std::min( (*rFirstArg
)(), (*rSecondArg
)() ); break;
511 case BINARY_FUNC_MAX
: fRet
= ::std::max( (*rFirstArg
)(), (*rSecondArg
)() ); break;
512 case BINARY_FUNC_ATAN2
: fRet
= atan2( (*rFirstArg
)(), (*rSecondArg
)() ); break;
518 virtual double operator()() const
520 return getValue( meFunct
, mpFirstArg
, mpSecondArg
);
522 virtual bool isConstant() const
524 return mpFirstArg
->isConstant() && mpSecondArg
->isConstant();
526 virtual ExpressionFunct
getType() const
530 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
)
532 EnhancedCustomShapeParameter aRet
;
535 case BINARY_FUNC_PLUS
:
537 if ( nFlags
& EXPRESSION_FLAG_SUMANGLE_MODE
)
539 if ( mpFirstArg
->getType() == ENUM_FUNC_ADJUSTMENT
)
541 EnhancedCustomShapeEquation aEquation
;
542 aEquation
.nOperation
|= 0xe; // sumangle
543 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
544 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
545 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
546 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
547 rEquations
.push_back( aEquation
);
549 else if ( mpSecondArg
->getType() == ENUM_FUNC_ADJUSTMENT
)
551 EnhancedCustomShapeEquation aEquation
;
552 aEquation
.nOperation
|= 0xe; // sumangle
553 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
554 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
555 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
556 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
557 rEquations
.push_back( aEquation
);
561 EnhancedCustomShapeEquation aSumangle1
;
562 aSumangle1
.nOperation
|= 0xe; // sumangle
563 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
&~EXPRESSION_FLAG_SUMANGLE_MODE
), 1, aSumangle1
);
564 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
565 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
566 rEquations
.push_back( aSumangle1
);
568 EnhancedCustomShapeEquation aSumangle2
;
569 aSumangle2
.nOperation
|= 0xe; // sumangle
570 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
&~EXPRESSION_FLAG_SUMANGLE_MODE
), 1, aSumangle2
);
571 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
572 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
573 rEquations
.push_back( aSumangle2
);
575 EnhancedCustomShapeEquation aEquation
;
576 aEquation
.nOperation
|= 0;
577 aEquation
.nPara
[ 0 ] = ( rEquations
.size() - 2 ) | 0x400;
578 aEquation
.nPara
[ 1 ] = ( rEquations
.size() - 1 ) | 0x400;
579 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
580 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
581 rEquations
.push_back( aEquation
);
586 bool bFirstIsEmpty
= mpFirstArg
->isConstant() && ( (*mpFirstArg
)() == 0 );
587 bool bSecondIsEmpty
= mpSecondArg
->isConstant() && ( (*mpSecondArg
)() == 0 );
590 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
591 else if ( bSecondIsEmpty
)
592 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
595 EnhancedCustomShapeEquation aEquation
;
596 aEquation
.nOperation
|= 0;
597 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
598 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
599 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
600 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
601 rEquations
.push_back( aEquation
);
606 case BINARY_FUNC_MINUS
:
608 EnhancedCustomShapeEquation aEquation
;
609 aEquation
.nOperation
|= 0;
610 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
611 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 2, aEquation
);
612 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
613 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
614 rEquations
.push_back( aEquation
);
617 case BINARY_FUNC_MUL
:
619 // in the dest. format the cos function is using integer as result :-(
620 // so we can't use the generic algorithm
621 if ( ( mpFirstArg
->getType() == UNARY_FUNC_SIN
) || ( mpFirstArg
->getType() == UNARY_FUNC_COS
) || ( mpFirstArg
->getType() == UNARY_FUNC_TAN
) )
622 aRet
= mpFirstArg
->fillNode( rEquations
, mpSecondArg
.get(), nFlags
);
623 else if ( ( mpSecondArg
->getType() == UNARY_FUNC_SIN
) || ( mpSecondArg
->getType() == UNARY_FUNC_COS
) || ( mpSecondArg
->getType() == UNARY_FUNC_TAN
) )
624 aRet
= mpSecondArg
->fillNode( rEquations
, mpFirstArg
.get(), nFlags
);
627 if ( mpFirstArg
->isConstant() && (*mpFirstArg
)() == 1 )
628 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
629 else if ( mpSecondArg
->isConstant() && (*mpSecondArg
)() == 1 )
630 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
631 else if ( ( mpFirstArg
->getType() == BINARY_FUNC_DIV
) // don't care of (pi/180)
632 && ( ((BinaryFunctionExpression
*)((BinaryFunctionExpression
*)mpFirstArg
.get())->mpFirstArg
.get())->getType() == ENUM_FUNC_PI
)
633 && ( ((BinaryFunctionExpression
*)((BinaryFunctionExpression
*)mpFirstArg
.get())->mpSecondArg
.get())->getType() == FUNC_CONST
) )
635 aRet
= mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
);
637 else if ( ( mpSecondArg
->getType() == BINARY_FUNC_DIV
) // don't care of (pi/180)
638 && ( ((BinaryFunctionExpression
*)((BinaryFunctionExpression
*)mpSecondArg
.get())->mpFirstArg
.get())->getType() == ENUM_FUNC_PI
)
639 && ( ((BinaryFunctionExpression
*)((BinaryFunctionExpression
*)mpSecondArg
.get())->mpSecondArg
.get())->getType() == FUNC_CONST
) )
641 aRet
= mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
);
645 EnhancedCustomShapeEquation aEquation
;
646 aEquation
.nOperation
|= 1;
647 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
648 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
649 aEquation
.nPara
[ 2 ] = 1;
650 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
651 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
652 rEquations
.push_back( aEquation
);
657 case BINARY_FUNC_DIV
:
659 EnhancedCustomShapeEquation aEquation
;
660 aEquation
.nOperation
|= 1;
661 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
662 aEquation
.nPara
[ 1 ] = 1;
663 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 2, aEquation
);
664 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
665 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
666 rEquations
.push_back( aEquation
);
669 case BINARY_FUNC_MIN
:
671 EnhancedCustomShapeEquation aEquation
;
672 aEquation
.nOperation
|= 4;
673 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
674 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
675 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
676 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
677 rEquations
.push_back( aEquation
);
680 case BINARY_FUNC_MAX
:
682 EnhancedCustomShapeEquation aEquation
;
683 aEquation
.nOperation
|= 5;
684 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
685 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
686 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
687 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
688 rEquations
.push_back( aEquation
);
691 case BINARY_FUNC_ATAN2
:
693 EnhancedCustomShapeEquation aEquation
;
694 aEquation
.nOperation
|= 8;
695 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
696 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
697 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
698 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
699 rEquations
.push_back( aEquation
);
709 class IfExpression
: public ExpressionNode
711 ExpressionNodeSharedPtr mpFirstArg
;
712 ExpressionNodeSharedPtr mpSecondArg
;
713 ExpressionNodeSharedPtr mpThirdArg
;
717 IfExpression( const ExpressionNodeSharedPtr
& rFirstArg
,
718 const ExpressionNodeSharedPtr
& rSecondArg
,
719 const ExpressionNodeSharedPtr
& rThirdArg
) :
720 mpFirstArg( rFirstArg
),
721 mpSecondArg( rSecondArg
),
722 mpThirdArg( rThirdArg
)
725 virtual bool isConstant() const
728 mpFirstArg
->isConstant() &&
729 mpSecondArg
->isConstant() &&
730 mpThirdArg
->isConstant();
732 virtual double operator()() const
734 return (*mpFirstArg
)() > 0 ? (*mpSecondArg
)() : (*mpThirdArg
)();
736 virtual ExpressionFunct
getType() const
738 return TERNARY_FUNC_IF
;
740 virtual EnhancedCustomShapeParameter
fillNode( std::vector
< EnhancedCustomShapeEquation
>& rEquations
, ExpressionNode
* /*pOptionalArg*/, sal_uInt32 nFlags
)
742 EnhancedCustomShapeParameter aRet
;
743 aRet
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
744 aRet
.Value
<<= (sal_Int32
)rEquations
.size();
746 EnhancedCustomShapeEquation aEquation
;
747 aEquation
.nOperation
|= 6;
748 FillEquationParameter( mpFirstArg
->fillNode( rEquations
, NULL
, nFlags
), 0, aEquation
);
749 FillEquationParameter( mpSecondArg
->fillNode( rEquations
, NULL
, nFlags
), 1, aEquation
);
750 FillEquationParameter( mpThirdArg
->fillNode( rEquations
, NULL
, nFlags
), 2, aEquation
);
751 rEquations
.push_back( aEquation
);
757 ////////////////////////
758 ////////////////////////
760 ////////////////////////
761 ////////////////////////
763 typedef const sal_Char
* StringIteratorT
;
767 typedef ::std::stack
< ExpressionNodeSharedPtr
> OperandStack
;
769 // stores a stack of not-yet-evaluated operands. This is used
770 // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
771 // arguments from. If all arguments to an operator are constant,
772 // the operator pushes a precalculated result on the stack, and
773 // a composite ExpressionNode otherwise.
774 OperandStack maOperandStack
;
776 const EnhancedCustomShape2d
* mpCustoShape
;
780 typedef ::boost::shared_ptr
< ParserContext
> ParserContextSharedPtr
;
782 /** Generate apriori constant value
785 class ConstantFunctor
787 const double mnValue
;
788 ParserContextSharedPtr mpContext
;
792 ConstantFunctor( double rValue
, const ParserContextSharedPtr
& rContext
) :
794 mpContext( rContext
)
797 void operator()( StringIteratorT
/*rFirst*/, StringIteratorT
/*rSecond*/ ) const
799 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( mnValue
) ) );
803 /** Generate parse-dependent-but-then-constant value
805 class DoubleConstantFunctor
807 ParserContextSharedPtr mpContext
;
810 DoubleConstantFunctor( const ParserContextSharedPtr
& rContext
) :
811 mpContext( rContext
)
814 void operator()( double n
) const
816 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n
) ) );
822 const ExpressionFunct meFunct
;
824 ParserContextSharedPtr mpContext
;
828 EnumFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
)
831 , mpContext( rContext
)
834 void operator()( StringIteratorT rFirst
, StringIteratorT rSecond
) const
836 /*double nVal = mnValue;*/
839 case ENUM_FUNC_ADJUSTMENT
:
841 OUString
aVal( rFirst
+ 1, rSecond
- rFirst
, RTL_TEXTENCODING_UTF8
);
842 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext
->mpCustoShape
, aVal
.toInt32() ) ) );
845 case ENUM_FUNC_EQUATION
:
847 OUString
aVal( rFirst
+ 1, rSecond
- rFirst
, RTL_TEXTENCODING_UTF8
);
848 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext
->mpCustoShape
, aVal
.toInt32() ) ) );
852 mpContext
->maOperandStack
.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext
->mpCustoShape
, meFunct
) ) );
857 class UnaryFunctionFunctor
859 const ExpressionFunct meFunct
;
860 ParserContextSharedPtr mpContext
;
864 UnaryFunctionFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
) :
866 mpContext( rContext
)
869 void operator()( StringIteratorT
, StringIteratorT
) const
871 ParserContext::OperandStack
& rNodeStack( mpContext
->maOperandStack
);
873 if( rNodeStack
.size() < 1 )
874 throw ParseError( "Not enough arguments for unary operator" );
876 // retrieve arguments
877 ExpressionNodeSharedPtr
pArg( rNodeStack
.top() );
880 if( pArg
->isConstant() ) // check for constness
881 rNodeStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct
, pArg
) ) ) );
882 else // push complex node, that calcs the value on demand
883 rNodeStack
.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct
, pArg
) ) );
887 /** Implements a binary function over two ExpressionNodes
890 Generator functor, to generate an ExpressionNode of
894 class BinaryFunctionFunctor
896 const ExpressionFunct meFunct
;
897 ParserContextSharedPtr mpContext
;
901 BinaryFunctionFunctor( const ExpressionFunct eFunct
, const ParserContextSharedPtr
& rContext
) :
903 mpContext( rContext
)
907 void operator()( StringIteratorT
, StringIteratorT
) const
909 ParserContext::OperandStack
& rNodeStack( mpContext
->maOperandStack
);
911 if( rNodeStack
.size() < 2 )
912 throw ParseError( "Not enough arguments for binary operator" );
914 // retrieve arguments
915 ExpressionNodeSharedPtr
pSecondArg( rNodeStack
.top() );
917 ExpressionNodeSharedPtr
pFirstArg( rNodeStack
.top() );
920 // create combined ExpressionNode
921 ExpressionNodeSharedPtr pNode
= ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct
, pFirstArg
, pSecondArg
) );
922 // check for constness
923 if( pFirstArg
->isConstant() && pSecondArg
->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
924 rNodeStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode
)() ) ) );
925 else // push complex node, that calcs the value on demand
926 rNodeStack
.push( pNode
);
932 ParserContextSharedPtr mpContext
;
936 IfFunctor( const ParserContextSharedPtr
& rContext
) :
937 mpContext( rContext
)
940 void operator()( StringIteratorT
, StringIteratorT
) const
942 ParserContext::OperandStack
& rNodeStack( mpContext
->maOperandStack
);
944 if( rNodeStack
.size() < 3 )
945 throw ParseError( "Not enough arguments for ternary operator" );
947 // retrieve arguments
948 ExpressionNodeSharedPtr
pThirdArg( rNodeStack
.top() );
950 ExpressionNodeSharedPtr
pSecondArg( rNodeStack
.top() );
952 ExpressionNodeSharedPtr
pFirstArg( rNodeStack
.top() );
955 // create combined ExpressionNode
956 ExpressionNodeSharedPtr
pNode( new IfExpression( pFirstArg
, pSecondArg
, pThirdArg
) );
957 // check for constness
958 if( pFirstArg
->isConstant() && pSecondArg
->isConstant() && pThirdArg
->isConstant() )
959 rNodeStack
.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode
)() ) ) ); // call the operator() at pNode, store result in constant value ExpressionNode.
961 rNodeStack
.push( pNode
); // push complex node, that calcs the value on demand
965 // Workaround for MSVC compiler anomaly (stack trashing)
967 // The default ureal_parser_policies implementation of parse_exp
968 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
969 // that the real_parser_impl::parse_main() call of parse_exp()
970 // overwrites the frame pointer _on the stack_ (EBP of the calling
971 // function gets overwritten while lying on the stack).
973 // For the time being, our parser thus can only read the 1.0E10
974 // notation, not the 1.0e10 one.
976 // TODO(F1): Also handle the 1.0e10 case here.
977 template< typename T
> struct custom_real_parser_policies
: public ::boost::spirit::ureal_parser_policies
<T
>
979 template< typename ScannerT
>
980 static typename ::boost::spirit::parser_result
< ::boost::spirit::chlit
<>, ScannerT
>::type
981 parse_exp(ScannerT
& scan
)
983 // as_lower_d somehow breaks MSVC7
984 return ::boost::spirit::ch_p('E').parse(scan
);
988 /* This class implements the following grammar (more or
989 less literally written down below, only slightly
990 obfuscated by the parser actions):
992 identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
994 function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
999 function '(' additive_expression ')' |
1000 '(' additive_expression ')'
1003 '-' basic_expression |
1006 multiplicative_expression =
1007 unary_expression ( ( '*' unary_expression )* |
1008 ( '/' unary_expression )* )
1010 additive_expression =
1011 multiplicative_expression ( ( '+' multiplicative_expression )* |
1012 ( '-' multiplicative_expression )* )
1016 class ExpressionGrammar
: public ::boost::spirit::grammar
< ExpressionGrammar
>
1019 /** Create an arithmetic expression grammar
1021 @param rParserContext
1022 Contains context info for the parser
1024 ExpressionGrammar( const ParserContextSharedPtr
& rParserContext
) :
1025 mpParserContext( rParserContext
)
1029 template< typename ScannerT
> class definition
1032 // grammar definition
1033 definition( const ExpressionGrammar
& self
)
1035 using ::boost::spirit::str_p
;
1036 using ::boost::spirit::range_p
;
1037 using ::boost::spirit::lexeme_d
;
1038 using ::boost::spirit::real_parser
;
1039 using ::boost::spirit::chseq_p
;
1042 str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI
, self
.getContext() ) ]
1043 | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT
, self
.getContext() ) ]
1044 | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP
, self
.getContext() ) ]
1045 | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT
, self
.getContext() ) ]
1046 | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM
, self
.getContext() ) ]
1047 | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH
, self
.getContext() ) ]
1048 | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH
, self
.getContext() ) ]
1049 | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE
, self
.getContext() ) ]
1050 | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL
, self
.getContext() ) ]
1051 | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH
, self
.getContext() ) ]
1052 | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT
, self
.getContext() ) ]
1053 | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH
, self
.getContext() ) ]
1054 | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT
, self
.getContext() ) ]
1058 (str_p( "abs" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS
, self
.getContext()) ]
1059 | (str_p( "sqrt" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT
, self
.getContext()) ]
1060 | (str_p( "sin" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN
, self
.getContext()) ]
1061 | (str_p( "cos" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS
, self
.getContext()) ]
1062 | (str_p( "tan" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN
, self
.getContext()) ]
1063 | (str_p( "atan" ) >> '(' >> additiveExpression
>> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN
, self
.getContext()) ]
1067 (str_p( "min" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN
, self
.getContext()) ]
1068 | (str_p( "max" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX
, self
.getContext()) ]
1069 | (str_p( "atan2") >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2
,self
.getContext()) ]
1073 (str_p( "if" ) >> '(' >> additiveExpression
>> ',' >> additiveExpression
>> ',' >> additiveExpression
>> ')' )[ IfFunctor( self
.getContext() ) ]
1077 lexeme_d
[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1080 (str_p( "?" ) >> funcRef_decl
)[ EnumFunctor( ENUM_FUNC_EQUATION
, self
.getContext() ) ];
1083 lexeme_d
[ +( range_p('0','9') ) ];
1086 (str_p( "$" ) >> modRef_decl
)[ EnumFunctor( ENUM_FUNC_ADJUSTMENT
, self
.getContext() ) ];
1089 real_parser
<double, custom_real_parser_policies
<double> >()[ DoubleConstantFunctor(self
.getContext()) ]
1096 | '(' >> additiveExpression
>> ')'
1100 ('-' >> basicExpression
)[ UnaryFunctionFunctor( UNARY_FUNC_NEG
, self
.getContext()) ]
1104 multiplicativeExpression
=
1106 >> *( ('*' >> unaryExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_MUL
, self
.getContext()) ]
1107 | ('/' >> unaryExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_DIV
, self
.getContext()) ]
1111 additiveExpression
=
1112 multiplicativeExpression
1113 >> *( ('+' >> multiplicativeExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS
, self
.getContext()) ]
1114 | ('-' >> multiplicativeExpression
)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS
, self
.getContext()) ]
1118 BOOST_SPIRIT_DEBUG_RULE(additiveExpression
);
1119 BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression
);
1120 BOOST_SPIRIT_DEBUG_RULE(unaryExpression
);
1121 BOOST_SPIRIT_DEBUG_RULE(basicExpression
);
1122 BOOST_SPIRIT_DEBUG_RULE(unaryFunction
);
1123 BOOST_SPIRIT_DEBUG_RULE(binaryFunction
);
1124 BOOST_SPIRIT_DEBUG_RULE(ternaryFunction
);
1125 BOOST_SPIRIT_DEBUG_RULE(identifier
);
1128 const ::boost::spirit::rule
< ScannerT
>& start() const
1130 return additiveExpression
;
1134 // the constituents of the Spirit arithmetic expression grammar.
1135 // For the sake of readability, without 'ma' prefix.
1136 ::boost::spirit::rule
< ScannerT
> additiveExpression
;
1137 ::boost::spirit::rule
< ScannerT
> multiplicativeExpression
;
1138 ::boost::spirit::rule
< ScannerT
> unaryExpression
;
1139 ::boost::spirit::rule
< ScannerT
> basicExpression
;
1140 ::boost::spirit::rule
< ScannerT
> unaryFunction
;
1141 ::boost::spirit::rule
< ScannerT
> binaryFunction
;
1142 ::boost::spirit::rule
< ScannerT
> ternaryFunction
;
1143 ::boost::spirit::rule
< ScannerT
> funcRef_decl
;
1144 ::boost::spirit::rule
< ScannerT
> functionReference
;
1145 ::boost::spirit::rule
< ScannerT
> modRef_decl
;
1146 ::boost::spirit::rule
< ScannerT
> modifierReference
;
1147 ::boost::spirit::rule
< ScannerT
> identifier
;
1150 const ParserContextSharedPtr
& getContext() const
1152 return mpParserContext
;
1156 ParserContextSharedPtr mpParserContext
; // might get modified during parsing
1159 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1160 const ParserContextSharedPtr
& getParserContext()
1162 static ParserContextSharedPtr
lcl_parserContext( new ParserContext() );
1164 // clear node stack (since we reuse the static object, that's
1165 // the whole point here)
1166 while( !lcl_parserContext
->maOperandStack
.empty() )
1167 lcl_parserContext
->maOperandStack
.pop();
1169 return lcl_parserContext
;
1175 namespace EnhancedCustomShape
{
1179 ExpressionNodeSharedPtr
FunctionParser::parseFunction( const OUString
& rFunction
, const EnhancedCustomShape2d
& rCustoShape
)
1181 // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1182 // gives better conversion robustness here (we might want to map space
1183 // etc. to ASCII space here)
1184 const OString
& rAsciiFunction(
1185 OUStringToOString( rFunction
, RTL_TEXTENCODING_ASCII_US
) );
1187 StringIteratorT
aStart( rAsciiFunction
.getStr() );
1188 StringIteratorT
aEnd( rAsciiFunction
.getStr()+rAsciiFunction
.getLength() );
1190 ParserContextSharedPtr pContext
;
1192 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1193 // static parser context, because the actual
1194 // Spirit parser is also a static object
1195 pContext
= getParserContext();
1197 pContext
.reset( new ParserContext() );
1199 pContext
->mpCustoShape
= &rCustoShape
;
1201 ExpressionGrammar
aExpressionGrammer( pContext
);
1202 const ::boost::spirit::parse_info
<StringIteratorT
> aParseInfo(
1203 ::boost::spirit::parse( aStart
,
1205 aExpressionGrammer
>> ::boost::spirit::end_p
,
1206 ::boost::spirit::space_p
) );
1207 OSL_DEBUG_ONLY(::std::cout
.flush()); // needed to keep stdout and cout in sync
1211 // input fully congested by the parser?
1212 if( !aParseInfo
.full
)
1213 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1215 // parser's state stack now must contain exactly _one_ ExpressionNode,
1216 // which represents our formula.
1217 if( pContext
->maOperandStack
.size() != 1 )
1218 throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1221 return pContext
->maOperandStack
.top();
1227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */