LCOV - code coverage report
Current view: top level - svx/source/customshapes - EnhancedCustomShapeFunctionParser.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 422 545 77.4 %
Date: 2014-11-03 Functions: 85 88 96.6 %
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>
      44             : using namespace EnhancedCustomShape;
      45             : using namespace com::sun::star;
      46             : using namespace com::sun::star::drawing;
      47             : 
      48       14614 : void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
      49             : {
      50       14614 :     sal_Int32 nValue = 0;
      51       14614 :     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       14614 :         rSource.Value >>= nValue;
      59             : 
      60       14614 :     switch( rSource.Type )
      61             :     {
      62             :         case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
      63             :         {
      64        4964 :             if ( nValue & 0x40000000 )
      65             :             {
      66        2474 :                 nValue ^= 0x40000000;
      67        2474 :                 rDest.nOperation |= 0x20000000 << nDestPara;    // the bit is indicating that this value has to be adjusted later
      68             :             }
      69        4964 :             nValue |= 0x400;
      70             :         }
      71        4964 :         break;
      72         768 :         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       14614 :     if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
      79        5732 :         rDest.nOperation |= ( 0x2000 << nDestPara );
      80       14614 :     rDest.nPara[ nDestPara ] = nValue;
      81       14614 : }
      82             : 
      83     1204508 : ExpressionNode::~ExpressionNode()
      84     1204508 : {}
      85             : 
      86             : namespace
      87             : {
      88             : 
      89             : 
      90             : 
      91             : // EXPRESSION NODES
      92             : 
      93             : 
      94      942184 : class ConstantValueExpression : public ExpressionNode
      95             : {
      96             :     double  maValue;
      97             : 
      98             : public:
      99             : 
     100      472808 :     ConstantValueExpression( double rValue ) :
     101      472808 :         maValue( rValue )
     102             :     {
     103      472808 :     }
     104      209854 :     virtual double operator()() const SAL_OVERRIDE
     105             :     {
     106      209854 :         return maValue;
     107             :     }
     108      293270 :     virtual bool isConstant() const SAL_OVERRIDE
     109             :     {
     110      293270 :         return true;
     111             :     }
     112        3032 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     113             :     {
     114        3032 :         return FUNC_CONST;
     115             :     }
     116        8980 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) SAL_OVERRIDE
     117             :     {
     118        8980 :         EnhancedCustomShapeParameter aRet;
     119        8980 :         Fraction aFract( maValue );
     120        8980 :         if ( aFract.GetDenominator() == 1 )
     121             :         {
     122        8882 :             aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
     123        8882 :             aRet.Value <<= (sal_Int32)aFract.GetNumerator();
     124             :         }
     125             :         else
     126             :         {
     127          98 :             EnhancedCustomShapeEquation aEquation;
     128          98 :             aEquation.nOperation = 1;
     129          98 :             aEquation.nPara[ 0 ] = 1;
     130          98 :             aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator();
     131          98 :             aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator();
     132          98 :             aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     133          98 :             aRet.Value <<= (sal_Int32)rEquations.size();
     134          98 :             rEquations.push_back( aEquation );
     135             :         }
     136        8980 :         return aRet;
     137             :     }
     138             : };
     139             : 
     140       58372 : class AdjustmentExpression : public ExpressionNode
     141             : {
     142             :     sal_Int32                       mnIndex;
     143             :     const EnhancedCustomShape2d&    mrCustoShape;
     144             : 
     145             : public:
     146             : 
     147       29186 :     AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
     148             :     : mnIndex       ( nIndex )
     149       29186 :     , mrCustoShape( rCustoShape )
     150             : 
     151             :     {
     152       29186 :     }
     153       12724 :     virtual double operator()() const SAL_OVERRIDE
     154             :     {
     155             :         OSL_TRACE("  $%d --> %f (angle: %f)", mnIndex, mrCustoShape.GetAdjustValueAsDouble( mnIndex ), 180.0*mrCustoShape.GetAdjustValueAsDouble( mnIndex )/10800000.0);
     156       12724 :         return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
     157             :     }
     158       34638 :     virtual bool isConstant() const SAL_OVERRIDE
     159             :     {
     160       34638 :         return false;
     161             :     }
     162         112 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     163             :     {
     164         112 :         return ENUM_FUNC_ADJUSTMENT;
     165             :     }
     166         768 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) SAL_OVERRIDE
     167             :     {
     168         768 :         EnhancedCustomShapeParameter aRet;
     169         768 :         aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
     170         768 :         aRet.Value <<= mnIndex;
     171         768 :         return aRet;
     172             :     }
     173             : };
     174             : 
     175      203744 : class EquationExpression : public ExpressionNode
     176             : {
     177             :     sal_Int32                       mnIndex;
     178             :     const EnhancedCustomShape2d&    mrCustoShape;
     179             : 
     180             : public:
     181             : 
     182      101872 :     EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
     183             :         : mnIndex       ( nIndex )
     184      101872 :         , mrCustoShape( rCustoShape )
     185             :     {
     186      101872 :     }
     187       25140 :     virtual double operator()() const SAL_OVERRIDE
     188             :     {
     189       25140 :         return mrCustoShape.GetEquationValueAsDouble( mnIndex );
     190             :     }
     191       79866 :     virtual bool isConstant() const SAL_OVERRIDE
     192             :     {
     193       79866 :         return false;
     194             :     }
     195        3126 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     196             :     {
     197        3126 :         return ENUM_FUNC_EQUATION;
     198             :     }
     199        2474 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) SAL_OVERRIDE
     200             :     {
     201        2474 :         EnhancedCustomShapeParameter aRet;
     202        2474 :         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     203        2474 :         aRet.Value <<= mnIndex | 0x40000000;                        // the bit is indicating that this equation needs to be adjusted later
     204        2474 :         return aRet;
     205             :     }
     206             : };
     207             : 
     208      330008 : class EnumValueExpression : public ExpressionNode
     209             : {
     210             :     const ExpressionFunct           meFunct;
     211             :     const EnhancedCustomShape2d&    mrCustoShape;
     212             : 
     213             : public:
     214             : 
     215      165004 :     EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
     216             :         : meFunct       ( eFunct )
     217      165004 :         , mrCustoShape  ( rCustoShape )
     218             :     {
     219      165004 :     }
     220       38912 :     static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc )
     221             :     {
     222             :         EnhancedCustomShape2d::EnumFunc eF;
     223       38912 :         switch( eFunc )
     224             :         {
     225        1902 :             case ENUM_FUNC_PI :         eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break;
     226          14 :             case ENUM_FUNC_LEFT :       eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break;
     227          14 :             case ENUM_FUNC_TOP :        eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break;
     228          24 :             case ENUM_FUNC_RIGHT :      eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break;
     229          24 :             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       18352 :             case ENUM_FUNC_LOGWIDTH :   eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break;
     237       18582 :             case ENUM_FUNC_LOGHEIGHT :  eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break;
     238             : 
     239             :             default :
     240           0 :                 return 0.0;
     241             :         }
     242       38912 :         return rCustoShape.GetEnumFunc( eF );
     243             :     }
     244       35480 :     virtual double operator()() const SAL_OVERRIDE
     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       35480 :         return getValue( mrCustoShape, meFunct );
     270             :     }
     271      242670 :     virtual bool isConstant() const SAL_OVERRIDE
     272             :     {
     273      242670 :         return false;
     274             :     }
     275        1216 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     276             :     {
     277        1216 :         return meFunct;
     278             :     }
     279        3432 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
     280             :     {
     281        3432 :         EnhancedCustomShapeParameter aRet;
     282             : 
     283        3432 :         sal_Int32 nDummy = 1;
     284        3432 :         aRet.Value <<= nDummy;
     285             : 
     286        3432 :         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        3432 :                 ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) );
     295        3432 :                 aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
     296             :             }
     297        3432 :             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        3432 :         return aRet;
     313             :     }
     314             : };
     315             : 
     316             : /** ExpressionNode implementation for unary
     317             :     function over one ExpressionNode
     318             :     */
     319       61592 : class UnaryFunctionExpression : public ExpressionNode
     320             : {
     321             :     const ExpressionFunct   meFunct;
     322             :     ExpressionNodeSharedPtr mpArg;
     323             : 
     324             : public:
     325       30796 :     UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) :
     326             :         meFunct( eFunct ),
     327       30796 :         mpArg( rArg )
     328             :     {
     329       30796 :     }
     330        2826 :     static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg )
     331             :     {
     332        2826 :         double fRet = 0;
     333        2826 :         switch( eFunct )
     334             :         {
     335          50 :             case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break;
     336          24 :             case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break;
     337         942 :             case UNARY_FUNC_SIN : fRet = sin( (*rArg)() );  break;
     338         926 :             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         884 :             case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break;
     342             :             default:
     343           0 :                 break;
     344             :         }
     345        2826 :         return fRet;
     346             :     }
     347        2198 :     virtual double operator()() const SAL_OVERRIDE
     348             :     {
     349        2198 :         return getValue( meFunct, mpArg );
     350             :     }
     351       52298 :     virtual bool isConstant() const SAL_OVERRIDE
     352             :     {
     353       52298 :         return mpArg->isConstant();
     354             :     }
     355         566 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     356             :     {
     357         566 :         return meFunct;
     358             :     }
     359         460 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags ) SAL_OVERRIDE
     360             :     {
     361         460 :         EnhancedCustomShapeParameter aRet;
     362         460 :         switch( meFunct )
     363             :         {
     364             :             case UNARY_FUNC_ABS :
     365             :             {
     366          14 :                 EnhancedCustomShapeEquation aEquation;
     367          14 :                 aEquation.nOperation |= 3;
     368          14 :                 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     369          14 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     370          14 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     371          14 :                 rEquations.push_back( aEquation );
     372             :             }
     373          14 :             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         190 :                 EnhancedCustomShapeEquation aEquation;
     387         190 :                 aEquation.nOperation |= 9;
     388         190 :                 if ( pOptionalArg )
     389         190 :                     FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     390             :                 else
     391           0 :                     aEquation.nPara[ 0 ] = 1;
     392             : 
     393         190 :                 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
     394         190 :                 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
     395             :                 {   // sumangle needed :-(
     396         136 :                     EnhancedCustomShapeEquation _aEquation;
     397         136 :                     _aEquation.nOperation |= 0xe;   // sumangle
     398         136 :                     FillEquationParameter( aSource, 1, _aEquation );
     399         136 :                     aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
     400         136 :                     aSource.Value <<= (sal_Int32)rEquations.size();
     401         136 :                     rEquations.push_back( _aEquation );
     402             :                 }
     403         190 :                 FillEquationParameter( aSource, 1, aEquation );
     404         190 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     405         190 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     406         190 :                 rEquations.push_back( aEquation );
     407             :             }
     408         190 :             break;
     409             :             case UNARY_FUNC_COS :
     410             :             {
     411         188 :                 EnhancedCustomShapeEquation aEquation;
     412         188 :                 aEquation.nOperation |= 10;
     413         188 :                 if ( pOptionalArg )
     414         188 :                     FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     415             :                 else
     416           0 :                     aEquation.nPara[ 0 ] = 1;
     417             : 
     418         188 :                 EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
     419         188 :                 if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
     420             :                 {   // sumangle needed :-(
     421         136 :                     EnhancedCustomShapeEquation aTmpEquation;
     422         136 :                     aTmpEquation.nOperation |= 0xe; // sumangle
     423         136 :                     FillEquationParameter( aSource, 1, aTmpEquation );
     424         136 :                     aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
     425         136 :                     aSource.Value <<= (sal_Int32)rEquations.size();
     426         136 :                     rEquations.push_back( aTmpEquation );
     427             :                 }
     428         188 :                 FillEquationParameter( aSource, 1, aEquation );
     429         188 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     430         188 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     431         188 :                 rEquations.push_back( aEquation );
     432             :             }
     433         188 :             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          68 :                 EnhancedCustomShapeEquation aEquation;
     468          68 :                 aEquation.nOperation |= 1;
     469          68 :                 aEquation.nPara[ 1 ] = -1;
     470          68 :                 aEquation.nPara[ 2 ] = 1;
     471          68 :                 FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     472          68 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     473          68 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     474          68 :                 rEquations.push_back( aEquation );
     475             :             }
     476          68 :             break;
     477             :             default:
     478           0 :                 break;
     479             :         }
     480         460 :         return aRet;
     481             :     }
     482             : };
     483             : 
     484             : /** ExpressionNode implementation for unary
     485             :     function over two ExpressionNodes
     486             :     */
     487      771760 : class BinaryFunctionExpression : public ExpressionNode
     488             : {
     489             :     const ExpressionFunct   meFunct;
     490             :     ExpressionNodeSharedPtr mpFirstArg;
     491             :     ExpressionNodeSharedPtr mpSecondArg;
     492             : 
     493             : public:
     494             : 
     495      385880 :     BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) :
     496             :         meFunct( eFunct ),
     497             :         mpFirstArg( rFirstArg ),
     498      385880 :         mpSecondArg( rSecondArg )
     499             :     {
     500      385880 :     }
     501      136746 :     static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg )
     502             :     {
     503      136746 :         double fRet = 0;
     504      136746 :         switch( eFunct )
     505             :         {
     506       10110 :             case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
     507       32866 :             case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
     508       11614 :             case BINARY_FUNC_MUL :  fRet = (*rFirstArg)() * (*rSecondArg)(); break;
     509       78566 :             case BINARY_FUNC_DIV :  fRet = (*rFirstArg)() / (*rSecondArg)(); break;
     510        3526 :             case BINARY_FUNC_MIN :  fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
     511           0 :             case BINARY_FUNC_MAX :  fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
     512          64 :             case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
     513             :             default:
     514           0 :                 break;
     515             :         }
     516      136746 :         return fRet;
     517             :     }
     518      136746 :     virtual double operator()() const SAL_OVERRIDE
     519             :     {
     520      136746 :         return getValue( meFunct, mpFirstArg, mpSecondArg );
     521             :     }
     522      291932 :     virtual bool isConstant() const SAL_OVERRIDE
     523             :     {
     524      291932 :         return mpFirstArg->isConstant() && mpSecondArg->isConstant();
     525             :     }
     526        1120 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     527             :     {
     528        1120 :         return meFunct;
     529             :     }
     530        6156 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
     531             :     {
     532        6156 :         EnhancedCustomShapeParameter aRet;
     533        6156 :         switch( meFunct )
     534             :         {
     535             :             case BINARY_FUNC_PLUS :
     536             :             {
     537        1226 :                 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        1226 :                     bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
     587        1226 :                     bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
     588             : 
     589        1226 :                     if ( bFirstIsEmpty )
     590           6 :                         aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
     591        1220 :                     else if ( bSecondIsEmpty )
     592         840 :                         aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
     593             :                     else
     594             :                     {
     595         380 :                         EnhancedCustomShapeEquation aEquation;
     596         380 :                         aEquation.nOperation |= 0;
     597         380 :                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     598         380 :                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
     599         380 :                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     600         380 :                         aRet.Value <<= (sal_Int32)rEquations.size();
     601         380 :                         rEquations.push_back( aEquation );
     602             :                     }
     603             :                 }
     604             :             }
     605        1226 :             break;
     606             :             case BINARY_FUNC_MINUS:
     607             :             {
     608        1652 :                 EnhancedCustomShapeEquation aEquation;
     609        1652 :                 aEquation.nOperation |= 0;
     610        1652 :                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     611        1652 :                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
     612        1652 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     613        1652 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     614        1652 :                 rEquations.push_back( aEquation );
     615             :             }
     616        1652 :             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        1344 :                 if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) )
     622         272 :                     aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
     623        1072 :                 else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
     624         106 :                     aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
     625             :                 else
     626             :                 {
     627         966 :                     if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
     628           0 :                         aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
     629         966 :                     else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
     630           0 :                         aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
     631        1932 :                     else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV )      // don't care of (pi/180)
     632           0 :                         && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpFirstArg.get()->getType() == ENUM_FUNC_PI )
     633         966 :                         && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpSecondArg.get()->getType() == FUNC_CONST ) )
     634             :                     {
     635           0 :                         aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
     636             :                     }
     637        1932 :                     else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV )     // don't care of (pi/180)
     638         280 :                         && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpFirstArg.get()->getType() == ENUM_FUNC_PI )
     639        1246 :                         && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpSecondArg.get()->getType() == FUNC_CONST ) )
     640             :                     {
     641         280 :                         aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
     642             :                     }
     643             :                     else
     644             :                     {
     645         686 :                         EnhancedCustomShapeEquation aEquation;
     646         686 :                         aEquation.nOperation |= 1;
     647         686 :                         FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     648         686 :                         FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
     649         686 :                         aEquation.nPara[ 2 ] = 1;
     650         686 :                         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     651         686 :                         aRet.Value <<= (sal_Int32)rEquations.size();
     652         686 :                         rEquations.push_back( aEquation );
     653             :                     }
     654             :                 }
     655             :             }
     656        1344 :             break;
     657             :             case BINARY_FUNC_DIV :
     658             :             {
     659        1748 :                 EnhancedCustomShapeEquation aEquation;
     660        1748 :                 aEquation.nOperation |= 1;
     661        1748 :                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     662        1748 :                 aEquation.nPara[ 1 ] = 1;
     663        1748 :                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
     664        1748 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     665        1748 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     666        1748 :                 rEquations.push_back( aEquation );
     667             :             }
     668        1748 :             break;
     669             :             case BINARY_FUNC_MIN :
     670             :             {
     671         186 :                 EnhancedCustomShapeEquation aEquation;
     672         186 :                 aEquation.nOperation |= 4;
     673         186 :                 FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     674         186 :                 FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
     675         186 :                 aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     676         186 :                 aRet.Value <<= (sal_Int32)rEquations.size();
     677         186 :                 rEquations.push_back( aEquation );
     678             :             }
     679         186 :             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        6156 :         return aRet;
     706             :     }
     707             : };
     708             : 
     709       37924 : class IfExpression : public ExpressionNode
     710             : {
     711             :     ExpressionNodeSharedPtr mpFirstArg;
     712             :     ExpressionNodeSharedPtr mpSecondArg;
     713             :     ExpressionNodeSharedPtr mpThirdArg;
     714             : 
     715             : public:
     716             : 
     717       18962 :     IfExpression( const ExpressionNodeSharedPtr& rFirstArg,
     718             :                   const ExpressionNodeSharedPtr& rSecondArg,
     719             :                   const ExpressionNodeSharedPtr& rThirdArg ) :
     720             :         mpFirstArg(  rFirstArg ),
     721             :         mpSecondArg( rSecondArg ),
     722       18962 :         mpThirdArg(  rThirdArg )
     723             :     {
     724       18962 :     }
     725           0 :     virtual bool isConstant() const SAL_OVERRIDE
     726             :     {
     727             :         return
     728           0 :             mpFirstArg->isConstant() &&
     729           0 :             mpSecondArg->isConstant() &&
     730           0 :             mpThirdArg->isConstant();
     731             :     }
     732        8196 :     virtual double operator()() const SAL_OVERRIDE
     733             :     {
     734        8196 :         return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
     735             :     }
     736           0 :     virtual ExpressionFunct getType() const SAL_OVERRIDE
     737             :     {
     738           0 :         return TERNARY_FUNC_IF;
     739             :     }
     740         498 :     virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
     741             :     {
     742         498 :         EnhancedCustomShapeParameter aRet;
     743         498 :         aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
     744         498 :         aRet.Value <<= (sal_Int32)rEquations.size();
     745             :         {
     746         498 :             EnhancedCustomShapeEquation aEquation;
     747         498 :             aEquation.nOperation |= 6;
     748         498 :             FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
     749         498 :             FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags  ), 1, aEquation );
     750         498 :             FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
     751         498 :             rEquations.push_back( aEquation );
     752             :         }
     753         498 :         return aRet;
     754             :     }
     755             : };
     756             : 
     757             : 
     758             : 
     759             : // FUNCTION PARSER
     760             : 
     761             : 
     762             : 
     763             : typedef const sal_Char* StringIteratorT;
     764             : 
     765          60 : 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 parse-dependent-but-then-constant value
     783             :     */
     784         570 : class DoubleConstantFunctor
     785             : {
     786             :     ParserContextSharedPtr  mpContext;
     787             : 
     788             : public:
     789          30 :     DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
     790          30 :         mpContext( rContext )
     791             :     {
     792          30 :     }
     793      387590 :     void operator()( double n ) const
     794             :     {
     795      387590 :         mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) );
     796      387590 :     }
     797             : };
     798             : 
     799        7650 : class EnumFunctor
     800             : {
     801             :     const ExpressionFunct           meFunct;
     802             :     double                          mnValue;
     803             :     ParserContextSharedPtr          mpContext;
     804             : 
     805             : public:
     806             : 
     807         450 :     EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
     808             :     : meFunct( eFunct )
     809             :     , mnValue( 0 )
     810         450 :     , mpContext( rContext )
     811             :     {
     812         450 :     }
     813      296062 :     void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
     814             :     {
     815             :         /*double nVal = mnValue;*/
     816      296062 :         switch( meFunct )
     817             :         {
     818             :             case ENUM_FUNC_ADJUSTMENT :
     819             :             {
     820       29186 :                 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
     821       29186 :                 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
     822             :             }
     823       29186 :             break;
     824             :             case ENUM_FUNC_EQUATION :
     825             :                 {
     826      101872 :                 OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
     827      101872 :                 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
     828             :             }
     829      101872 :             break;
     830             :             default:
     831      165004 :                 mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext->mpCustoShape, meFunct ) ) );
     832             :         }
     833      296062 :     }
     834             : };
     835             : 
     836        2310 : class UnaryFunctionFunctor
     837             : {
     838             :     const ExpressionFunct   meFunct;
     839             :     ParserContextSharedPtr  mpContext;
     840             : 
     841             : public :
     842             : 
     843         210 :     UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
     844             :         meFunct( eFunct ),
     845         210 :         mpContext( rContext )
     846             :     {
     847         210 :     }
     848       31424 :     void operator()( StringIteratorT, StringIteratorT ) const
     849             :     {
     850       31424 :         ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
     851             : 
     852       31424 :         if( rNodeStack.size() < 1 )
     853           0 :             throw ParseError( "Not enough arguments for unary operator" );
     854             : 
     855             :         // retrieve arguments
     856       31424 :         ExpressionNodeSharedPtr pArg( rNodeStack.top() );
     857       31424 :         rNodeStack.pop();
     858             : 
     859       31424 :         if( pArg->isConstant() )    // check for constness
     860         628 :             rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) );
     861             :         else                        // push complex node, that calcs the value on demand
     862       30796 :             rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) );
     863       31424 :     }
     864             : };
     865             : 
     866             : /** Implements a binary function over two ExpressionNodes
     867             : 
     868             :     @tpl Generator
     869             :     Generator functor, to generate an ExpressionNode of
     870             :     appropriate type
     871             : 
     872             :     */
     873        2070 : class BinaryFunctionFunctor
     874             : {
     875             :     const ExpressionFunct   meFunct;
     876             :     ParserContextSharedPtr  mpContext;
     877             : 
     878             : public:
     879             : 
     880         210 :     BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
     881             :         meFunct( eFunct ),
     882         210 :         mpContext( rContext )
     883             :     {
     884         210 :     }
     885             : 
     886      385880 :     void operator()( StringIteratorT, StringIteratorT ) const
     887             :     {
     888      385880 :         ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
     889             : 
     890      385880 :         if( rNodeStack.size() < 2 )
     891           0 :             throw ParseError( "Not enough arguments for binary operator" );
     892             : 
     893             :         // retrieve arguments
     894      385880 :         ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
     895      385880 :         rNodeStack.pop();
     896      771760 :         ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
     897      385880 :         rNodeStack.pop();
     898             : 
     899             :         // create combined ExpressionNode
     900      771760 :         ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) );
     901             :         // check for constness
     902      385880 :         if( pFirstArg->isConstant() && pSecondArg->isConstant() )   // call the operator() at pNode, store result in constant value ExpressionNode.
     903       81158 :             rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );
     904             :         else                                                        // push complex node, that calcs the value on demand
     905      690602 :             rNodeStack.push( pNode );
     906      385880 :     }
     907             : };
     908             : 
     909         150 : class IfFunctor
     910             : {
     911             :     ParserContextSharedPtr  mpContext;
     912             : 
     913             : public :
     914             : 
     915          30 :     IfFunctor( const ParserContextSharedPtr& rContext ) :
     916          30 :         mpContext( rContext )
     917             :     {
     918          30 :     }
     919       18962 :     void operator()( StringIteratorT, StringIteratorT ) const
     920             :     {
     921       18962 :         ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
     922             : 
     923       18962 :         if( rNodeStack.size() < 3 )
     924           0 :             throw ParseError( "Not enough arguments for ternary operator" );
     925             : 
     926             :         // retrieve arguments
     927       18962 :         ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() );
     928       18962 :         rNodeStack.pop();
     929       37924 :         ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
     930       18962 :         rNodeStack.pop();
     931       37924 :         ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
     932       18962 :         rNodeStack.pop();
     933             : 
     934             :         // create combined ExpressionNode
     935       37924 :         ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) );
     936             :         // check for constness
     937       18962 :         if( pFirstArg->isConstant() && pSecondArg->isConstant() && pThirdArg->isConstant() )
     938           0 :             rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );    // call the operator() at pNode, store result in constant value ExpressionNode.
     939             :         else
     940       37924 :             rNodeStack.push( pNode );                                       // push complex node, that calcs the value on demand
     941       18962 :     }
     942             : };
     943             : 
     944             : // Workaround for MSVC compiler anomaly (stack trashing)
     945             : 
     946             : // The default ureal_parser_policies implementation of parse_exp
     947             : // triggers a really weird error in MSVC7 (Version 13.00.9466), in
     948             : // that the real_parser_impl::parse_main() call of parse_exp()
     949             : // overwrites the frame pointer _on the stack_ (EBP of the calling
     950             : // function gets overwritten while lying on the stack).
     951             : 
     952             : // For the time being, our parser thus can only read the 1.0E10
     953             : // notation, not the 1.0e10 one.
     954             : 
     955             : // TODO(F1): Also handle the 1.0e10 case here.
     956             : template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T>
     957             : {
     958             :     template< typename ScannerT >
     959             :         static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type
     960      387590 :     parse_exp(ScannerT& scan)
     961             :     {
     962             :         // as_lower_d somehow breaks MSVC7
     963      387590 :         return ::boost::spirit::ch_p('E').parse(scan);
     964             :     }
     965             : };
     966             : 
     967             : /* This class implements the following grammar (more or
     968             :     less literally written down below, only slightly
     969             :     obfuscated by the parser actions):
     970             : 
     971             :     identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
     972             : 
     973             :     function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
     974             : 
     975             :     basic_expression =
     976             :                        number |
     977             :                        identifier |
     978             :                        function '(' additive_expression ')' |
     979             :                        '(' additive_expression ')'
     980             : 
     981             :     unary_expression =
     982             :                        '-' basic_expression |
     983             :                     basic_expression
     984             : 
     985             :     multiplicative_expression =
     986             :                        unary_expression ( ( '*' unary_expression )* |
     987             :                                         ( '/' unary_expression )* )
     988             : 
     989             :     additive_expression =
     990             :                        multiplicative_expression ( ( '+' multiplicative_expression )* |
     991             :                                                    ( '-' multiplicative_expression )* )
     992             : 
     993             :     */
     994             : 
     995      259848 : class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar >
     996             : {
     997             : public:
     998             :     /** Create an arithmetic expression grammar
     999             : 
    1000             :         @param rParserContext
    1001             :         Contains context info for the parser
    1002             :         */
    1003      259848 :     ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
    1004      259848 :         mpParserContext( rParserContext )
    1005             :     {
    1006      259848 :     }
    1007             : 
    1008          30 :     template< typename ScannerT > class definition
    1009             :     {
    1010             :     public:
    1011             :         // grammar definition
    1012          30 :         definition( const ExpressionGrammar& self )
    1013          30 :         {
    1014             :             using ::boost::spirit::str_p;
    1015             :             using ::boost::spirit::range_p;
    1016             :             using ::boost::spirit::lexeme_d;
    1017             :             using ::boost::spirit::real_parser;
    1018             :             using ::boost::spirit::chseq_p;
    1019             : 
    1020         390 :             identifier =
    1021          30 :                             str_p( "pi"         )[ EnumFunctor(ENUM_FUNC_PI,        self.getContext() ) ]
    1022          30 :                     |       str_p( "left"       )[ EnumFunctor(ENUM_FUNC_LEFT,      self.getContext() ) ]
    1023          30 :                     |       str_p( "top"        )[ EnumFunctor(ENUM_FUNC_TOP,       self.getContext() ) ]
    1024          30 :                     |       str_p( "right"      )[ EnumFunctor(ENUM_FUNC_RIGHT,     self.getContext() ) ]
    1025          30 :                     |       str_p( "bottom"     )[ EnumFunctor(ENUM_FUNC_BOTTOM,    self.getContext() ) ]
    1026          30 :                     |       str_p( "xstretch"   )[ EnumFunctor(ENUM_FUNC_XSTRETCH,  self.getContext() ) ]
    1027          30 :                     |       str_p( "ystretch"   )[ EnumFunctor(ENUM_FUNC_YSTRETCH,  self.getContext() ) ]
    1028          30 :                     |       str_p( "hasstroke"  )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ]
    1029          30 :                     |       str_p( "hasfill"    )[ EnumFunctor(ENUM_FUNC_HASFILL,   self.getContext() ) ]
    1030          30 :                     |       str_p( "width"      )[ EnumFunctor(ENUM_FUNC_WIDTH,     self.getContext() ) ]
    1031          30 :                     |       str_p( "height"     )[ EnumFunctor(ENUM_FUNC_HEIGHT,    self.getContext() ) ]
    1032          30 :                     |       str_p( "logwidth"   )[ EnumFunctor(ENUM_FUNC_LOGWIDTH,  self.getContext() ) ]
    1033          30 :                     |       str_p( "logheight"  )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ]
    1034             :                     ;
    1035             : 
    1036         540 :             unaryFunction =
    1037          90 :                     (str_p( "abs"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS,  self.getContext()) ]
    1038          90 :                 |   (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ]
    1039          90 :                 |   (str_p( "sin"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN,  self.getContext()) ]
    1040          90 :                 |   (str_p( "cos"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS,  self.getContext()) ]
    1041          90 :                 |   (str_p( "tan"  ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN,  self.getContext()) ]
    1042          90 :                 |   (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ]
    1043             :                 ;
    1044             : 
    1045         270 :             binaryFunction =
    1046          90 :                     (str_p( "min"  ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN,  self.getContext()) ]
    1047          90 :                 |   (str_p( "max"  ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX,  self.getContext()) ]
    1048          90 :                 |   (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ]
    1049             :                 ;
    1050             : 
    1051          90 :             ternaryFunction =
    1052          90 :                     (str_p( "if"  ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
    1053             :                 ;
    1054             : 
    1055          30 :             funcRef_decl =
    1056          60 :                 lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
    1057             : 
    1058          90 :             functionReference =
    1059          90 :                 (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ];
    1060             : 
    1061          30 :             modRef_decl =
    1062             :                 lexeme_d[ +( range_p('0','9') ) ];
    1063             : 
    1064          90 :             modifierReference =
    1065          90 :                 (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ];
    1066             : 
    1067          60 :             basicExpression =
    1068          30 :                     real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
    1069             :                 |   identifier
    1070             :                 |   functionReference
    1071             :                 |   modifierReference
    1072             :                 |   unaryFunction
    1073             :                 |   binaryFunction
    1074             :                 |   ternaryFunction
    1075          60 :                 |   '(' >> additiveExpression >> ')'
    1076             :                 ;
    1077             : 
    1078          90 :             unaryExpression =
    1079          60 :                     ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ]
    1080             :                 |   basicExpression
    1081             :                 ;
    1082             : 
    1083         120 :             multiplicativeExpression =
    1084             :                     unaryExpression
    1085          60 :                 >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ]
    1086          60 :                     | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ]
    1087             :                     )
    1088             :                 ;
    1089             : 
    1090         120 :             additiveExpression =
    1091             :                     multiplicativeExpression
    1092          60 :                 >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS,  self.getContext()) ]
    1093          60 :                     | ('-' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MINUS, self.getContext()) ]
    1094             :                     )
    1095             :                 ;
    1096             : 
    1097             :             BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
    1098             :             BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
    1099             :             BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
    1100             :             BOOST_SPIRIT_DEBUG_RULE(basicExpression);
    1101             :             BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
    1102             :             BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
    1103             :             BOOST_SPIRIT_DEBUG_RULE(ternaryFunction);
    1104             :             BOOST_SPIRIT_DEBUG_RULE(identifier);
    1105          30 :         }
    1106             : 
    1107      259848 :         const ::boost::spirit::rule< ScannerT >& start() const
    1108             :         {
    1109      259848 :             return additiveExpression;
    1110             :         }
    1111             : 
    1112             :     private:
    1113             :         // the constituents of the Spirit arithmetic expression grammar.
    1114             :         // For the sake of readability, without 'ma' prefix.
    1115             :         ::boost::spirit::rule< ScannerT >   additiveExpression;
    1116             :         ::boost::spirit::rule< ScannerT >   multiplicativeExpression;
    1117             :         ::boost::spirit::rule< ScannerT >   unaryExpression;
    1118             :         ::boost::spirit::rule< ScannerT >   basicExpression;
    1119             :         ::boost::spirit::rule< ScannerT >   unaryFunction;
    1120             :         ::boost::spirit::rule< ScannerT >   binaryFunction;
    1121             :         ::boost::spirit::rule< ScannerT >   ternaryFunction;
    1122             :         ::boost::spirit::rule< ScannerT >   funcRef_decl;
    1123             :         ::boost::spirit::rule< ScannerT >   functionReference;
    1124             :         ::boost::spirit::rule< ScannerT >   modRef_decl;
    1125             :         ::boost::spirit::rule< ScannerT >   modifierReference;
    1126             :         ::boost::spirit::rule< ScannerT >   identifier;
    1127             :     };
    1128             : 
    1129         930 :     const ParserContextSharedPtr& getContext() const
    1130             :     {
    1131         930 :         return mpParserContext;
    1132             :     }
    1133             : 
    1134             : private:
    1135             :     ParserContextSharedPtr          mpParserContext; // might get modified during parsing
    1136             : };
    1137             : 
    1138             : #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
    1139      259848 : const ParserContextSharedPtr& getParserContext()
    1140             : {
    1141      259848 :     static ParserContextSharedPtr lcl_parserContext( new ParserContext() );
    1142             : 
    1143             :     // clear node stack (since we reuse the static object, that's
    1144             :     // the whole point here)
    1145      779514 :     while( !lcl_parserContext->maOperandStack.empty() )
    1146      259818 :         lcl_parserContext->maOperandStack.pop();
    1147             : 
    1148      259848 :     return lcl_parserContext;
    1149             : }
    1150             : #endif
    1151             : 
    1152             : }
    1153             : 
    1154             : namespace EnhancedCustomShape  {
    1155             : 
    1156             : 
    1157             : 
    1158      259848 : ExpressionNodeSharedPtr FunctionParser::parseFunction( const OUString& rFunction, const EnhancedCustomShape2d& rCustoShape )
    1159             : {
    1160             :     // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
    1161             :     // gives better conversion robustness here (we might want to map space
    1162             :     // etc. to ASCII space here)
    1163             :     const OString& rAsciiFunction(
    1164      259848 :         OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
    1165             : 
    1166      259848 :     StringIteratorT aStart( rAsciiFunction.getStr() );
    1167      259848 :     StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() );
    1168             : 
    1169      519696 :     ParserContextSharedPtr pContext;
    1170             : 
    1171             : #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
    1172             :     // static parser context, because the actual
    1173             :     // Spirit parser is also a static object
    1174      259848 :     pContext = getParserContext();
    1175             : #else
    1176             :     pContext.reset( new ParserContext() );
    1177             : #endif
    1178      259848 :     pContext->mpCustoShape = &rCustoShape;
    1179             : 
    1180      519696 :     ExpressionGrammar aExpressionGrammer( pContext );
    1181             :     const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
    1182             :             ::boost::spirit::parse( aStart,
    1183             :                                     aEnd,
    1184      519696 :                                     aExpressionGrammer >> ::boost::spirit::end_p,
    1185      259848 :                                     ::boost::spirit::space_p ) );
    1186             : 
    1187             : #if (OSL_DEBUG_LEVEL > 0)
    1188             :     ::std::cout.flush(); // needed to keep stdout and cout in sync
    1189             : #endif
    1190             : 
    1191             :     // input fully congested by the parser?
    1192      259848 :     if( !aParseInfo.full )
    1193           0 :         throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): string not fully parseable" );
    1194             : 
    1195             :     // parser's state stack now must contain exactly _one_ ExpressionNode,
    1196             :     // which represents our formula.
    1197      259848 :     if( pContext->maOperandStack.size() != 1 )
    1198           0 :         throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
    1199             : 
    1200             : 
    1201      519696 :     return pContext->maOperandStack.top();
    1202             : }
    1203             : 
    1204             : 
    1205         651 : }
    1206             : 
    1207             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10