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