LCOV - code coverage report
Current view: top level - libreoffice/svx/source/customshapes - EnhancedCustomShapeFunctionParser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 189 511 37.0 %
Date: 2012-12-27 Functions: 70 88 79.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10