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 14614 : void EnhancedCustomShape::FillEquationParameter( const EnhancedCustomShapeParameter& rSource, const sal_Int32 nDestPara, EnhancedCustomShapeEquation& rDest )
49 : {
50 14614 : sal_Int32 nValue = 0;
51 14614 : 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 14614 : rSource.Value >>= nValue;
59 :
60 14614 : switch( rSource.Type )
61 : {
62 : case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
63 : {
64 4964 : if ( nValue & 0x40000000 )
65 : {
66 2474 : nValue ^= 0x40000000;
67 2474 : rDest.nOperation |= 0x20000000 << nDestPara; // the bit is indicating that this value has to be adjusted later
68 : }
69 4964 : nValue |= 0x400;
70 : }
71 4964 : break;
72 768 : 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 14614 : if ( rSource.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL )
79 5732 : rDest.nOperation |= ( 0x2000 << nDestPara );
80 14614 : rDest.nPara[ nDestPara ] = nValue;
81 14614 : }
82 :
83 1204508 : ExpressionNode::~ExpressionNode()
84 1204508 : {}
85 :
86 : namespace
87 : {
88 :
89 :
90 :
91 : // EXPRESSION NODES
92 :
93 :
94 942184 : class ConstantValueExpression : public ExpressionNode
95 : {
96 : double maValue;
97 :
98 : public:
99 :
100 472808 : ConstantValueExpression( double rValue ) :
101 472808 : maValue( rValue )
102 : {
103 472808 : }
104 209854 : virtual double operator()() const SAL_OVERRIDE
105 : {
106 209854 : return maValue;
107 : }
108 293270 : virtual bool isConstant() const SAL_OVERRIDE
109 : {
110 293270 : return true;
111 : }
112 3032 : virtual ExpressionFunct getType() const SAL_OVERRIDE
113 : {
114 3032 : return FUNC_CONST;
115 : }
116 8980 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) SAL_OVERRIDE
117 : {
118 8980 : EnhancedCustomShapeParameter aRet;
119 8980 : Fraction aFract( maValue );
120 8980 : if ( aFract.GetDenominator() == 1 )
121 : {
122 8882 : aRet.Type = EnhancedCustomShapeParameterType::NORMAL;
123 8882 : aRet.Value <<= (sal_Int32)aFract.GetNumerator();
124 : }
125 : else
126 : {
127 98 : EnhancedCustomShapeEquation aEquation;
128 98 : aEquation.nOperation = 1;
129 98 : aEquation.nPara[ 0 ] = 1;
130 98 : aEquation.nPara[ 1 ] = (sal_Int16)aFract.GetNumerator();
131 98 : aEquation.nPara[ 2 ] = (sal_Int16)aFract.GetDenominator();
132 98 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
133 98 : aRet.Value <<= (sal_Int32)rEquations.size();
134 98 : rEquations.push_back( aEquation );
135 : }
136 8980 : return aRet;
137 : }
138 : };
139 :
140 58372 : class AdjustmentExpression : public ExpressionNode
141 : {
142 : sal_Int32 mnIndex;
143 : const EnhancedCustomShape2d& mrCustoShape;
144 :
145 : public:
146 :
147 29186 : AdjustmentExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
148 : : mnIndex ( nIndex )
149 29186 : , mrCustoShape( rCustoShape )
150 :
151 : {
152 29186 : }
153 12724 : 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 12724 : return mrCustoShape.GetAdjustValueAsDouble( mnIndex );
157 : }
158 34638 : virtual bool isConstant() const SAL_OVERRIDE
159 : {
160 34638 : return false;
161 : }
162 112 : virtual ExpressionFunct getType() const SAL_OVERRIDE
163 : {
164 112 : return ENUM_FUNC_ADJUSTMENT;
165 : }
166 768 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) SAL_OVERRIDE
167 : {
168 768 : EnhancedCustomShapeParameter aRet;
169 768 : aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
170 768 : aRet.Value <<= mnIndex;
171 768 : return aRet;
172 : }
173 : };
174 :
175 203744 : class EquationExpression : public ExpressionNode
176 : {
177 : sal_Int32 mnIndex;
178 : const EnhancedCustomShape2d& mrCustoShape;
179 :
180 : public:
181 :
182 101872 : EquationExpression( const EnhancedCustomShape2d& rCustoShape, sal_Int32 nIndex )
183 : : mnIndex ( nIndex )
184 101872 : , mrCustoShape( rCustoShape )
185 : {
186 101872 : }
187 25140 : virtual double operator()() const SAL_OVERRIDE
188 : {
189 25140 : return mrCustoShape.GetEquationValueAsDouble( mnIndex );
190 : }
191 79866 : virtual bool isConstant() const SAL_OVERRIDE
192 : {
193 79866 : return false;
194 : }
195 3126 : virtual ExpressionFunct getType() const SAL_OVERRIDE
196 : {
197 3126 : return ENUM_FUNC_EQUATION;
198 : }
199 2474 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) SAL_OVERRIDE
200 : {
201 2474 : EnhancedCustomShapeParameter aRet;
202 2474 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
203 2474 : aRet.Value <<= mnIndex | 0x40000000; // the bit is indicating that this equation needs to be adjusted later
204 2474 : return aRet;
205 : }
206 : };
207 :
208 330008 : class EnumValueExpression : public ExpressionNode
209 : {
210 : const ExpressionFunct meFunct;
211 : const EnhancedCustomShape2d& mrCustoShape;
212 :
213 : public:
214 :
215 165004 : EnumValueExpression( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunct )
216 : : meFunct ( eFunct )
217 165004 : , mrCustoShape ( rCustoShape )
218 : {
219 165004 : }
220 38912 : static double getValue( const EnhancedCustomShape2d& rCustoShape, const ExpressionFunct eFunc )
221 : {
222 : EnhancedCustomShape2d::EnumFunc eF;
223 38912 : switch( eFunc )
224 : {
225 1902 : case ENUM_FUNC_PI : eF = EnhancedCustomShape2d::ENUM_FUNC_PI; break;
226 14 : case ENUM_FUNC_LEFT : eF = EnhancedCustomShape2d::ENUM_FUNC_LEFT; break;
227 14 : case ENUM_FUNC_TOP : eF = EnhancedCustomShape2d::ENUM_FUNC_TOP; break;
228 24 : case ENUM_FUNC_RIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_RIGHT; break;
229 24 : 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 18352 : case ENUM_FUNC_LOGWIDTH : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGWIDTH; break;
237 18582 : case ENUM_FUNC_LOGHEIGHT : eF = EnhancedCustomShape2d::ENUM_FUNC_LOGHEIGHT; break;
238 :
239 : default :
240 0 : return 0.0;
241 : }
242 38912 : return rCustoShape.GetEnumFunc( eF );
243 : }
244 35480 : 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 35480 : return getValue( mrCustoShape, meFunct );
270 : }
271 242670 : virtual bool isConstant() const SAL_OVERRIDE
272 : {
273 242670 : return false;
274 : }
275 1216 : virtual ExpressionFunct getType() const SAL_OVERRIDE
276 : {
277 1216 : return meFunct;
278 : }
279 3432 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
280 : {
281 3432 : EnhancedCustomShapeParameter aRet;
282 :
283 3432 : sal_Int32 nDummy = 1;
284 3432 : aRet.Value <<= nDummy;
285 :
286 3432 : 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 3432 : ConstantValueExpression aConstantValue( getValue( mrCustoShape, meFunct ) );
295 3432 : aRet = aConstantValue.fillNode( rEquations, NULL, nFlags );
296 : }
297 3432 : 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 3432 : return aRet;
313 : }
314 : };
315 :
316 : /** ExpressionNode implementation for unary
317 : function over one ExpressionNode
318 : */
319 61592 : class UnaryFunctionExpression : public ExpressionNode
320 : {
321 : const ExpressionFunct meFunct;
322 : ExpressionNodeSharedPtr mpArg;
323 :
324 : public:
325 30796 : UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) :
326 : meFunct( eFunct ),
327 30796 : mpArg( rArg )
328 : {
329 30796 : }
330 2826 : static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg )
331 : {
332 2826 : double fRet = 0;
333 2826 : switch( eFunct )
334 : {
335 50 : case UNARY_FUNC_ABS : fRet = fabs( (*rArg)() ); break;
336 24 : case UNARY_FUNC_SQRT: fRet = sqrt( (*rArg)() ); break;
337 942 : case UNARY_FUNC_SIN : fRet = sin( (*rArg)() ); break;
338 926 : 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 884 : case UNARY_FUNC_NEG : fRet = ::std::negate<double>()( (*rArg)() ); break;
342 : default:
343 0 : break;
344 : }
345 2826 : return fRet;
346 : }
347 2198 : virtual double operator()() const SAL_OVERRIDE
348 : {
349 2198 : return getValue( meFunct, mpArg );
350 : }
351 52298 : virtual bool isConstant() const SAL_OVERRIDE
352 : {
353 52298 : return mpArg->isConstant();
354 : }
355 566 : virtual ExpressionFunct getType() const SAL_OVERRIDE
356 : {
357 566 : return meFunct;
358 : }
359 460 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* pOptionalArg, sal_uInt32 nFlags ) SAL_OVERRIDE
360 : {
361 460 : EnhancedCustomShapeParameter aRet;
362 460 : switch( meFunct )
363 : {
364 : case UNARY_FUNC_ABS :
365 : {
366 14 : EnhancedCustomShapeEquation aEquation;
367 14 : aEquation.nOperation |= 3;
368 14 : FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
369 14 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
370 14 : aRet.Value <<= (sal_Int32)rEquations.size();
371 14 : rEquations.push_back( aEquation );
372 : }
373 14 : 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 190 : EnhancedCustomShapeEquation aEquation;
387 190 : aEquation.nOperation |= 9;
388 190 : if ( pOptionalArg )
389 190 : FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
390 : else
391 0 : aEquation.nPara[ 0 ] = 1;
392 :
393 190 : EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
394 190 : if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
395 : { // sumangle needed :-(
396 136 : EnhancedCustomShapeEquation _aEquation;
397 136 : _aEquation.nOperation |= 0xe; // sumangle
398 136 : FillEquationParameter( aSource, 1, _aEquation );
399 136 : aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
400 136 : aSource.Value <<= (sal_Int32)rEquations.size();
401 136 : rEquations.push_back( _aEquation );
402 : }
403 190 : FillEquationParameter( aSource, 1, aEquation );
404 190 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
405 190 : aRet.Value <<= (sal_Int32)rEquations.size();
406 190 : rEquations.push_back( aEquation );
407 : }
408 190 : break;
409 : case UNARY_FUNC_COS :
410 : {
411 188 : EnhancedCustomShapeEquation aEquation;
412 188 : aEquation.nOperation |= 10;
413 188 : if ( pOptionalArg )
414 188 : FillEquationParameter( pOptionalArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
415 : else
416 0 : aEquation.nPara[ 0 ] = 1;
417 :
418 188 : EnhancedCustomShapeParameter aSource( mpArg->fillNode( rEquations, NULL, nFlags | EXPRESSION_FLAG_SUMANGLE_MODE ) );
419 188 : if ( aSource.Type == EnhancedCustomShapeParameterType::NORMAL )
420 : { // sumangle needed :-(
421 136 : EnhancedCustomShapeEquation aTmpEquation;
422 136 : aTmpEquation.nOperation |= 0xe; // sumangle
423 136 : FillEquationParameter( aSource, 1, aTmpEquation );
424 136 : aSource.Type = EnhancedCustomShapeParameterType::EQUATION;
425 136 : aSource.Value <<= (sal_Int32)rEquations.size();
426 136 : rEquations.push_back( aTmpEquation );
427 : }
428 188 : FillEquationParameter( aSource, 1, aEquation );
429 188 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
430 188 : aRet.Value <<= (sal_Int32)rEquations.size();
431 188 : rEquations.push_back( aEquation );
432 : }
433 188 : 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 68 : EnhancedCustomShapeEquation aEquation;
468 68 : aEquation.nOperation |= 1;
469 68 : aEquation.nPara[ 1 ] = -1;
470 68 : aEquation.nPara[ 2 ] = 1;
471 68 : FillEquationParameter( mpArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
472 68 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
473 68 : aRet.Value <<= (sal_Int32)rEquations.size();
474 68 : rEquations.push_back( aEquation );
475 : }
476 68 : break;
477 : default:
478 0 : break;
479 : }
480 460 : return aRet;
481 : }
482 : };
483 :
484 : /** ExpressionNode implementation for unary
485 : function over two ExpressionNodes
486 : */
487 771760 : class BinaryFunctionExpression : public ExpressionNode
488 : {
489 : const ExpressionFunct meFunct;
490 : ExpressionNodeSharedPtr mpFirstArg;
491 : ExpressionNodeSharedPtr mpSecondArg;
492 :
493 : public:
494 :
495 385880 : BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) :
496 : meFunct( eFunct ),
497 : mpFirstArg( rFirstArg ),
498 385880 : mpSecondArg( rSecondArg )
499 : {
500 385880 : }
501 136746 : static double getValue( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg )
502 : {
503 136746 : double fRet = 0;
504 136746 : switch( eFunct )
505 : {
506 10110 : case BINARY_FUNC_PLUS : fRet = (*rFirstArg)() + (*rSecondArg)(); break;
507 32866 : case BINARY_FUNC_MINUS: fRet = (*rFirstArg)() - (*rSecondArg)(); break;
508 11614 : case BINARY_FUNC_MUL : fRet = (*rFirstArg)() * (*rSecondArg)(); break;
509 78566 : case BINARY_FUNC_DIV : fRet = (*rFirstArg)() / (*rSecondArg)(); break;
510 3526 : case BINARY_FUNC_MIN : fRet = ::std::min( (*rFirstArg)(), (*rSecondArg)() ); break;
511 0 : case BINARY_FUNC_MAX : fRet = ::std::max( (*rFirstArg)(), (*rSecondArg)() ); break;
512 64 : case BINARY_FUNC_ATAN2: fRet = atan2( (*rFirstArg)(), (*rSecondArg)() ); break;
513 : default:
514 0 : break;
515 : }
516 136746 : return fRet;
517 : }
518 136746 : virtual double operator()() const SAL_OVERRIDE
519 : {
520 136746 : return getValue( meFunct, mpFirstArg, mpSecondArg );
521 : }
522 291932 : virtual bool isConstant() const SAL_OVERRIDE
523 : {
524 291932 : return mpFirstArg->isConstant() && mpSecondArg->isConstant();
525 : }
526 1120 : virtual ExpressionFunct getType() const SAL_OVERRIDE
527 : {
528 1120 : return meFunct;
529 : }
530 6156 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
531 : {
532 6156 : EnhancedCustomShapeParameter aRet;
533 6156 : switch( meFunct )
534 : {
535 : case BINARY_FUNC_PLUS :
536 : {
537 1226 : 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 1226 : bool bFirstIsEmpty = mpFirstArg->isConstant() && ( (*mpFirstArg)() == 0 );
587 1226 : bool bSecondIsEmpty = mpSecondArg->isConstant() && ( (*mpSecondArg)() == 0 );
588 :
589 1226 : if ( bFirstIsEmpty )
590 6 : aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
591 1220 : else if ( bSecondIsEmpty )
592 840 : aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
593 : else
594 : {
595 380 : EnhancedCustomShapeEquation aEquation;
596 380 : aEquation.nOperation |= 0;
597 380 : FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
598 380 : FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
599 380 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
600 380 : aRet.Value <<= (sal_Int32)rEquations.size();
601 380 : rEquations.push_back( aEquation );
602 : }
603 : }
604 : }
605 1226 : break;
606 : case BINARY_FUNC_MINUS:
607 : {
608 1652 : EnhancedCustomShapeEquation aEquation;
609 1652 : aEquation.nOperation |= 0;
610 1652 : FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
611 1652 : FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
612 1652 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
613 1652 : aRet.Value <<= (sal_Int32)rEquations.size();
614 1652 : rEquations.push_back( aEquation );
615 : }
616 1652 : 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 1344 : if ( ( mpFirstArg->getType() == UNARY_FUNC_SIN ) || ( mpFirstArg->getType() == UNARY_FUNC_COS ) || ( mpFirstArg->getType() == UNARY_FUNC_TAN ) )
622 272 : aRet = mpFirstArg->fillNode( rEquations, mpSecondArg.get(), nFlags );
623 1072 : else if ( ( mpSecondArg->getType() == UNARY_FUNC_SIN ) || ( mpSecondArg->getType() == UNARY_FUNC_COS ) || ( mpSecondArg->getType() == UNARY_FUNC_TAN ) )
624 106 : aRet = mpSecondArg->fillNode( rEquations, mpFirstArg.get(), nFlags );
625 : else
626 : {
627 966 : if ( mpFirstArg->isConstant() && (*mpFirstArg)() == 1 )
628 0 : aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
629 966 : else if ( mpSecondArg->isConstant() && (*mpSecondArg)() == 1 )
630 0 : aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
631 1932 : else if ( ( mpFirstArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
632 0 : && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpFirstArg.get()->getType() == ENUM_FUNC_PI )
633 966 : && ( static_cast<BinaryFunctionExpression*>(mpFirstArg.get())->mpSecondArg.get()->getType() == FUNC_CONST ) )
634 : {
635 0 : aRet = mpSecondArg->fillNode( rEquations, NULL, nFlags );
636 : }
637 1932 : else if ( ( mpSecondArg->getType() == BINARY_FUNC_DIV ) // don't care of (pi/180)
638 280 : && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpFirstArg.get()->getType() == ENUM_FUNC_PI )
639 1246 : && ( static_cast<BinaryFunctionExpression*>(mpSecondArg.get())->mpSecondArg.get()->getType() == FUNC_CONST ) )
640 : {
641 280 : aRet = mpFirstArg->fillNode( rEquations, NULL, nFlags );
642 : }
643 : else
644 : {
645 686 : EnhancedCustomShapeEquation aEquation;
646 686 : aEquation.nOperation |= 1;
647 686 : FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
648 686 : FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
649 686 : aEquation.nPara[ 2 ] = 1;
650 686 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
651 686 : aRet.Value <<= (sal_Int32)rEquations.size();
652 686 : rEquations.push_back( aEquation );
653 : }
654 : }
655 : }
656 1344 : break;
657 : case BINARY_FUNC_DIV :
658 : {
659 1748 : EnhancedCustomShapeEquation aEquation;
660 1748 : aEquation.nOperation |= 1;
661 1748 : FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
662 1748 : aEquation.nPara[ 1 ] = 1;
663 1748 : FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
664 1748 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
665 1748 : aRet.Value <<= (sal_Int32)rEquations.size();
666 1748 : rEquations.push_back( aEquation );
667 : }
668 1748 : break;
669 : case BINARY_FUNC_MIN :
670 : {
671 186 : EnhancedCustomShapeEquation aEquation;
672 186 : aEquation.nOperation |= 4;
673 186 : FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
674 186 : FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
675 186 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
676 186 : aRet.Value <<= (sal_Int32)rEquations.size();
677 186 : rEquations.push_back( aEquation );
678 : }
679 186 : 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 6156 : return aRet;
706 : }
707 : };
708 :
709 37924 : class IfExpression : public ExpressionNode
710 : {
711 : ExpressionNodeSharedPtr mpFirstArg;
712 : ExpressionNodeSharedPtr mpSecondArg;
713 : ExpressionNodeSharedPtr mpThirdArg;
714 :
715 : public:
716 :
717 18962 : IfExpression( const ExpressionNodeSharedPtr& rFirstArg,
718 : const ExpressionNodeSharedPtr& rSecondArg,
719 : const ExpressionNodeSharedPtr& rThirdArg ) :
720 : mpFirstArg( rFirstArg ),
721 : mpSecondArg( rSecondArg ),
722 18962 : mpThirdArg( rThirdArg )
723 : {
724 18962 : }
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 8196 : virtual double operator()() const SAL_OVERRIDE
733 : {
734 8196 : return (*mpFirstArg)() > 0 ? (*mpSecondArg)() : (*mpThirdArg)();
735 : }
736 0 : virtual ExpressionFunct getType() const SAL_OVERRIDE
737 : {
738 0 : return TERNARY_FUNC_IF;
739 : }
740 498 : virtual EnhancedCustomShapeParameter fillNode( std::vector< EnhancedCustomShapeEquation >& rEquations, ExpressionNode* /*pOptionalArg*/, sal_uInt32 nFlags ) SAL_OVERRIDE
741 : {
742 498 : EnhancedCustomShapeParameter aRet;
743 498 : aRet.Type = EnhancedCustomShapeParameterType::EQUATION;
744 498 : aRet.Value <<= (sal_Int32)rEquations.size();
745 : {
746 498 : EnhancedCustomShapeEquation aEquation;
747 498 : aEquation.nOperation |= 6;
748 498 : FillEquationParameter( mpFirstArg->fillNode( rEquations, NULL, nFlags ), 0, aEquation );
749 498 : FillEquationParameter( mpSecondArg->fillNode( rEquations, NULL, nFlags ), 1, aEquation );
750 498 : FillEquationParameter( mpThirdArg->fillNode( rEquations, NULL, nFlags ), 2, aEquation );
751 498 : rEquations.push_back( aEquation );
752 : }
753 498 : return aRet;
754 : }
755 : };
756 :
757 :
758 :
759 : // FUNCTION PARSER
760 :
761 :
762 :
763 : typedef const sal_Char* StringIteratorT;
764 :
765 60 : 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 570 : class DoubleConstantFunctor
785 : {
786 : ParserContextSharedPtr mpContext;
787 :
788 : public:
789 30 : DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
790 30 : mpContext( rContext )
791 : {
792 30 : }
793 387590 : void operator()( double n ) const
794 : {
795 387590 : mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( n ) ) );
796 387590 : }
797 : };
798 :
799 7650 : class EnumFunctor
800 : {
801 : const ExpressionFunct meFunct;
802 : double mnValue;
803 : ParserContextSharedPtr mpContext;
804 :
805 : public:
806 :
807 450 : EnumFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext )
808 : : meFunct( eFunct )
809 : , mnValue( 0 )
810 450 : , mpContext( rContext )
811 : {
812 450 : }
813 296062 : void operator()( StringIteratorT rFirst, StringIteratorT rSecond ) const
814 : {
815 : /*double nVal = mnValue;*/
816 296062 : switch( meFunct )
817 : {
818 : case ENUM_FUNC_ADJUSTMENT :
819 : {
820 29186 : OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
821 29186 : mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new AdjustmentExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
822 : }
823 29186 : break;
824 : case ENUM_FUNC_EQUATION :
825 : {
826 101872 : OUString aVal( rFirst + 1, rSecond - rFirst, RTL_TEXTENCODING_UTF8 );
827 101872 : mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EquationExpression( *mpContext->mpCustoShape, aVal.toInt32() ) ) );
828 : }
829 101872 : break;
830 : default:
831 165004 : mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new EnumValueExpression( *mpContext->mpCustoShape, meFunct ) ) );
832 : }
833 296062 : }
834 : };
835 :
836 2310 : class UnaryFunctionFunctor
837 : {
838 : const ExpressionFunct meFunct;
839 : ParserContextSharedPtr mpContext;
840 :
841 : public :
842 :
843 210 : UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
844 : meFunct( eFunct ),
845 210 : mpContext( rContext )
846 : {
847 210 : }
848 31424 : void operator()( StringIteratorT, StringIteratorT ) const
849 : {
850 31424 : ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
851 :
852 31424 : if( rNodeStack.size() < 1 )
853 0 : throw ParseError( "Not enough arguments for unary operator" );
854 :
855 : // retrieve arguments
856 31424 : ExpressionNodeSharedPtr pArg( rNodeStack.top() );
857 31424 : rNodeStack.pop();
858 :
859 31424 : if( pArg->isConstant() ) // check for constness
860 628 : rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( UnaryFunctionExpression::getValue( meFunct, pArg ) ) ) );
861 : else // push complex node, that calcs the value on demand
862 30796 : rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) );
863 31424 : }
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 2070 : class BinaryFunctionFunctor
874 : {
875 : const ExpressionFunct meFunct;
876 : ParserContextSharedPtr mpContext;
877 :
878 : public:
879 :
880 210 : BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) :
881 : meFunct( eFunct ),
882 210 : mpContext( rContext )
883 : {
884 210 : }
885 :
886 385880 : void operator()( StringIteratorT, StringIteratorT ) const
887 : {
888 385880 : ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
889 :
890 385880 : if( rNodeStack.size() < 2 )
891 0 : throw ParseError( "Not enough arguments for binary operator" );
892 :
893 : // retrieve arguments
894 385880 : ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
895 385880 : rNodeStack.pop();
896 771760 : ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
897 385880 : rNodeStack.pop();
898 :
899 : // create combined ExpressionNode
900 771760 : ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) );
901 : // check for constness
902 385880 : if( pFirstArg->isConstant() && pSecondArg->isConstant() ) // call the operator() at pNode, store result in constant value ExpressionNode.
903 81158 : rNodeStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( (*pNode)() ) ) );
904 : else // push complex node, that calcs the value on demand
905 690602 : rNodeStack.push( pNode );
906 385880 : }
907 : };
908 :
909 150 : class IfFunctor
910 : {
911 : ParserContextSharedPtr mpContext;
912 :
913 : public :
914 :
915 30 : IfFunctor( const ParserContextSharedPtr& rContext ) :
916 30 : mpContext( rContext )
917 : {
918 30 : }
919 18962 : void operator()( StringIteratorT, StringIteratorT ) const
920 : {
921 18962 : ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
922 :
923 18962 : if( rNodeStack.size() < 3 )
924 0 : throw ParseError( "Not enough arguments for ternary operator" );
925 :
926 : // retrieve arguments
927 18962 : ExpressionNodeSharedPtr pThirdArg( rNodeStack.top() );
928 18962 : rNodeStack.pop();
929 37924 : ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
930 18962 : rNodeStack.pop();
931 37924 : ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
932 18962 : rNodeStack.pop();
933 :
934 : // create combined ExpressionNode
935 37924 : ExpressionNodeSharedPtr pNode( new IfExpression( pFirstArg, pSecondArg, pThirdArg ) );
936 : // check for constness
937 18962 : 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 37924 : rNodeStack.push( pNode ); // push complex node, that calcs the value on demand
941 18962 : }
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 387590 : parse_exp(ScannerT& scan)
961 : {
962 : // as_lower_d somehow breaks MSVC7
963 387590 : 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 259848 : 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 259848 : ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
1004 259848 : mpParserContext( rParserContext )
1005 : {
1006 259848 : }
1007 :
1008 30 : template< typename ScannerT > class definition
1009 : {
1010 : public:
1011 : // grammar definition
1012 30 : definition( const ExpressionGrammar& self )
1013 30 : {
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 390 : identifier =
1021 30 : str_p( "pi" )[ EnumFunctor(ENUM_FUNC_PI, self.getContext() ) ]
1022 30 : | str_p( "left" )[ EnumFunctor(ENUM_FUNC_LEFT, self.getContext() ) ]
1023 30 : | str_p( "top" )[ EnumFunctor(ENUM_FUNC_TOP, self.getContext() ) ]
1024 30 : | str_p( "right" )[ EnumFunctor(ENUM_FUNC_RIGHT, self.getContext() ) ]
1025 30 : | str_p( "bottom" )[ EnumFunctor(ENUM_FUNC_BOTTOM, self.getContext() ) ]
1026 30 : | str_p( "xstretch" )[ EnumFunctor(ENUM_FUNC_XSTRETCH, self.getContext() ) ]
1027 30 : | str_p( "ystretch" )[ EnumFunctor(ENUM_FUNC_YSTRETCH, self.getContext() ) ]
1028 30 : | str_p( "hasstroke" )[ EnumFunctor(ENUM_FUNC_HASSTROKE, self.getContext() ) ]
1029 30 : | str_p( "hasfill" )[ EnumFunctor(ENUM_FUNC_HASFILL, self.getContext() ) ]
1030 30 : | str_p( "width" )[ EnumFunctor(ENUM_FUNC_WIDTH, self.getContext() ) ]
1031 30 : | str_p( "height" )[ EnumFunctor(ENUM_FUNC_HEIGHT, self.getContext() ) ]
1032 30 : | str_p( "logwidth" )[ EnumFunctor(ENUM_FUNC_LOGWIDTH, self.getContext() ) ]
1033 30 : | str_p( "logheight" )[ EnumFunctor(ENUM_FUNC_LOGHEIGHT, self.getContext() ) ]
1034 : ;
1035 :
1036 540 : unaryFunction =
1037 90 : (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ABS, self.getContext()) ]
1038 90 : | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SQRT, self.getContext()) ]
1039 90 : | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_SIN, self.getContext()) ]
1040 90 : | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_COS, self.getContext()) ]
1041 90 : | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_TAN, self.getContext()) ]
1042 90 : | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ UnaryFunctionFunctor( UNARY_FUNC_ATAN, self.getContext()) ]
1043 : ;
1044 :
1045 270 : binaryFunction =
1046 90 : (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MIN, self.getContext()) ]
1047 90 : | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_MAX, self.getContext()) ]
1048 90 : | (str_p( "atan2") >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ BinaryFunctionFunctor( BINARY_FUNC_ATAN2,self.getContext()) ]
1049 : ;
1050 :
1051 90 : ternaryFunction =
1052 90 : (str_p( "if" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ IfFunctor( self.getContext() ) ]
1053 : ;
1054 :
1055 30 : funcRef_decl =
1056 60 : lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ];
1057 :
1058 90 : functionReference =
1059 90 : (str_p( "?" ) >> funcRef_decl )[ EnumFunctor( ENUM_FUNC_EQUATION, self.getContext() ) ];
1060 :
1061 30 : modRef_decl =
1062 : lexeme_d[ +( range_p('0','9') ) ];
1063 :
1064 90 : modifierReference =
1065 90 : (str_p( "$" ) >> modRef_decl )[ EnumFunctor( ENUM_FUNC_ADJUSTMENT, self.getContext() ) ];
1066 :
1067 60 : basicExpression =
1068 30 : real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
1069 : | identifier
1070 : | functionReference
1071 : | modifierReference
1072 : | unaryFunction
1073 : | binaryFunction
1074 : | ternaryFunction
1075 60 : | '(' >> additiveExpression >> ')'
1076 : ;
1077 :
1078 90 : unaryExpression =
1079 60 : ('-' >> basicExpression)[ UnaryFunctionFunctor( UNARY_FUNC_NEG, self.getContext()) ]
1080 : | basicExpression
1081 : ;
1082 :
1083 120 : multiplicativeExpression =
1084 : unaryExpression
1085 60 : >> *( ('*' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_MUL, self.getContext()) ]
1086 60 : | ('/' >> unaryExpression)[ BinaryFunctionFunctor( BINARY_FUNC_DIV, self.getContext()) ]
1087 : )
1088 : ;
1089 :
1090 120 : additiveExpression =
1091 : multiplicativeExpression
1092 60 : >> *( ('+' >> multiplicativeExpression)[ BinaryFunctionFunctor( BINARY_FUNC_PLUS, self.getContext()) ]
1093 60 : | ('-' >> 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 30 : }
1106 :
1107 259848 : const ::boost::spirit::rule< ScannerT >& start() const
1108 : {
1109 259848 : 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 930 : const ParserContextSharedPtr& getContext() const
1130 : {
1131 930 : return mpParserContext;
1132 : }
1133 :
1134 : private:
1135 : ParserContextSharedPtr mpParserContext; // might get modified during parsing
1136 : };
1137 :
1138 : #ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
1139 259848 : const ParserContextSharedPtr& getParserContext()
1140 : {
1141 259848 : 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 779514 : while( !lcl_parserContext->maOperandStack.empty() )
1146 259818 : lcl_parserContext->maOperandStack.pop();
1147 :
1148 259848 : return lcl_parserContext;
1149 : }
1150 : #endif
1151 :
1152 : }
1153 :
1154 : namespace EnhancedCustomShape {
1155 :
1156 :
1157 :
1158 259848 : 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 259848 : OUStringToOString( rFunction, RTL_TEXTENCODING_ASCII_US ) );
1165 :
1166 259848 : StringIteratorT aStart( rAsciiFunction.getStr() );
1167 259848 : StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() );
1168 :
1169 519696 : 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 259848 : pContext = getParserContext();
1175 : #else
1176 : pContext.reset( new ParserContext() );
1177 : #endif
1178 259848 : pContext->mpCustoShape = &rCustoShape;
1179 :
1180 519696 : ExpressionGrammar aExpressionGrammer( pContext );
1181 : const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
1182 : ::boost::spirit::parse( aStart,
1183 : aEnd,
1184 519696 : aExpressionGrammer >> ::boost::spirit::end_p,
1185 259848 : ::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 259848 : 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 259848 : if( pContext->maOperandStack.size() != 1 )
1198 0 : throw ParseError( "EnhancedCustomShapeFunctionParser::parseFunction(): incomplete or empty expression" );
1199 :
1200 :
1201 519696 : return pContext->maOperandStack.top();
1202 : }
1203 :
1204 :
1205 651 : }
1206 :
1207 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|