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