LCOV - code coverage report
Current view: top level - svx/source/customshapes - EnhancedCustomShapeFunctionParser.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 395 545 72.5 %
Date: 2014-04-11 Functions: 84 88 95.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10