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