LCOV - code coverage report
Current view: top level - svx/source/customshapes - EnhancedCustomShapeFunctionParser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 187 511 36.6 %
Date: 2012-08-25 Functions: 70 88 79.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 450 1343 33.5 %

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

Generated by: LCOV version 1.10