xref: /trunk/main/svx/source/customshapes/EnhancedCustomShapeFunctionParser.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include "svx/EnhancedCustomShape2d.hxx"
31 #include <rtl/ustring.hxx>
32 #include <tools/fract.hxx>
33 
34 // Makes parser a static resource,
35 // we're synchronized externally.
36 // But watch out, the parser might have
37 // state not visible to this code!
38 
39 #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
40 #if defined(VERBOSE) && defined(DBG_UTIL)
41 #include <typeinfo>
42 #define BOOST_SPIRIT_DEBUG
43 #endif
44 #include <boost/spirit/include/classic_core.hpp>
45 
46 #if (OSL_DEBUG_LEVEL > 0)
47 #include <iostream>
48 #endif
49 #include <functional>
50 #include <algorithm>
51 #include <stack>
52 
53 #include <math.h> // fabs, sqrt, sin, cos, tan, atan, atan2
54 using namespace EnhancedCustomShape;
55 using namespace com::sun::star;
56 using namespace com::sun::star::drawing;
57 
58 void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
59 {
60     sal_Int32 nValue = 0;
61     if ( rSource.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
62     {
63         double fValue;
64         if ( rSource.Value >>= fValue )
65             nValue = (sal_Int32)fValue;
66     }
67     else
68         rSource.Value >>= nValue;
69 
70     switch( rSource.Type )
71     {
72         case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
73         {
74             if ( nValue & 0x40000000 )
75             {
76                 nValue ^= 0x40000000;
77                 rDest.nOperation |= 0x20000000 << nDestPara;    // the bit is indicating that this value has to be adjusted later
78             }
79             nValue |= 0x400;
80         }
81         break;
82         case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT : nValue += DFF_Prop_adjustValue; break;
83         case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM : nValue = DFF_Prop_geoBottom; break;
84         case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT : nValue = DFF_Prop_geoRight; break;
85         case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP : nValue = DFF_Prop_geoTop; break;
86         case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT : nValue = DFF_Prop_geoLeft; break;
87     }
88     if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
89         rDest.nOperation |= ( 0x2000 << nDestPara );
90     rDest.nPara[ nDestPara ] = nValue;
91 }
92 
93 ExpressionNode::~ExpressionNode()
94 {}
95 
96 namespace
97 {
98 
99 //////////////////////
100 //////////////////////
101 // EXPRESSION NODES
102 //////////////////////
103 //////////////////////
104 class ConstantValueExpression : public ExpressionNode
105 {
106     double  maValue;
107 
108 public:
109 
110     ConstantValueExpression( double rValue ) :
111         maValue( rValue )
112     {
113     }
114     virtual double operator()() const
115     {
116         return maValue;
117     }
118     virtual bool isConstant() const
119     {
120         return true;
121     }
122     virtual ExpressionFunct getType() const
123     {
124         return FUNC_CONST;
125     }
126     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ )
127     {
128         EnhancedCustomShapeParameter aRet;
129         Fraction aFract( maValue );
130         if ( aFract.GetDenominator() == 1 )
131         {
132             aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
133             aRet.Value <<= (sal_Int32)aFract.GetNumerator();
134         }
135         else
136         {
137             EnhancedCustomShapeEquation aEquation;
138             aEquation.nOperation = 1;
139             aEquation.nPara[ 0 ] = 1;
140             aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator();
141             aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator();
142             aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
143             aRet.Value <<= (sal_Int32)rEquations.size();
144             rEquations.push_back( aEquation );
145         }
146         return aRet;
147     }
148 };
149 
150 class AdjustmentExpression : public ExpressionNode
151 {
152     sal_Int32                       mnIndex;
153     const EnhancedCustomShape2d&    mrCustoShape;
154 
155 public:
156 
157     AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
158     : mnIndex       ( nIndex )
159     , mrCustoShape( rCustoShape )
160 
161     {
162     }
163     virtual double operator()() const
164     {
165         return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
166     }
167     virtual bool isConstant() const
168     {
169         return false;
170     }
171     virtual ExpressionFunct getType() const
172     {
173         return ENUM_FUNC_ADJUSTMENT;
174     }
175     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
176     {
177         EnhancedCustomShapeParameter aRet;
178         aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
179         aRet.Value <<= mnIndex;
180         return aRet;
181     }
182 };
183 
184 class EquationExpression : public ExpressionNode
185 {
186     sal_Int32                       mnIndex;
187     const EnhancedCustomShape2d&    mrCustoShape;
188 
189 public:
190 
191     EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
192         : mnIndex       ( nIndex )
193         , mrCustoShape( rCustoShape )
194     {
195     }
196     virtual double operator()() const
197     {
198         return mrCustoShape.GetEquationValueAsDouble( mnIndex );
199     }
200     virtual bool isConstant() const
201     {
202         return false;
203     }
204     virtual ExpressionFunct getType() const
205     {
206         return ENUM_FUNC_EQUATION;
207     }
208     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ )
209     {
210         EnhancedCustomShapeParameter aRet;
211         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
212         aRet.Value <<= mnIndex | 0x40000000;                        // the bit is indicating that this equation needs to be adjusted later
213         return aRet;
214     }
215 };
216 
217 class EnumValueExpression : public ExpressionNode
218 {
219     const ExpressionFunct           meFunct;
220     const EnhancedCustomShape2d&    mrCustoShape;
221 
222 public:
223 
224     EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
225         : meFunct       ( eFunct )
226         , mrCustoShape  ( rCustoShape )
227     {
228     }
229     static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc )
230     {
231         EnhancedCustomShape2d::EnumFunc eF;
232         switch( eFunc )
233         {
234             case ENUM_FUNC_PI :         eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break;
235             case ENUM_FUNC_LEFT :       eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break;
236             case ENUM_FUNC_TOP :        eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break;
237             case ENUM_FUNC_RIGHT :      eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break;
238             case ENUM_FUNC_BOTTOM :     eF = EnhancedCustomShape2d::ENUM_FUNC_BOTTOM; break;
239             case ENUM_FUNC_XSTRETCH :   eF = EnhancedCustomShape2d::ENUM_FUNC_XSTRETCH; break;
240             case ENUM_FUNC_YSTRETCH :   eF = EnhancedCustomShape2d::ENUM_FUNC_YSTRETCH; break;
241             case ENUM_FUNC_HASSTROKE :  eF = EnhancedCustomShape2d::ENUM_FUNC_HASSTROKE; break;
242             case ENUM_FUNC_HASFILL :    eF = EnhancedCustomShape2d::ENUM_FUNC_HASFILL; break;
243             case ENUM_FUNC_WIDTH :      eF = EnhancedCustomShape2d::ENUM_FUNC_WIDTH; break;
244             case ENUM_FUNC_HEIGHT :     eF = EnhancedCustomShape2d::ENUM_FUNC_HEIGHT; break;
245             case ENUM_FUNC_LOGWIDTH :   eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break;
246             case ENUM_FUNC_LOGHEIGHT :  eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break;
247 
248             default :
249                 return 0.0;
250         }
251         return rCustoShape.GetEnumFunc( eF );
252     }
253     virtual double operator()() const
254     {
255         return getValue( mrCustoShape, meFunct );
256     }
257     virtual bool isConstant() const
258     {
259         return false;
260     }
261     virtual ExpressionFunct getType() const
262     {
263         return meFunct;
264     }
265     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
266     {
267         EnhancedCustomShapeParameter aRet;
268 
269         sal_Int32 nDummy = 1;
270         aRet.Value <<= nDummy;
271 
272         switch( meFunct )
273         {
274             case ENUM_FUNC_WIDTH :  // TODO: do not use this as constant value
275             case ENUM_FUNC_HEIGHT :
276             case ENUM_FUNC_LOGWIDTH :
277             case ENUM_FUNC_LOGHEIGHT :
278             case ENUM_FUNC_PI :
279             {
280                 ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) );
281                 aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
282             }
283             break;
284             case ENUM_FUNC_LEFT :   aRet.Type = EnhancedCustomShapeParameterType::LEFT; break;
285             case ENUM_FUNC_TOP :    aRet.Type = EnhancedCustomShapeParameterType::TOP; break;
286             case ENUM_FUNC_RIGHT :  aRet.Type = EnhancedCustomShapeParameterType::RIGHT; break;
287             case ENUM_FUNC_BOTTOM : aRet.Type = EnhancedCustomShapeParameterType::BOTTOM; break;
288 
289             // not implemented so far
290             case ENUM_FUNC_XSTRETCH :
291             case ENUM_FUNC_YSTRETCH :
292             case ENUM_FUNC_HASSTROKE :
293             case ENUM_FUNC_HASFILL : aRet.Type = EnhancedCustomShapeParameterType::NORMAL; break;
294 
295             default:
296                 break;
297         }
298         return aRet;
299     }
300 };
301 
302 /** ExpressionNode implementation for unary
303     function over one ExpressionNode
304     */
305 class UnaryFunctionExpression : public ExpressionNode
306 {
307     const ExpressionFunct   meFunct;
308     ExpressionNodeSharedPtr mpArg;
309 
310 public:
311     UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) :
312         meFunct( eFunct ),
313         mpArg( rArg )
314     {
315     }
316     static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg )
317     {
318         double fRet = 0;
319         switch( eFunct )
320         {
321             case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break;
322             case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break;
323             case UNARY_FUNC_SIN : fRet = sin( (*rArg)() );  break;
324             case UNARY_FUNC_COS : fRet = cos( (*rArg)() );  break;
325             case UNARY_FUNC_TAN : fRet = tan( (*rArg)() );  break;
326             case UNARY_FUNC_ATAN: fRet = atan( (*rArg)() ); break;
327             case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break;
328             default:
329                 break;
330         }
331         return fRet;
332     }
333     virtual double operator()() const
334     {
335         return getValue( meFunct, mpArg );
336     }
337     virtual bool isConstant() const
338     {
339         return mpArg->isConstant();
340     }
341     virtual ExpressionFunct getType() const
342     {
343         return meFunct;
344     }
345     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags )
346     {
347         EnhancedCustomShapeParameter aRet;
348         switch( meFunct )
349         {
350             case UNARY_FUNC_ABS :
351             {
352                 EnhancedCustomShapeEquation aEquation;
353                 aEquation.nOperation |= 3;
354                 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
355                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
356                 aRet.Value <<= (sal_Int32)rEquations.size();
357                 rEquations.push_back( aEquation );
358             }
359             break;
360             case UNARY_FUNC_SQRT:
361             {
362                 EnhancedCustomShapeEquation aEquation;
363                 aEquation.nOperation |= 13;
364                 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
365                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
366                 aRet.Value <<= (sal_Int32)rEquations.size();
367                 rEquations.push_back( aEquation );
368             }
369             break;
370             case UNARY_FUNC_SIN :
371             {
372                 EnhancedCustomShapeEquation aEquation;
373                 aEquation.nOperation |= 9;
374                 if ( pOptionalArg )
375                     FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
376                 else
377                     aEquation.nPara[ 0 ] = 1;
378 
379                 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
380                 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
381                 {   // sumangle needed :-(
382                     EnhancedCustomShapeEquation _aEquation;
383                     _aEquation.nOperation |= 0xe;   // sumangle
384                     FillEquationParameter( aSource, 1, _aEquation );
385                     aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
386                     aSource.Value <<= (sal_Int32)rEquations.size();
387                     rEquations.push_back( _aEquation );
388                 }
389                 FillEquationParameter( aSource, 1, aEquation );
390                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
391                 aRet.Value <<= (sal_Int32)rEquations.size();
392                 rEquations.push_back( aEquation );
393             }
394             break;
395             case UNARY_FUNC_COS :
396             {
397                 EnhancedCustomShapeEquation aEquation;
398                 aEquation.nOperation |= 10;
399                 if ( pOptionalArg )
400                     FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
401                 else
402                     aEquation.nPara[ 0 ] = 1;
403 
404                 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
405                 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
406                 {   // sumangle needed :-(
407                     EnhancedCustomShapeEquation aTmpEquation;
408                     aTmpEquation.nOperation |= 0xe; // sumangle
409                     FillEquationParameter( aSource, 1, aTmpEquation );
410                     aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
411                     aSource.Value <<= (sal_Int32)rEquations.size();
412                     rEquations.push_back( aTmpEquation );
413                 }
414                 FillEquationParameter( aSource, 1, aEquation );
415                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
416                 aRet.Value <<= (sal_Int32)rEquations.size();
417                 rEquations.push_back( aEquation );
418             }
419             break;
420             case UNARY_FUNC_TAN :
421             {
422                 EnhancedCustomShapeEquation aEquation;
423                 aEquation.nOperation |= 16;
424                 if ( pOptionalArg )
425                     FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
426                 else
427                     aEquation.nPara[ 0 ] = 1;
428 
429                 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
430                 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
431                 {   // sumangle needed :-(
432                     EnhancedCustomShapeEquation aTmpEquation;
433                     aTmpEquation.nOperation |= 0xe; // sumangle
434                     FillEquationParameter( aSource, 1, aTmpEquation );
435                     aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
436                     aSource.Value <<= (sal_Int32)rEquations.size();
437                     rEquations.push_back( aTmpEquation );
438                 }
439                 FillEquationParameter( aSource, 1, aEquation );
440                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
441                 aRet.Value <<= (sal_Int32)rEquations.size();
442                 rEquations.push_back( aEquation );
443             }
444             break;
445             case UNARY_FUNC_ATAN:
446             {
447 // TODO:
448                 aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
449             }
450             break;
451             case UNARY_FUNC_NEG:
452             {
453                 EnhancedCustomShapeEquation aEquation;
454                 aEquation.nOperation |= 1;
455                 aEquation.nPara[ 1 ] = -1;
456                 aEquation.nPara[ 2 ] = 1;
457                 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
458                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
459                 aRet.Value <<= (sal_Int32)rEquations.size();
460                 rEquations.push_back( aEquation );
461             }
462             break;
463             default:
464                 break;
465         }
466         return aRet;
467     }
468 };
469 
470 /** ExpressionNode implementation for unary
471     function over two ExpressionNodes
472     */
473 class BinaryFunctionExpression : public ExpressionNode
474 {
475     const ExpressionFunct   meFunct;
476     ExpressionNodeSharedPtr mpFirstArg;
477     ExpressionNodeSharedPtr mpSecondArg;
478 
479 public:
480 
481     BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) :
482         meFunct( eFunct ),
483         mpFirstArg( rFirstArg ),
484         mpSecondArg( rSecondArg )
485     {
486     }
487     static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg )
488     {
489         double fRet = 0;
490         switch( eFunct )
491         {
492             case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
493             case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
494             case BINARY_FUNC_MUL :  fRet = (*rFirstArg)() * (*rSecondArg)(); break;
495             case BINARY_FUNC_DIV :  fRet = (*rFirstArg)() / (*rSecondArg)(); break;
496             case BINARY_FUNC_MIN :  fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
497             case BINARY_FUNC_MAX :  fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
498             case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
499             default:
500                 break;
501         }
502         return fRet;
503     }
504     virtual double operator()() const
505     {
506         return getValue( meFunct, mpFirstArg, mpSecondArg );
507     }
508     virtual bool isConstant() const
509     {
510         return mpFirstArg->isConstant() && mpSecondArg->isConstant();
511     }
512     virtual ExpressionFunct getType() const
513     {
514         return meFunct;
515     }
516     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
517     {
518         EnhancedCustomShapeParameter aRet;
519         switch( meFunct )
520         {
521             case BINARY_FUNC_PLUS :
522             {
523                 if ( nFlags & EXPRESSION_FLAG_SUMANGLE_MODE )
524                 {
525                     if ( mpFirstArg->getType() == ENUM_FUNC_ADJUSTMENT )
526                     {
527                         EnhancedCustomShapeEquation aEquation;
528                         aEquation.nOperation |= 0xe;    // sumangle
529                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
530                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
531                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
532                         aRet.Value <<= (sal_Int32)rEquations.size();
533                         rEquations.push_back( aEquation );
534                     }
535                     else if ( mpSecondArg->getType() == ENUM_FUNC_ADJUSTMENT )
536                     {
537                         EnhancedCustomShapeEquation aEquation;
538                         aEquation.nOperation |= 0xe;    // sumangle
539                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
540                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
541                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
542                         aRet.Value <<= (sal_Int32)rEquations.size();
543                         rEquations.push_back( aEquation );
544                     }
545                     else
546                     {
547                         EnhancedCustomShapeEquation aSumangle1;
548                         aSumangle1.nOperation |= 0xe;   // sumangle
549                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle1 );
550                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
551                         aRet.Value <<= (sal_Int32)rEquations.size();
552                         rEquations.push_back( aSumangle1 );
553 
554                         EnhancedCustomShapeEquation aSumangle2;
555                         aSumangle2.nOperation |= 0xe;   // sumangle
556                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags &~EXPRESSION_FLAG_SUMANGLE_MODE ), 1, aSumangle2 );
557                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
558                         aRet.Value <<= (sal_Int32)rEquations.size();
559                         rEquations.push_back( aSumangle2 );
560 
561                         EnhancedCustomShapeEquation aEquation;
562                         aEquation.nOperation |= 0;
563                         aEquation.nPara[ 0 ] = ( rEquations.size() - 2 ) | 0x400;
564                         aEquation.nPara[ 1 ] = ( rEquations.size() - 1 ) | 0x400;
565                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
566                         aRet.Value <<= (sal_Int32)rEquations.size();
567                         rEquations.push_back( aEquation );
568                     }
569                 }
570                 else
571                 {
572                     sal_Bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
573                     sal_Bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
574 
575                     if ( bFirstIsEmpty )
576                         aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
577                     else if ( bSecondIsEmpty )
578                         aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
579                     else
580                     {
581                         EnhancedCustomShapeEquation aEquation;
582                         aEquation.nOperation |= 0;
583                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
584                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
585                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
586                         aRet.Value <<= (sal_Int32)rEquations.size();
587                         rEquations.push_back( aEquation );
588                     }
589                 }
590             }
591             break;
592             case BINARY_FUNC_MINUS:
593             {
594                 EnhancedCustomShapeEquation aEquation;
595                 aEquation.nOperation |= 0;
596                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
597                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
598                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
599                 aRet.Value <<= (sal_Int32)rEquations.size();
600                 rEquations.push_back( aEquation );
601             }
602             break;
603             case BINARY_FUNC_MUL :
604             {
605                 // in the dest. format the cos function is using integer as result :-(
606                 // so we can't use the generic algorithm
607                 if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) )
608                     aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
609                 else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
610                     aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
611                 else
612                 {
613                     if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
614                         aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
615                     else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
616                         aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
617                     else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV )      // don't care of (pi/180)
618                         && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI )
619                         && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpFirstArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) )
620                     {
621                         aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
622                     }
623                     else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV )     // don't care of (pi/180)
624                         && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpFirstArg.get())->getType() == ENUM_FUNC_PI )
625                         && ( ((BinaryFunctionExpression*)((BinaryFunctionExpression*)mpSecondArg.get())->mpSecondArg.get())->getType() == FUNC_CONST ) )
626                     {
627                         aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
628                     }
629                     else
630                     {
631                         EnhancedCustomShapeEquation aEquation;
632                         aEquation.nOperation |= 1;
633                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
634                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
635                         aEquation.nPara[ 2 ] = 1;
636                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
637                         aRet.Value <<= (sal_Int32)rEquations.size();
638                         rEquations.push_back( aEquation );
639                     }
640                 }
641             }
642             break;
643             case BINARY_FUNC_DIV :
644             {
645                 EnhancedCustomShapeEquation aEquation;
646                 aEquation.nOperation |= 1;
647                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
648                 aEquation.nPara[ 1 ] = 1;
649                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
650                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
651                 aRet.Value <<= (sal_Int32)rEquations.size();
652                 rEquations.push_back( aEquation );
653             }
654             break;
655             case BINARY_FUNC_MIN :
656             {
657                 EnhancedCustomShapeEquation aEquation;
658                 aEquation.nOperation |= 4;
659                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
660                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
661                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
662                 aRet.Value <<= (sal_Int32)rEquations.size();
663                 rEquations.push_back( aEquation );
664             }
665             break;
666             case BINARY_FUNC_MAX :
667             {
668                 EnhancedCustomShapeEquation aEquation;
669                 aEquation.nOperation |= 5;
670                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
671                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
672                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
673                 aRet.Value <<= (sal_Int32)rEquations.size();
674                 rEquations.push_back( aEquation );
675             }
676             break;
677             case BINARY_FUNC_ATAN2:
678             {
679                 EnhancedCustomShapeEquation aEquation;
680                 aEquation.nOperation |= 8;
681                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
682                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
683                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
684                 aRet.Value <<= (sal_Int32)rEquations.size();
685                 rEquations.push_back( aEquation );
686             }
687             break;
688             default:
689                 break;
690         }
691         return aRet;
692     }
693 };
694 
695 class IfExpression : public ExpressionNode
696 {
697     ExpressionNodeSharedPtr mpFirstArg;
698     ExpressionNodeSharedPtr mpSecondArg;
699     ExpressionNodeSharedPtr mpThirdArg;
700 
701 public:
702 
703     IfExpression( const ExpressionNodeSharedPtr& rFirstArg,
704                   const ExpressionNodeSharedPtr& rSecondArg,
705                   const ExpressionNodeSharedPtr& rThirdArg ) :
706         mpFirstArg(  rFirstArg ),
707         mpSecondArg( rSecondArg ),
708         mpThirdArg(  rThirdArg )
709     {
710     }
711     virtual bool isConstant() const
712     {
713         return
714             mpFirstArg->isConstant() &&
715             mpSecondArg->isConstant() &&
716             mpThirdArg->isConstant();
717     }
718     virtual double operator()() const
719     {
720         return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
721     }
722     virtual ExpressionFunct getType() const
723     {
724         return TERNARY_FUNC_IF;
725     }
726     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags )
727     {
728         EnhancedCustomShapeParameter aRet;
729         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
730         aRet.Value <<= (sal_Int32)rEquations.size();
731         {
732             EnhancedCustomShapeEquation aEquation;
733             aEquation.nOperation |= 6;
734             FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
735             FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags  ), 1, aEquation );
736             FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
737             rEquations.push_back( aEquation );
738         }
739         return aRet;
740     }
741 };
742 
743 ////////////////////////
744 ////////////////////////
745 // FUNCTION PARSER
746 ////////////////////////
747 ////////////////////////
748 
749 typedef const sal_Char* StringIteratorT;
750 
751 struct ParserContext
752 {
753     typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack;
754 
755     // stores a stack of not-yet-evaluated operands. This is used
756     // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
757     // arguments from. If all arguments to an operator are constant,
758     // the operator pushes a precalculated result on the stack, and
759     // a composite ExpressionNode otherwise.
760     OperandStack                maOperandStack;
761 
762     const EnhancedCustomShape2d* mpCustoShape;
763 
764 };
765 
766 typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr;
767 
768 /** Generate apriori constant value
769     */
770 
771 class ConstantFunctor
772 {
773     const double                    mnValue;
774     ParserContextSharedPtr          mpContext;
775 
776 public:
777 
778     ConstantFunctor( double rValue, const ParserContextSharedPtr& rContext ) :
779         mnValue( rValue ),
780         mpContext( rContext )
781     {
782     }
783     void operator()( StringIteratorT /*rFirst*/, StringIteratorT /*rSecond*/ ) const
784     {
785         mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( mnValue ) ) );
786     }
787 };
788 
789 /** Generate parse-dependent-but-then-constant value
790     */
791 class DoubleConstantFunctor
792 {
793     ParserContextSharedPtr  mpContext;
794 
795 public:
796     DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
797         mpContext( rContext )
798     {
799     }
800     void operator()( double n ) const
801     {
802         mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) );
803     }
804 };
805 
806 class EnumFunctor
807 {
808     const ExpressionFunct           meFunct;
809     double                          mnValue;
810     ParserContextSharedPtr          mpContext;
811 
812 public:
813 
814     EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
815     : meFunct( eFunct )
816     , mnValue( 0 )
817     , mpContext( rContext )
818     {
819     }
820     void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
821     {
822         /*double nVal = mnValue;*/
823         switch( meFunct )
824         {
825             case ENUM_FUNC_ADJUSTMENT :
826             {
827                 rtl::OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
828                 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
829             }
830             break;
831             case ENUM_FUNC_EQUATION :
832                 {
833                 rtl::OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
834                 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
835             }
836             break;
837             default:
838                 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext->mpCustoShape, meFunct ) ) );
839         }
840     }
841 };
842 
843 class UnaryFunctionFunctor
844 {
845     const ExpressionFunct   meFunct;
846     ParserContextSharedPtr  mpContext;
847 
848 public :
849 
850     UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
851         meFunct( eFunct ),
852         mpContext( rContext )
853     {
854     }
855     void operator()( StringIteratorT, StringIteratorT ) const
856     {
857         ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
858 
859         if( rNodeStack.size() < 1 )
860             throw ParseError( "Not enough arguments for unary operator" );
861 
862         // retrieve arguments
863         ExpressionNodeSharedPtr pArg( rNodeStack.top() );
864         rNodeStack.pop();
865 
866         if( pArg->isConstant() )    // check for constness
867             rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) );
868         else                        // push complex node, that calcs the value on demand
869             rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) );
870     }
871 };
872 
873 /** Implements a binary function over two ExpressionNodes
874 
875     @tpl Generator
876     Generator functor, to generate an ExpressionNode of
877     appropriate type
878 
879     */
880 class BinaryFunctionFunctor
881 {
882     const ExpressionFunct   meFunct;
883     ParserContextSharedPtr  mpContext;
884 
885 public:
886 
887     BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
888         meFunct( eFunct ),
889         mpContext( rContext )
890     {
891     }
892 
893     void operator()( StringIteratorT, StringIteratorT ) const
894     {
895         ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
896 
897         if( rNodeStack.size() < 2 )
898             throw ParseError( "Not enough arguments for binary operator" );
899 
900         // retrieve arguments
901         ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
902         rNodeStack.pop();
903         ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
904         rNodeStack.pop();
905 
906         // create combined ExpressionNode
907         ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) );
908         // check for constness
909         if( pFirstArg->isConstant() && pSecondArg->isConstant() )   // call the operator() at pNode, store result in constant value ExpressionNode.
910             rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );
911         else                                                        // push complex node, that calcs the value on demand
912             rNodeStack.push( pNode );
913     }
914 };
915 
916 class IfFunctor
917 {
918     ParserContextSharedPtr  mpContext;
919 
920 public :
921 
922     IfFunctor( const ParserContextSharedPtr& rContext ) :
923         mpContext( rContext )
924     {
925     }
926     void operator()( StringIteratorT, StringIteratorT ) const
927     {
928         ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
929 
930         if( rNodeStack.size() < 3 )
931             throw ParseError( "Not enough arguments for ternary operator" );
932 
933         // retrieve arguments
934         ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() );
935         rNodeStack.pop();
936         ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
937         rNodeStack.pop();
938         ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
939         rNodeStack.pop();
940 
941         // create combined ExpressionNode
942         ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) );
943         // check for constness
944         if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() )
945             rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );    // call the operator() at pNode, store result in constant value ExpressionNode.
946         else
947             rNodeStack.push( pNode );                                       // push complex node, that calcs the value on demand
948     }
949 };
950 
951 // Workaround for MSVC compiler anomaly (stack trashing)
952 //
953 // The default ureal_parser_policies implementation of parse_exp
954 // triggers a really weird error in MSVC7 (Version 13.00.9466), in
955 // that the real_parser_impl::parse_main() call of parse_exp()
956 // overwrites the frame pointer _on the stack_ (EBP of the calling
957 // function gets overwritten while lying on the stack).
958 //
959 // For the time being, our parser thus can only read the 1.0E10
960 // notation, not the 1.0e10 one.
961 //
962 // TODO(F1): Also handle the 1.0e10 case here.
963 template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T>
964 {
965     template< typename ScannerT >
966         static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type
967     parse_exp(ScannerT& scan)
968     {
969         // as_lower_d somehow breaks MSVC7
970         return ::boost::spirit::ch_p('E').parse(scan);
971     }
972 };
973 
974 /* This class implements the following grammar (more or
975     less literally written down below, only slightly
976     obfuscated by the parser actions):
977 
978     identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
979 
980     function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
981 
982     basic_expression =
983                     number |
984                     identifier |
985                     function '(' additive_expression ')' |
986                     '(' additive_expression ')'
987 
988     unary_expression =
989                     '-' basic_expression |
990                     basic_expression
991 
992     multiplicative_expression =
993                     unary_expression ( ( '*' unary_expression )* |
994                                         ( '/' unary_expression )* )
995 
996     additive_expression =
997                     multiplicative_expression ( ( '+' multiplicative_expression )* |
998                                                 ( '-' multiplicative_expression )* )
999 
1000     */
1001 
1002 class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar >
1003 {
1004 public:
1005     /** Create an arithmetic expression grammar
1006 
1007         @param rParserContext
1008         Contains context info for the parser
1009         */
1010     ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
1011         mpParserContext( rParserContext )
1012     {
1013     }
1014 
1015     template< typename ScannerT > class definition
1016     {
1017     public:
1018         // grammar definition
1019         definition( const ExpressionGrammar& self )
1020         {
1021             using ::boost::spirit::str_p;
1022             using ::boost::spirit::range_p;
1023             using ::boost::spirit::lexeme_d;
1024             using ::boost::spirit::real_parser;
1025             using ::boost::spirit::chseq_p;
1026 
1027             identifier =
1028                             str_p( "pi"         )[ EnumFunctor(ENUM_FUNC_PI,        self.getContext() ) ]
1029                     |       str_p( "left"       )[ EnumFunctor(ENUM_FUNC_LEFT,      self.getContext() ) ]
1030                     |       str_p( "top"        )[ EnumFunctor(ENUM_FUNC_TOP,       self.getContext() ) ]
1031                     |       str_p( "right"      )[ EnumFunctor(ENUM_FUNC_RIGHT,     self.getContext() ) ]
1032                     |       str_p( "bottom"     )[ EnumFunctor(ENUM_FUNC_BOTTOM,    self.getContext() ) ]
1033                     |       str_p( "xstretch"   )[ EnumFunctor(ENUM_FUNC_XSTRETCH,  self.getContext() ) ]
1034                     |       str_p( "ystretch"   )[ EnumFunctor(ENUM_FUNC_YSTRETCH,  self.getContext() ) ]
1035                     |       str_p( "hasstroke"  )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ]
1036                     |       str_p( "hasfill"    )[ EnumFunctor(ENUM_FUNC_HASFILL,   self.getContext() ) ]
1037                     |       str_p( "width"      )[ EnumFunctor(ENUM_FUNC_WIDTH,     self.getContext() ) ]
1038                     |       str_p( "height"     )[ EnumFunctor(ENUM_FUNC_HEIGHT,    self.getContext() ) ]
1039                     |       str_p( "logwidth"   )[ EnumFunctor(ENUM_FUNC_LOGWIDTH,  self.getContext() ) ]
1040                     |       str_p( "logheight"  )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ]
1041                     ;
1042 
1043             unaryFunction =
1044                     (str_p( "abs"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS,  self.getContext()) ]
1045                 |   (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ]
1046                 |   (str_p( "sin"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN,  self.getContext()) ]
1047                 |   (str_p( "cos"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS,  self.getContext()) ]
1048                 |   (str_p( "tan"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN,  self.getContext()) ]
1049                 |   (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ]
1050                 ;
1051 
1052             binaryFunction =
1053                     (str_p( "min"  ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN,  self.getContext()) ]
1054                 |   (str_p( "max"  ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX,  self.getContext()) ]
1055                 |   (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ]
1056                 ;
1057 
1058             ternaryFunction =
1059                     (str_p( "if"  ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
1060                 ;
1061 
1062             funcRef_decl =
1063                 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1064 
1065             functionReference =
1066                 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ];
1067 
1068             modRef_decl =
1069                 lexeme_d[ +( range_p('0','9') ) ];
1070 
1071             modifierReference =
1072                 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ];
1073 
1074             basicExpression =
1075                     real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
1076                 |   identifier
1077                 |   functionReference
1078                 |   modifierReference
1079                 |   unaryFunction
1080                 |   binaryFunction
1081                 |   ternaryFunction
1082                 |   '(' >> additiveExpression >> ')'
1083                 ;
1084 
1085             unaryExpression =
1086                     ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ]
1087                 |   basicExpression
1088                 ;
1089 
1090             multiplicativeExpression =
1091                     unaryExpression
1092                 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ]
1093                     | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ]
1094                     )
1095                 ;
1096 
1097             additiveExpression =
1098                     multiplicativeExpression
1099                 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS,  self.getContext()) ]
1100                     | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS, self.getContext()) ]
1101                     )
1102                 ;
1103 
1104             BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
1105             BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
1106             BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
1107             BOOST_SPIRIT_DEBUG_RULE(basicExpression);
1108             BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
1109             BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
1110             BOOST_SPIRIT_DEBUG_RULE(ternaryFunction);
1111             BOOST_SPIRIT_DEBUG_RULE(identifier);
1112         }
1113 
1114         const ::boost::spirit::rule< ScannerT >& start() const
1115         {
1116             return additiveExpression;
1117         }
1118 
1119     private:
1120         // the constituents of the Spirit arithmetic expression grammar.
1121         // For the sake of readability, without 'ma' prefix.
1122         ::boost::spirit::rule< ScannerT >   additiveExpression;
1123         ::boost::spirit::rule< ScannerT >   multiplicativeExpression;
1124         ::boost::spirit::rule< ScannerT >   unaryExpression;
1125         ::boost::spirit::rule< ScannerT >   basicExpression;
1126         ::boost::spirit::rule< ScannerT >   unaryFunction;
1127         ::boost::spirit::rule< ScannerT >   binaryFunction;
1128         ::boost::spirit::rule< ScannerT >   ternaryFunction;
1129         ::boost::spirit::rule< ScannerT >   funcRef_decl;
1130         ::boost::spirit::rule< ScannerT >   functionReference;
1131         ::boost::spirit::rule< ScannerT >   modRef_decl;
1132         ::boost::spirit::rule< ScannerT >   modifierReference;
1133         ::boost::spirit::rule< ScannerT >   identifier;
1134     };
1135 
1136     const ParserContextSharedPtr& getContext() const
1137     {
1138         return mpParserContext;
1139     }
1140 
1141 private:
1142     ParserContextSharedPtr          mpParserContext; // might get modified during parsing
1143 };
1144 
1145 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1146 const ParserContextSharedPtr& getParserContext()
1147 {
1148     static ParserContextSharedPtr lcl_parserContext( new ParserContext() );
1149 
1150     // clear node stack (since we reuse the static object, that's
1151     // the whole point here)
1152     while( !lcl_parserContext->maOperandStack.empty() )
1153         lcl_parserContext->maOperandStack.pop();
1154 
1155     return lcl_parserContext;
1156 }
1157 #endif
1158 
1159 }
1160 
1161 namespace EnhancedCustomShape  {
1162 
1163 
1164 
1165 ExpressionNodeSharedPtr FunctionParser::parseFunction( const ::rtl::OUString& rFunction, const EnhancedCustomShape2d& rCustoShape )
1166 {
1167     // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
1168     // gives better conversion robustness here (we might want to map space
1169     // etc. to ASCII space here)
1170     const ::rtl::OString& rAsciiFunction(
1171         rtl::OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
1172 
1173     StringIteratorT aStart( rAsciiFunction.getStr() );
1174     StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() );
1175 
1176     ParserContextSharedPtr pContext;
1177 
1178 #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1179     // static parser context, because the actual
1180     // Spirit parser is also a static object
1181     pContext = getParserContext();
1182 #else
1183     pContext.reset( new ParserContext() );
1184 #endif
1185     pContext->mpCustoShape = &rCustoShape;
1186 
1187     ExpressionGrammar aExpressionGrammer( pContext );
1188     const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
1189             ::boost::spirit::parse( aStart,
1190                                     aEnd,
1191                                     aExpressionGrammer >> ::boost::spirit::end_p,
1192                                     ::boost::spirit::space_p ) );
1193     OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync
1194 
1195 
1196 
1197     // input fully congested by the parser?
1198     if( !aParseInfo.full )
1199         throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
1200 
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" );
1205 
1206 
1207     return pContext->maOperandStack.top();
1208 }
1209 
1210 
1211 }
1212 
1213