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