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