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