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