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