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_slideshow.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir // must be first 32*cdf0e10cSrcweir #include <canvas/debug.hxx> 33*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir #include <rtl/math.hxx> 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir #include <smilfunctionparser.hxx> 38*cdf0e10cSrcweir #include <expressionnodefactory.hxx> 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir #include <rtl/ustring.hxx> 41*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx> 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 44*cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir // Makes parser a static resource, 47*cdf0e10cSrcweir // we're synchronized externally. 48*cdf0e10cSrcweir // But watch out, the parser might have 49*cdf0e10cSrcweir // state not visible to this code! 50*cdf0e10cSrcweir #define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 51*cdf0e10cSrcweir #if defined(VERBOSE) && defined(DBG_UTIL) 52*cdf0e10cSrcweir #include <typeinfo> 53*cdf0e10cSrcweir #define BOOST_SPIRIT_DEBUG 54*cdf0e10cSrcweir #endif 55*cdf0e10cSrcweir #include <boost/spirit/include/classic_core.hpp> 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 58*cdf0e10cSrcweir #include <iostream> 59*cdf0e10cSrcweir #endif 60*cdf0e10cSrcweir #include <functional> 61*cdf0e10cSrcweir #include <algorithm> 62*cdf0e10cSrcweir #include <stack> 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir /* Implementation of SmilFunctionParser class */ 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir namespace slideshow 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir namespace internal 71*cdf0e10cSrcweir { 72*cdf0e10cSrcweir namespace 73*cdf0e10cSrcweir { 74*cdf0e10cSrcweir typedef const sal_Char* StringIteratorT; 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir struct ParserContext 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack; 79*cdf0e10cSrcweir 80*cdf0e10cSrcweir // stores a stack of not-yet-evaluated operands. This is used 81*cdf0e10cSrcweir // by the operators (i.e. '+', '*', 'sin' etc.) to pop their 82*cdf0e10cSrcweir // arguments from. If all arguments to an operator are constant, 83*cdf0e10cSrcweir // the operator pushes a precalculated result on the stack, and 84*cdf0e10cSrcweir // a composite ExpressionNode otherwise. 85*cdf0e10cSrcweir OperandStack maOperandStack; 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir // bounds of the shape this expression is associated with 88*cdf0e10cSrcweir ::basegfx::B2DRectangle maShapeBounds; 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir // when true, enable usage of time-dependent variable '$' 91*cdf0e10cSrcweir // in expressions 92*cdf0e10cSrcweir bool mbParseAnimationFunction; 93*cdf0e10cSrcweir }; 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr; 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir template< typename Generator > class ShapeBoundsFunctor 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir public: 101*cdf0e10cSrcweir ShapeBoundsFunctor( Generator aGenerator, 102*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) : 103*cdf0e10cSrcweir maGenerator( aGenerator ), 104*cdf0e10cSrcweir mpContext( rContext ) 105*cdf0e10cSrcweir { 106*cdf0e10cSrcweir ENSURE_OR_THROW( mpContext, 107*cdf0e10cSrcweir "ShapeBoundsFunctor::ShapeBoundsFunctor(): Invalid context" ); 108*cdf0e10cSrcweir } 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir void operator()( StringIteratorT, StringIteratorT ) const 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir mpContext->maOperandStack.push( 113*cdf0e10cSrcweir ExpressionNodeFactory::createConstantValueExpression( 114*cdf0e10cSrcweir maGenerator( mpContext->maShapeBounds ) ) ); 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir private: 118*cdf0e10cSrcweir Generator maGenerator; 119*cdf0e10cSrcweir ParserContextSharedPtr mpContext; 120*cdf0e10cSrcweir }; 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir template< typename Generator > ShapeBoundsFunctor< Generator > 123*cdf0e10cSrcweir makeShapeBoundsFunctor( const Generator& rGenerator, 124*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir return ShapeBoundsFunctor<Generator>(rGenerator, rContext); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir /** Generate apriori constant value 130*cdf0e10cSrcweir */ 131*cdf0e10cSrcweir class ConstantFunctor 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir public: 134*cdf0e10cSrcweir ConstantFunctor( double rValue, 135*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) : 136*cdf0e10cSrcweir mnValue( rValue ), 137*cdf0e10cSrcweir mpContext( rContext ) 138*cdf0e10cSrcweir { 139*cdf0e10cSrcweir ENSURE_OR_THROW( mpContext, 140*cdf0e10cSrcweir "ConstantFunctor::ConstantFunctor(): Invalid context" ); 141*cdf0e10cSrcweir } 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir void operator()( StringIteratorT, StringIteratorT ) const 144*cdf0e10cSrcweir { 145*cdf0e10cSrcweir mpContext->maOperandStack.push( 146*cdf0e10cSrcweir ExpressionNodeFactory::createConstantValueExpression( mnValue ) ); 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir private: 150*cdf0e10cSrcweir const double mnValue; 151*cdf0e10cSrcweir ParserContextSharedPtr mpContext; 152*cdf0e10cSrcweir }; 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir /** Generate parse-dependent-but-then-constant value 155*cdf0e10cSrcweir */ 156*cdf0e10cSrcweir class DoubleConstantFunctor 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir public: 159*cdf0e10cSrcweir DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) : 160*cdf0e10cSrcweir mpContext( rContext ) 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir ENSURE_OR_THROW( mpContext, 163*cdf0e10cSrcweir "DoubleConstantFunctor::DoubleConstantFunctor(): Invalid context" ); 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir void operator()( double n ) const 167*cdf0e10cSrcweir { 168*cdf0e10cSrcweir // push constant value expression to the stack 169*cdf0e10cSrcweir mpContext->maOperandStack.push( 170*cdf0e10cSrcweir ExpressionNodeFactory::createConstantValueExpression( n ) ); 171*cdf0e10cSrcweir } 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir private: 174*cdf0e10cSrcweir ParserContextSharedPtr mpContext; 175*cdf0e10cSrcweir }; 176*cdf0e10cSrcweir 177*cdf0e10cSrcweir /** Generate special t value expression node 178*cdf0e10cSrcweir */ 179*cdf0e10cSrcweir class ValueTFunctor 180*cdf0e10cSrcweir { 181*cdf0e10cSrcweir public: 182*cdf0e10cSrcweir ValueTFunctor( const ParserContextSharedPtr& rContext ) : 183*cdf0e10cSrcweir mpContext( rContext ) 184*cdf0e10cSrcweir { 185*cdf0e10cSrcweir ENSURE_OR_THROW( mpContext, 186*cdf0e10cSrcweir "ValueTFunctor::ValueTFunctor(): Invalid context" ); 187*cdf0e10cSrcweir } 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir void operator()( StringIteratorT, StringIteratorT ) const 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir if( !mpContext->mbParseAnimationFunction ) 192*cdf0e10cSrcweir { 193*cdf0e10cSrcweir OSL_ENSURE( false, 194*cdf0e10cSrcweir "ValueTFunctor::operator(): variable encountered, but we're not parsing a function here" ); 195*cdf0e10cSrcweir throw ParseError(); 196*cdf0e10cSrcweir } 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir // push special t value expression to the stack 199*cdf0e10cSrcweir mpContext->maOperandStack.push( 200*cdf0e10cSrcweir ExpressionNodeFactory::createValueTExpression() ); 201*cdf0e10cSrcweir } 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir private: 204*cdf0e10cSrcweir ParserContextSharedPtr mpContext; 205*cdf0e10cSrcweir }; 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir template< typename Functor > class UnaryFunctionFunctor 208*cdf0e10cSrcweir { 209*cdf0e10cSrcweir private: 210*cdf0e10cSrcweir /** ExpressionNode implementation for unary 211*cdf0e10cSrcweir function over one ExpressionNode 212*cdf0e10cSrcweir */ 213*cdf0e10cSrcweir class UnaryFunctionExpression : public ExpressionNode 214*cdf0e10cSrcweir { 215*cdf0e10cSrcweir public: 216*cdf0e10cSrcweir UnaryFunctionExpression( const Functor& rFunctor, 217*cdf0e10cSrcweir const ExpressionNodeSharedPtr& rArg ) : 218*cdf0e10cSrcweir maFunctor( rFunctor ), 219*cdf0e10cSrcweir mpArg( rArg ) 220*cdf0e10cSrcweir { 221*cdf0e10cSrcweir } 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir virtual double operator()( double t ) const 224*cdf0e10cSrcweir { 225*cdf0e10cSrcweir return maFunctor( (*mpArg)(t) ); 226*cdf0e10cSrcweir } 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir virtual bool isConstant() const 229*cdf0e10cSrcweir { 230*cdf0e10cSrcweir return mpArg->isConstant(); 231*cdf0e10cSrcweir } 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir private: 234*cdf0e10cSrcweir Functor maFunctor; 235*cdf0e10cSrcweir ExpressionNodeSharedPtr mpArg; 236*cdf0e10cSrcweir }; 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir public: 239*cdf0e10cSrcweir UnaryFunctionFunctor( const Functor& rFunctor, 240*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) : 241*cdf0e10cSrcweir maFunctor( rFunctor ), 242*cdf0e10cSrcweir mpContext( rContext ) 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir ENSURE_OR_THROW( mpContext, 245*cdf0e10cSrcweir "UnaryFunctionFunctor::UnaryFunctionFunctor(): Invalid context" ); 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir void operator()( StringIteratorT, StringIteratorT ) const 249*cdf0e10cSrcweir { 250*cdf0e10cSrcweir ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir if( rNodeStack.size() < 1 ) 253*cdf0e10cSrcweir throw ParseError( "Not enough arguments for unary operator" ); 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir // retrieve arguments 256*cdf0e10cSrcweir ExpressionNodeSharedPtr pArg( rNodeStack.top() ); 257*cdf0e10cSrcweir rNodeStack.pop(); 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir // check for constness 260*cdf0e10cSrcweir if( pArg->isConstant() ) 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir rNodeStack.push( 263*cdf0e10cSrcweir ExpressionNodeFactory::createConstantValueExpression( 264*cdf0e10cSrcweir maFunctor( (*pArg)(0.0) ) ) ); 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir else 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir // push complex node, that calcs the value on demand 269*cdf0e10cSrcweir rNodeStack.push( 270*cdf0e10cSrcweir ExpressionNodeSharedPtr( 271*cdf0e10cSrcweir new UnaryFunctionExpression( 272*cdf0e10cSrcweir maFunctor, 273*cdf0e10cSrcweir pArg ) ) ); 274*cdf0e10cSrcweir } 275*cdf0e10cSrcweir } 276*cdf0e10cSrcweir 277*cdf0e10cSrcweir private: 278*cdf0e10cSrcweir Functor maFunctor; 279*cdf0e10cSrcweir ParserContextSharedPtr mpContext; 280*cdf0e10cSrcweir }; 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir // TODO(Q2): Refactor makeUnaryFunctionFunctor, 283*cdf0e10cSrcweir // makeBinaryFunctionFunctor and the whole 284*cdf0e10cSrcweir // ExpressionNodeFactory, to use a generic 285*cdf0e10cSrcweir // makeFunctionFunctor template, which is overloaded for 286*cdf0e10cSrcweir // unary, binary, ternary, etc. function pointers. 287*cdf0e10cSrcweir template< typename Functor > UnaryFunctionFunctor<Functor> 288*cdf0e10cSrcweir makeUnaryFunctionFunctor( const Functor& rFunctor, 289*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) 290*cdf0e10cSrcweir { 291*cdf0e10cSrcweir return UnaryFunctionFunctor<Functor>( rFunctor, rContext ); 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir // MSVC has problems instantiating above template function with plain function 295*cdf0e10cSrcweir // pointers (doesn't like the const reference there). Thus, provide it with 296*cdf0e10cSrcweir // a dedicated overload here. 297*cdf0e10cSrcweir UnaryFunctionFunctor< double (*)(double) > 298*cdf0e10cSrcweir makeUnaryFunctionFunctor( double (*pFunc)(double), 299*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir return UnaryFunctionFunctor< double (*)(double) >( pFunc, rContext ); 302*cdf0e10cSrcweir } 303*cdf0e10cSrcweir 304*cdf0e10cSrcweir /** Implements a binary function over two ExpressionNodes 305*cdf0e10cSrcweir 306*cdf0e10cSrcweir @tpl Generator 307*cdf0e10cSrcweir Generator functor, to generate an ExpressionNode of 308*cdf0e10cSrcweir appropriate type 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir */ 311*cdf0e10cSrcweir template< class Generator > class BinaryFunctionFunctor 312*cdf0e10cSrcweir { 313*cdf0e10cSrcweir public: 314*cdf0e10cSrcweir BinaryFunctionFunctor( const Generator& rGenerator, 315*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) : 316*cdf0e10cSrcweir maGenerator( rGenerator ), 317*cdf0e10cSrcweir mpContext( rContext ) 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir ENSURE_OR_THROW( mpContext, 320*cdf0e10cSrcweir "BinaryFunctionFunctor::BinaryFunctionFunctor(): Invalid context" ); 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir void operator()( StringIteratorT, StringIteratorT ) const 324*cdf0e10cSrcweir { 325*cdf0e10cSrcweir ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); 326*cdf0e10cSrcweir 327*cdf0e10cSrcweir if( rNodeStack.size() < 2 ) 328*cdf0e10cSrcweir throw ParseError( "Not enough arguments for binary operator" ); 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir // retrieve arguments 331*cdf0e10cSrcweir ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() ); 332*cdf0e10cSrcweir rNodeStack.pop(); 333*cdf0e10cSrcweir ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() ); 334*cdf0e10cSrcweir rNodeStack.pop(); 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir // create combined ExpressionNode 337*cdf0e10cSrcweir ExpressionNodeSharedPtr pNode( maGenerator( pFirstArg, 338*cdf0e10cSrcweir pSecondArg ) ); 339*cdf0e10cSrcweir // check for constness 340*cdf0e10cSrcweir if( pFirstArg->isConstant() && 341*cdf0e10cSrcweir pSecondArg->isConstant() ) 342*cdf0e10cSrcweir { 343*cdf0e10cSrcweir // call the operator() at pNode, store result 344*cdf0e10cSrcweir // in constant value ExpressionNode. 345*cdf0e10cSrcweir rNodeStack.push( 346*cdf0e10cSrcweir ExpressionNodeFactory::createConstantValueExpression( 347*cdf0e10cSrcweir (*pNode)( 0.0 ) ) ); 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir else 350*cdf0e10cSrcweir { 351*cdf0e10cSrcweir // push complex node, that calcs the value on demand 352*cdf0e10cSrcweir rNodeStack.push( pNode ); 353*cdf0e10cSrcweir } 354*cdf0e10cSrcweir } 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir private: 357*cdf0e10cSrcweir Generator maGenerator; 358*cdf0e10cSrcweir ParserContextSharedPtr mpContext; 359*cdf0e10cSrcweir }; 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir template< typename Generator > BinaryFunctionFunctor<Generator> 362*cdf0e10cSrcweir makeBinaryFunctionFunctor( const Generator& rGenerator, 363*cdf0e10cSrcweir const ParserContextSharedPtr& rContext ) 364*cdf0e10cSrcweir { 365*cdf0e10cSrcweir return BinaryFunctionFunctor<Generator>( rGenerator, rContext ); 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir // Workaround for MSVC compiler anomaly (stack trashing) 370*cdf0e10cSrcweir // 371*cdf0e10cSrcweir // The default ureal_parser_policies implementation of parse_exp 372*cdf0e10cSrcweir // triggers a really weird error in MSVC7 (Version 13.00.9466), in 373*cdf0e10cSrcweir // that the real_parser_impl::parse_main() call of parse_exp() 374*cdf0e10cSrcweir // overwrites the frame pointer _on the stack_ (EBP of the calling 375*cdf0e10cSrcweir // function gets overwritten while lying on the stack). 376*cdf0e10cSrcweir // 377*cdf0e10cSrcweir // For the time being, our parser thus can only read the 1.0E10 378*cdf0e10cSrcweir // notation, not the 1.0e10 one. 379*cdf0e10cSrcweir // 380*cdf0e10cSrcweir // TODO(F1): Also handle the 1.0e10 case here. 381*cdf0e10cSrcweir template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T> 382*cdf0e10cSrcweir { 383*cdf0e10cSrcweir template< typename ScannerT > 384*cdf0e10cSrcweir static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type 385*cdf0e10cSrcweir parse_exp(ScannerT& scan) 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir // as_lower_d somehow breaks MSVC7 388*cdf0e10cSrcweir return ::boost::spirit::ch_p('E').parse(scan); 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir }; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir /* This class implements the following grammar (more or 393*cdf0e10cSrcweir less literally written down below, only slightly 394*cdf0e10cSrcweir obfuscated by the parser actions): 395*cdf0e10cSrcweir 396*cdf0e10cSrcweir identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height' 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log' 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir basic_expression = 401*cdf0e10cSrcweir number | 402*cdf0e10cSrcweir identifier | 403*cdf0e10cSrcweir function '(' additive_expression ')' | 404*cdf0e10cSrcweir '(' additive_expression ')' 405*cdf0e10cSrcweir 406*cdf0e10cSrcweir unary_expression = 407*cdf0e10cSrcweir '-' basic_expression | 408*cdf0e10cSrcweir basic_expression 409*cdf0e10cSrcweir 410*cdf0e10cSrcweir multiplicative_expression = 411*cdf0e10cSrcweir unary_expression ( ( '*' unary_expression )* | 412*cdf0e10cSrcweir ( '/' unary_expression )* ) 413*cdf0e10cSrcweir 414*cdf0e10cSrcweir additive_expression = 415*cdf0e10cSrcweir multiplicative_expression ( ( '+' multiplicative_expression )* | 416*cdf0e10cSrcweir ( '-' multiplicative_expression )* ) 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir */ 419*cdf0e10cSrcweir class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar > 420*cdf0e10cSrcweir { 421*cdf0e10cSrcweir public: 422*cdf0e10cSrcweir /** Create an arithmetic expression grammar 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir @param rParserContext 425*cdf0e10cSrcweir Contains context info for the parser 426*cdf0e10cSrcweir */ 427*cdf0e10cSrcweir ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) : 428*cdf0e10cSrcweir mpParserContext( rParserContext ) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir } 431*cdf0e10cSrcweir 432*cdf0e10cSrcweir template< typename ScannerT > class definition 433*cdf0e10cSrcweir { 434*cdf0e10cSrcweir public: 435*cdf0e10cSrcweir // grammar definition 436*cdf0e10cSrcweir definition( const ExpressionGrammar& self ) 437*cdf0e10cSrcweir { 438*cdf0e10cSrcweir using ::boost::spirit::str_p; 439*cdf0e10cSrcweir using ::boost::spirit::real_parser; 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir identifier = 442*cdf0e10cSrcweir str_p( "$" )[ ValueTFunctor( self.getContext()) ] 443*cdf0e10cSrcweir | str_p( "pi" )[ ConstantFunctor(M_PI, self.getContext()) ] 444*cdf0e10cSrcweir | str_p( "e" )[ ConstantFunctor(M_E, self.getContext()) ] 445*cdf0e10cSrcweir | str_p( "x" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getCenterX),self.getContext()) ] 446*cdf0e10cSrcweir | str_p( "y" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getCenterY),self.getContext()) ] 447*cdf0e10cSrcweir | str_p( "width" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getWidth), self.getContext()) ] 448*cdf0e10cSrcweir | str_p( "height" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getHeight), self.getContext()) ] 449*cdf0e10cSrcweir ; 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir unaryFunction = 452*cdf0e10cSrcweir (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&fabs, self.getContext()) ] 453*cdf0e10cSrcweir | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&sqrt, self.getContext()) ] 454*cdf0e10cSrcweir | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&sin, self.getContext()) ] 455*cdf0e10cSrcweir | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&cos, self.getContext()) ] 456*cdf0e10cSrcweir | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&tan, self.getContext()) ] 457*cdf0e10cSrcweir | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&atan, self.getContext()) ] 458*cdf0e10cSrcweir | (str_p( "acos" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&acos, self.getContext()) ] 459*cdf0e10cSrcweir | (str_p( "asin" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&asin, self.getContext()) ] 460*cdf0e10cSrcweir | (str_p( "exp" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&exp, self.getContext()) ] 461*cdf0e10cSrcweir | (str_p( "log" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&log, self.getContext()) ] 462*cdf0e10cSrcweir ; 463*cdf0e10cSrcweir 464*cdf0e10cSrcweir binaryFunction = 465*cdf0e10cSrcweir (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMinExpression, self.getContext()) ] 466*cdf0e10cSrcweir | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMaxExpression, self.getContext()) ] 467*cdf0e10cSrcweir ; 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir basicExpression = 470*cdf0e10cSrcweir real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ] 471*cdf0e10cSrcweir | identifier 472*cdf0e10cSrcweir | unaryFunction 473*cdf0e10cSrcweir | binaryFunction 474*cdf0e10cSrcweir | '(' >> additiveExpression >> ')' 475*cdf0e10cSrcweir ; 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir unaryExpression = 478*cdf0e10cSrcweir ('-' >> basicExpression)[ makeUnaryFunctionFunctor(::std::negate<double>(), self.getContext()) ] 479*cdf0e10cSrcweir | basicExpression 480*cdf0e10cSrcweir ; 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir multiplicativeExpression = 483*cdf0e10cSrcweir unaryExpression 484*cdf0e10cSrcweir >> *( ('*' >> unaryExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMultipliesExpression, self.getContext()) ] 485*cdf0e10cSrcweir | ('/' >> unaryExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createDividesExpression, self.getContext()) ] 486*cdf0e10cSrcweir ) 487*cdf0e10cSrcweir ; 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir additiveExpression = 490*cdf0e10cSrcweir multiplicativeExpression 491*cdf0e10cSrcweir >> *( ('+' >> multiplicativeExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createPlusExpression, self.getContext()) ] 492*cdf0e10cSrcweir | ('-' >> multiplicativeExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMinusExpression, self.getContext()) ] 493*cdf0e10cSrcweir ) 494*cdf0e10cSrcweir ; 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(additiveExpression); 497*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression); 498*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(unaryExpression); 499*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(basicExpression); 500*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(unaryFunction); 501*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(binaryFunction); 502*cdf0e10cSrcweir BOOST_SPIRIT_DEBUG_RULE(identifier); 503*cdf0e10cSrcweir } 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir const ::boost::spirit::rule< ScannerT >& start() const 506*cdf0e10cSrcweir { 507*cdf0e10cSrcweir return additiveExpression; 508*cdf0e10cSrcweir } 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir private: 511*cdf0e10cSrcweir // the constituents of the Spirit arithmetic expression grammar. 512*cdf0e10cSrcweir // For the sake of readability, without 'ma' prefix. 513*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > additiveExpression; 514*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > multiplicativeExpression; 515*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > unaryExpression; 516*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > basicExpression; 517*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > unaryFunction; 518*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > binaryFunction; 519*cdf0e10cSrcweir ::boost::spirit::rule< ScannerT > identifier; 520*cdf0e10cSrcweir }; 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir const ParserContextSharedPtr& getContext() const 523*cdf0e10cSrcweir { 524*cdf0e10cSrcweir return mpParserContext; 525*cdf0e10cSrcweir } 526*cdf0e10cSrcweir 527*cdf0e10cSrcweir private: 528*cdf0e10cSrcweir ParserContextSharedPtr mpParserContext; // might get modified during parsing 529*cdf0e10cSrcweir }; 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 532*cdf0e10cSrcweir const ParserContextSharedPtr& getParserContext() 533*cdf0e10cSrcweir { 534*cdf0e10cSrcweir static ParserContextSharedPtr lcl_parserContext( new ParserContext() ); 535*cdf0e10cSrcweir 536*cdf0e10cSrcweir // clear node stack (since we reuse the static object, that's 537*cdf0e10cSrcweir // the whole point here) 538*cdf0e10cSrcweir while( !lcl_parserContext->maOperandStack.empty() ) 539*cdf0e10cSrcweir lcl_parserContext->maOperandStack.pop(); 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir return lcl_parserContext; 542*cdf0e10cSrcweir } 543*cdf0e10cSrcweir #endif 544*cdf0e10cSrcweir } 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir ExpressionNodeSharedPtr SmilFunctionParser::parseSmilValue( const ::rtl::OUString& rSmilValue, 547*cdf0e10cSrcweir const ::basegfx::B2DRectangle& rRelativeShapeBounds ) 548*cdf0e10cSrcweir { 549*cdf0e10cSrcweir // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_* 550*cdf0e10cSrcweir // gives better conversion robustness here (we might want to map space 551*cdf0e10cSrcweir // etc. to ASCII space here) 552*cdf0e10cSrcweir const ::rtl::OString& rAsciiSmilValue( 553*cdf0e10cSrcweir rtl::OUStringToOString( rSmilValue, RTL_TEXTENCODING_ASCII_US ) ); 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir StringIteratorT aStart( rAsciiSmilValue.getStr() ); 556*cdf0e10cSrcweir StringIteratorT aEnd( rAsciiSmilValue.getStr()+rAsciiSmilValue.getLength() ); 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir ParserContextSharedPtr pContext; 559*cdf0e10cSrcweir 560*cdf0e10cSrcweir #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 561*cdf0e10cSrcweir // static parser context, because the actual 562*cdf0e10cSrcweir // Spirit parser is also a static object 563*cdf0e10cSrcweir pContext = getParserContext(); 564*cdf0e10cSrcweir #else 565*cdf0e10cSrcweir pContext.reset( new ParserContext() ); 566*cdf0e10cSrcweir #endif 567*cdf0e10cSrcweir 568*cdf0e10cSrcweir pContext->maShapeBounds = rRelativeShapeBounds; 569*cdf0e10cSrcweir pContext->mbParseAnimationFunction = false; // parse with '$' disabled 570*cdf0e10cSrcweir 571*cdf0e10cSrcweir 572*cdf0e10cSrcweir ExpressionGrammar aExpressionGrammer( pContext ); 573*cdf0e10cSrcweir const ::boost::spirit::parse_info<StringIteratorT> aParseInfo( 574*cdf0e10cSrcweir ::boost::spirit::parse( aStart, 575*cdf0e10cSrcweir aEnd, 576*cdf0e10cSrcweir aExpressionGrammer, 577*cdf0e10cSrcweir ::boost::spirit::space_p ) ); 578*cdf0e10cSrcweir OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync 579*cdf0e10cSrcweir 580*cdf0e10cSrcweir // input fully congested by the parser? 581*cdf0e10cSrcweir if( !aParseInfo.full ) 582*cdf0e10cSrcweir throw ParseError( "SmilFunctionParser::parseSmilValue(): string not fully parseable" ); 583*cdf0e10cSrcweir 584*cdf0e10cSrcweir // parser's state stack now must contain exactly _one_ ExpressionNode, 585*cdf0e10cSrcweir // which represents our formula. 586*cdf0e10cSrcweir if( pContext->maOperandStack.size() != 1 ) 587*cdf0e10cSrcweir throw ParseError( "SmilFunctionParser::parseSmilValue(): incomplete or empty expression" ); 588*cdf0e10cSrcweir 589*cdf0e10cSrcweir return pContext->maOperandStack.top(); 590*cdf0e10cSrcweir } 591*cdf0e10cSrcweir 592*cdf0e10cSrcweir ExpressionNodeSharedPtr SmilFunctionParser::parseSmilFunction( const ::rtl::OUString& rSmilFunction, 593*cdf0e10cSrcweir const ::basegfx::B2DRectangle& rRelativeShapeBounds ) 594*cdf0e10cSrcweir { 595*cdf0e10cSrcweir // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_* 596*cdf0e10cSrcweir // gives better conversion robustness here (we might want to map space 597*cdf0e10cSrcweir // etc. to ASCII space here) 598*cdf0e10cSrcweir const ::rtl::OString& rAsciiSmilFunction( 599*cdf0e10cSrcweir rtl::OUStringToOString( rSmilFunction, RTL_TEXTENCODING_ASCII_US ) ); 600*cdf0e10cSrcweir 601*cdf0e10cSrcweir StringIteratorT aStart( rAsciiSmilFunction.getStr() ); 602*cdf0e10cSrcweir StringIteratorT aEnd( rAsciiSmilFunction.getStr()+rAsciiSmilFunction.getLength() ); 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir ParserContextSharedPtr pContext; 605*cdf0e10cSrcweir 606*cdf0e10cSrcweir #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE 607*cdf0e10cSrcweir // static parser context, because the actual 608*cdf0e10cSrcweir // Spirit parser is also a static object 609*cdf0e10cSrcweir pContext = getParserContext(); 610*cdf0e10cSrcweir #else 611*cdf0e10cSrcweir pContext.reset( new ParserContext() ); 612*cdf0e10cSrcweir #endif 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir pContext->maShapeBounds = rRelativeShapeBounds; 615*cdf0e10cSrcweir pContext->mbParseAnimationFunction = true; // parse with '$' enabled 616*cdf0e10cSrcweir 617*cdf0e10cSrcweir 618*cdf0e10cSrcweir ExpressionGrammar aExpressionGrammer( pContext ); 619*cdf0e10cSrcweir const ::boost::spirit::parse_info<StringIteratorT> aParseInfo( 620*cdf0e10cSrcweir ::boost::spirit::parse( aStart, 621*cdf0e10cSrcweir aEnd, 622*cdf0e10cSrcweir aExpressionGrammer >> ::boost::spirit::end_p, 623*cdf0e10cSrcweir ::boost::spirit::space_p ) ); 624*cdf0e10cSrcweir OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync 625*cdf0e10cSrcweir 626*cdf0e10cSrcweir // input fully congested by the parser? 627*cdf0e10cSrcweir if( !aParseInfo.full ) 628*cdf0e10cSrcweir throw ParseError( "SmilFunctionParser::parseSmilFunction(): string not fully parseable" ); 629*cdf0e10cSrcweir 630*cdf0e10cSrcweir // parser's state stack now must contain exactly _one_ ExpressionNode, 631*cdf0e10cSrcweir // which represents our formula. 632*cdf0e10cSrcweir if( pContext->maOperandStack.size() != 1 ) 633*cdf0e10cSrcweir throw ParseError( "SmilFunctionParser::parseSmilFunction(): incomplete or empty expression" ); 634*cdf0e10cSrcweir 635*cdf0e10cSrcweir return pContext->maOperandStack.top(); 636*cdf0e10cSrcweir } 637*cdf0e10cSrcweir } 638*cdf0e10cSrcweir } 639