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