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