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