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

Generated by: LCOV version 1.11