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