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