xref: /trunk/main/svx/source/customshapes/EnhancedCustomShape2d.cxx (revision fdf35928d88cfd82963a58c9928d6a5ce4934096)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include "svx/EnhancedCustomShape2d.hxx"
27 #include "svx/EnhancedCustomShapeGeometry.hxx"
28 #include "svx/EnhancedCustomShapeTypeNames.hxx"
29 #include <svx/svdoashp.hxx>
30 #include <svx/svdtrans.hxx>
31 #include <svx/svdocirc.hxx>
32 #include <svx/svdogrp.hxx>
33 #include <svx/svdopath.hxx>
34 #ifndef _SVDOCAPT_HXX
35 #include <svx/svdocapt.hxx>
36 #endif
37 #include <svx/svdpage.hxx>
38 #include <svx/xflclit.hxx>
39 #include <svx/sdasaitm.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <rtl/crc.h>
42 #include <rtl/math.hxx>
43 #include <svx/xfillit0.hxx>
44 #include <svx/xlnstit.hxx>
45 #include <svx/xlnedit.hxx>
46 #include <svx/xlnstwit.hxx>
47 #include <svx/xlnedwit.hxx>
48 #include <svx/xlnstcit.hxx>
49 #include <svx/xlnedcit.hxx>
50 #include <svx/xflgrit.hxx>
51 #include <svx/xflhtit.hxx>
52 #include <svx/xbtmpit.hxx>
53 #include <svx/xgrad.hxx>
54 #include <svx/xhatch.hxx>
55 #include <com/sun/star/awt/Size.hpp>
56 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
57 #ifndef __COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPESEGMENTCOMMAND_HPP__
58 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
59 #endif
60 #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
61 #include <boost/shared_ptr.hpp>
62 #endif
63 #include <basegfx/numeric/ftools.hxx>
64 #include <basegfx/color/bcolortools.hxx>
65 #include <basegfx/polygon/b2dpolygon.hxx>
66 
67 // #i76201#
68 #include <basegfx/polygon/b2dpolygontools.hxx>
69 
70 #include <math.h>
71 
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::drawing;
74 using namespace ::com::sun::star::drawing::EnhancedCustomShapeSegmentCommand;
75 
76 void EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nValue )
77 {
78     sal_uInt32 nDat = (sal_uInt32)nValue;
79     sal_Int32  nNewValue = nValue;
80 
81     // check if this is a special point
82     if ( ( nDat >> 16 ) == 0x8000 )
83     {
84         nNewValue = (sal_uInt16)nDat;
85         rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
86     }
87     else
88         rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
89     rParameter.Value <<= nNewValue;
90 }
91 
92 rtl::OUString EnhancedCustomShape2d::GetEquation( const sal_uInt16 nFlags, sal_Int16 nP1, sal_Int16 nP2, sal_Int16 nP3 )
93 {
94     rtl::OUString aEquation;
95     sal_Bool b1Special = ( nFlags & 0x2000 ) != 0;
96     sal_Bool b2Special = ( nFlags & 0x4000 ) != 0;
97     sal_Bool b3Special = ( nFlags & 0x8000 ) != 0;
98     switch( nFlags & 0xff )
99     {
100         case 0 :
101         case 14 :
102         {
103             sal_Int32 nOptimize = 0;
104             if ( nP1 )
105                 nOptimize |= 1;
106             if ( nP2 )
107                 nOptimize |= 2;
108             if ( b1Special )
109                 nOptimize |= 4;
110             if ( b2Special )
111                 nOptimize |= 8;
112             switch( nOptimize )
113             {
114                 case 0 :
115                 break;
116                 case 1 :
117                 case 4 :
118                 case 5 :
119                     EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
120                 break;
121                 case 2 :
122                 case 8 :
123                 case 10:
124                     EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
125                 break;
126                 default :
127                 {
128                     EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
129                     aEquation += rtl::OUString( (sal_Unicode)'+' );
130                     EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
131                 }
132                 break;
133             }
134             if ( b3Special || nP3 )
135             {
136                 aEquation += rtl::OUString( (sal_Unicode)'-' );
137                 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
138             }
139         }
140         break;
141         case 1 :
142         {
143             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
144             if ( b2Special || ( nP2 != 1 ) )
145             {
146                 aEquation += rtl::OUString( (sal_Unicode)'*' );
147                 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
148             }
149             if ( b3Special || ( ( nP3 != 1 ) && ( nP3 != 0 ) ) )
150             {
151                 aEquation += rtl::OUString( (sal_Unicode)'/' );
152                 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
153             }
154         }
155         break;
156         case 2 :
157         {
158             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "(" ) );
159             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
160             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "+" ) );
161             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
162             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")/2" ) );
163         }
164         break;
165         case 3 :
166         {
167             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "abs(" ) );
168             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
169             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
170         }
171         break;
172         case 4 :
173         {
174             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "min(" ) );
175             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
176             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
177             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
178             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
179         }
180         break;
181         case 5 :
182         {
183             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "max(" ) );
184             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
185             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
186             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
187             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
188         }
189         break;
190         case 6 :
191         {
192             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "if(" ) );
193             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
194             aEquation += rtl::OUString( (sal_Unicode)',' );
195             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
196             aEquation += rtl::OUString( (sal_Unicode)',' );
197             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
198             aEquation += rtl::OUString( (sal_Unicode)')' );
199         }
200         break;
201         case 7 :
202         {
203             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sqrt(" ) );
204             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
205             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
206             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
207             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "+" ) );
208             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
209             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
210             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
211             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "+" ) );
212             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
213             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
214             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
215             aEquation += rtl::OUString( (sal_Unicode)')' );
216         }
217         break;
218         case 8 :
219         {
220             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "atan2(" ) );
221             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
222             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
223             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
224             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")/(pi/180)" ) );
225         }
226         break;
227         case 9 :
228         {
229             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
230             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*sin(" ) );
231             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
232             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))" ) );
233         }
234         break;
235         case 10 :
236         {
237             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
238             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*cos(" ) );
239             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
240             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))" ) );
241         }
242         break;
243         case 11 :
244         {
245             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
246             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
247             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "cos(atan2(" ) );
248             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
249             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
250             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
251             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "))" ) );
252         }
253         break;
254         case 12 :
255         {
256             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
257             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
258             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sin(atan2(" ) );
259             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
260             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
261             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
262             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "))" ) );
263         }
264         break;
265         case 13 :
266         {
267             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sqrt(" ) );
268             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
269             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
270         }
271         break;
272         case 15 :
273         {
274             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
275             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*sqrt(1-(" ) );
276             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
277             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
278             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
279             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
280             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(" ) );
281             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
282             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
283             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
284             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "))" ) );
285         }
286         break;
287         case 16 :
288         {
289             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
290             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*tan(" ) );
291             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
292             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
293         }
294         break;
295         case 0x80 :
296         {
297             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sqrt(" ) );
298             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
299             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
300             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
301             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-" ) );
302             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
303             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
304             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
305             aEquation += rtl::OUString( (sal_Unicode)')' );
306         }
307         break;
308         case 0x81 :
309         {
310             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "(cos(" ) );
311             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
312             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
313             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
314             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800)+sin(" ) );
315             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
316             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
317             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
318             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800))+10800" ) );
319         }
320         break;
321         case 0x82 :
322         {
323             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-(sin(" ) );
324             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
325             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
326             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
327             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800)-cos(" ) );
328             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
329             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
330             EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
331             aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800))+10800" ) );
332         }
333         break;
334     }
335     return aEquation;
336 }
337 
338 void EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( rtl::OUString& rParameter, const sal_Int16 nPara, const sal_Bool bIsSpecialValue )
339 {
340     if ( bIsSpecialValue )
341     {
342         if ( nPara & 0x400 )
343         {
344             rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "?" ) );
345             rParameter += rtl::OUString::valueOf( (sal_Int32)( nPara & 0xff ) );
346             rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( " " ) );
347         }
348         else
349         {
350             switch( nPara )
351             {
352                 case DFF_Prop_adjustValue :
353                 case DFF_Prop_adjust2Value :
354                 case DFF_Prop_adjust3Value :
355                 case DFF_Prop_adjust4Value :
356                 case DFF_Prop_adjust5Value :
357                 case DFF_Prop_adjust6Value :
358                 case DFF_Prop_adjust7Value :
359                 case DFF_Prop_adjust8Value :
360                 case DFF_Prop_adjust9Value :
361                 case DFF_Prop_adjust10Value :
362                 {
363                     rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "$" ) );
364                     rParameter += rtl::OUString::valueOf( (sal_Int32)( nPara - DFF_Prop_adjustValue ) );
365                     rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( " " ) );
366                 }
367                 break;
368                 case DFF_Prop_geoLeft :
369                 {
370                     rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "left" ) );
371                 }
372                 break;
373                 case DFF_Prop_geoTop :
374                 {
375                     rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "top" ) );
376                 }
377                 break;
378                 case DFF_Prop_geoRight :
379                 {
380                     rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "right" ) );
381                 }
382                 break;
383                 case DFF_Prop_geoBottom :
384                 {
385                     rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "bottom" ) );
386                 }
387                 break;
388             }
389         }
390     }
391     else
392     {
393         rParameter += rtl::OUString::valueOf( (sal_Int32)( nPara ) );
394     }
395 }
396 
397 void EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nPara, const sal_Bool bIsSpecialValue, sal_Bool bHorz )
398 {
399     sal_Int32 nValue = 0;
400     if ( bIsSpecialValue )
401     {
402         if ( ( nPara >= 0x100 ) && ( nPara <= 0x107 ) )
403         {
404             nValue = nPara & 0xff;
405             rParameter.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
406         }
407         else if ( ( nPara >= 3 ) && ( nPara <= 0x82 ) )
408         {
409             nValue = nPara - 3;
410             rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
411         }
412         else if ( nPara == 0 )
413         {
414             nValue = 0;
415             if ( bHorz )
416                 rParameter.Type = EnhancedCustomShapeParameterType::LEFT;
417             else
418                 rParameter.Type = EnhancedCustomShapeParameterType::TOP;
419         }
420         else if ( nPara == 1 )
421         {
422             nValue = 0;
423             if ( bHorz )
424                 rParameter.Type = EnhancedCustomShapeParameterType::RIGHT;
425             else
426                 rParameter.Type = EnhancedCustomShapeParameterType::BOTTOM;
427         }
428         else if ( nPara == 2 )  // means to be centered, but should not be
429         {                       // used in our implementation
430             nValue = 5600;
431             rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
432         }
433         else
434         {
435             nValue = nPara;
436             rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
437         }
438     }
439     else
440     {
441         nValue = nPara;
442         rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
443     }
444     rParameter.Value <<= nValue;
445 }
446 
447 sal_Bool EnhancedCustomShape2d::ConvertSequenceToEnhancedCustomShape2dHandle(
448     const com::sun::star::beans::PropertyValues& rHandleProperties,
449         EnhancedCustomShape2d::Handle& rDestinationHandle )
450 {
451     sal_Bool bRetValue = sal_False;
452     sal_uInt32 i, nProperties = rHandleProperties.getLength();
453     if ( nProperties )
454     {
455         rDestinationHandle.nFlags = 0;
456         for ( i = 0; i < nProperties; i++ )
457         {
458             const com::sun::star::beans::PropertyValue& rPropVal = rHandleProperties[ i ];
459 
460             const rtl::OUString sPosition           ( RTL_CONSTASCII_USTRINGPARAM( "Position" ) );
461             const rtl::OUString sMirroredX          ( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) );
462             const rtl::OUString sMirroredY          ( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) );
463             const rtl::OUString sSwitched           ( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) );
464             const rtl::OUString sPolar              ( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) );
465 //          const rtl::OUString sMap                ( RTL_CONSTASCII_USTRINGPARAM( "Map" ) );
466             const rtl::OUString sRefX               ( RTL_CONSTASCII_USTRINGPARAM( "RefX" ) );
467             const rtl::OUString sRefY               ( RTL_CONSTASCII_USTRINGPARAM( "RefY" ) );
468             const rtl::OUString sRefAngle           ( RTL_CONSTASCII_USTRINGPARAM( "RefAngle" ) );
469             const rtl::OUString sRefR               ( RTL_CONSTASCII_USTRINGPARAM( "RefR" ) );
470             const rtl::OUString sRadiusRangeMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) );
471             const rtl::OUString sRadiusRangeMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) );
472             const rtl::OUString sRangeXMinimum      ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) );
473             const rtl::OUString sRangeXMaximum      ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) );
474             const rtl::OUString sRangeYMinimum      ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) );
475             const rtl::OUString sRangeYMaximum      ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) );
476 
477             if ( rPropVal.Name.equals( sPosition ) )
478             {
479                 if ( rPropVal.Value >>= rDestinationHandle.aPosition )
480                     bRetValue = sal_True;
481             }
482             else if ( rPropVal.Name.equals( sMirroredX ) )
483             {
484                 sal_Bool bMirroredX = sal_Bool();
485                 if ( rPropVal.Value >>= bMirroredX )
486                 {
487                     if ( bMirroredX )
488                         rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_X;
489                 }
490             }
491             else if ( rPropVal.Name.equals( sMirroredY ) )
492             {
493                 sal_Bool bMirroredY = sal_Bool();
494                 if ( rPropVal.Value >>= bMirroredY )
495                 {
496                     if ( bMirroredY )
497                         rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_Y;
498                 }
499             }
500             else if ( rPropVal.Name.equals( sSwitched ) )
501             {
502                 sal_Bool bSwitched = sal_Bool();
503                 if ( rPropVal.Value >>= bSwitched )
504                 {
505                     if ( bSwitched )
506                         rDestinationHandle.nFlags |= HANDLE_FLAGS_SWITCHED;
507                 }
508             }
509             else if ( rPropVal.Name.equals( sPolar ) )
510             {
511                 if ( rPropVal.Value >>= rDestinationHandle.aPolar )
512                     rDestinationHandle.nFlags |= HANDLE_FLAGS_POLAR;
513             }
514 /* seems not to be used.
515             else if ( rPropVal.Name.equals( sMap ) )
516             {
517                 com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap;
518                 if ( rPropVal.Value >>= aMap )
519                 {
520                     if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) )
521                         rDestinationHandle.Flags |= 0x800;
522                     if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) )
523                         rDestinationHandle.Flags |= 0x1000;
524                     rDestinationHandle.Flags |= 0x10;
525                 }
526             }
527 */
528             else if ( rPropVal.Name.equals( sRefX ) )
529             {
530                 if ( rPropVal.Value >>= rDestinationHandle.nRefX )
531                     rDestinationHandle.nFlags |= HANDLE_FLAGS_REFX;
532             }
533             else if ( rPropVal.Name.equals( sRefY ) )
534             {
535                 if ( rPropVal.Value >>= rDestinationHandle.nRefY )
536                     rDestinationHandle.nFlags |= HANDLE_FLAGS_REFY;
537             }
538             else if ( rPropVal.Name.equals( sRefAngle ) )
539             {
540                 if ( rPropVal.Value >>= rDestinationHandle.nRefAngle )
541                     rDestinationHandle.nFlags |= HANDLE_FLAGS_REFANGLE;
542             }
543             else if ( rPropVal.Name.equals( sRefR ) )
544             {
545                 if ( rPropVal.Value >>= rDestinationHandle.nRefR )
546                     rDestinationHandle.nFlags |= HANDLE_FLAGS_REFR;
547             }
548             else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) )
549             {
550                 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMinimum )
551                     rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MINIMUM;
552             }
553             else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) )
554             {
555                 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMaximum )
556                     rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM;
557             }
558             else if ( rPropVal.Name.equals( sRangeXMinimum ) )
559             {
560                 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMinimum )
561                     rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MINIMUM;
562             }
563             else if ( rPropVal.Name.equals( sRangeXMaximum ) )
564             {
565                 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMaximum )
566                     rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MAXIMUM;
567             }
568             else if ( rPropVal.Name.equals( sRangeYMinimum ) )
569             {
570                 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMinimum )
571                     rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MINIMUM;
572             }
573             else if ( rPropVal.Name.equals( sRangeYMaximum ) )
574             {
575                 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMaximum )
576                     rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MAXIMUM;
577             }
578         }
579     }
580     return bRetValue;
581 }
582 
583 const sal_Int32* EnhancedCustomShape2d::ApplyShapeAttributes( const SdrCustomShapeGeometryItem& rGeometryItem )
584 {
585     const sal_Int32* pDefData = NULL;
586     const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
587     if ( pDefCustomShape )
588         pDefData = pDefCustomShape->pDefData;
589 
590     //////////////////////
591     // AdjustmentValues //
592     //////////////////////
593     const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
594     const Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sAdjustmentValues );
595     if ( pAny )
596         *pAny >>= seqAdjustmentValues;
597 
598     ///////////////
599     // Coordsize //
600     ///////////////
601     const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) );
602     const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
603     com::sun::star::awt::Rectangle aViewBox;
604     if ( pViewBox && (*pViewBox >>= aViewBox ) )
605     {
606         nCoordLeft  = aViewBox.X;
607         nCoordTop   = aViewBox.Y;
608         nCoordWidth = labs( aViewBox.Width );
609         nCoordHeight= labs( aViewBox.Height);
610     }
611     const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) );
612 
613     //////////////////////
614     // Path/Coordinates //
615     //////////////////////
616     const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) );
617     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
618     if ( pAny )
619         *pAny >>= seqCoordinates;
620 
621     /////////////////////
622     // Path/GluePoints //
623     /////////////////////
624     const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) );
625     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
626     if ( pAny )
627         *pAny >>= seqGluePoints;
628 
629     ///////////////////
630     // Path/Segments //
631     ///////////////////
632     const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) );
633     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSegments );
634     if ( pAny )
635         *pAny >>= seqSegments;
636 
637     ///////////////////
638     // Path/StretchX //
639     ///////////////////
640     const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) );
641     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchX );
642     if ( pAny )
643     {
644         sal_Int32 nStretchX = 0;
645         if ( *pAny >>= nStretchX )
646             nXRef = nStretchX;
647     }
648 
649     ///////////////////
650     // Path/StretchY //
651     ///////////////////
652     const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) );
653     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchY );
654     if ( pAny )
655     {
656         sal_Int32 nStretchY = 0;
657         if ( *pAny >>= nStretchY )
658             nYRef = nStretchY;
659     }
660 
661     /////////////////////
662     // Path/TextFrames //
663     /////////////////////
664     const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) );
665     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
666     if ( pAny )
667         *pAny >>= seqTextFrames;
668 
669     ///////////////
670     // Equations //
671     ///////////////
672     const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
673     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
674     if ( pAny )
675         *pAny >>= seqEquations;
676 
677     /////////////
678     // Handles //
679     /////////////
680     const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
681     pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sHandles );
682     if ( pAny )
683         *pAny >>= seqHandles;
684 
685     return pDefData;
686 }
687 
688 EnhancedCustomShape2d::~EnhancedCustomShape2d()
689 {
690 }
691 
692 EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
693     SfxItemSet          ( pAObj->GetMergedItemSet() ),
694     pCustomShapeObj     ( pAObj ),
695     eSpType             ( mso_sptNil ),
696     nCoordLeft          ( 0 ),
697     nCoordTop           ( 0 ),
698     nCoordWidth         ( 21600 ),
699     nCoordHeight        ( 21600 ),
700     nXRef               ( 0x80000000 ),
701     nYRef               ( 0x80000000 ),
702     nFlags              ( 0 ),
703     nColorData          ( 0 ),
704     bTextFlow           ( sal_False ),
705     bFilled             ( ((const XFillStyleItem&)pAObj->GetMergedItem( XATTR_FILLSTYLE )).GetValue() != XFILL_NONE ),
706     bStroked            ( ((const XLineStyleItem&)pAObj->GetMergedItem( XATTR_LINESTYLE )).GetValue() != XLINE_NONE ),
707     bFlipH              ( sal_False ),
708     bFlipV              ( sal_False )
709 {
710     // bTextFlow needs to be set before clearing the TextDirection Item
711 
712     ClearItem( SDRATTR_TEXTDIRECTION ); //SJ: vertical writing is not required, by removing this item no outliner is created
713 
714     // #i105323# For 2D AtoShapes, the shadow attirbute does not need to be applied to any
715     // of the constucted helper SdrObjects. This would lead to problems since the shadow
716     // of one helper object would fall on one helper object behind it (e.g. with the
717     // eyes of the smiley shape). This is not wanted; instead a single shadow 'behind'
718     // the AutoShape visualisation is wanted. This is done with primitive functionailty
719     // now in SdrCustomShapePrimitive2D::create2DDecomposition, but only for 2D objects
720     // (see there and in EnhancedCustomShape3d::Create3DObject to read more).
721     // This exception may be removed later when AutoShapes will create primitives directly.
722     // So, currently remove the ShadowAttribute from the ItemSet to not apply it to any
723     // 2D helper shape.
724     ClearItem(SDRATTR_SHADOW);
725 
726     Point aP( pCustomShapeObj->GetSnapRect().Center() );
727     Size aS( pCustomShapeObj->GetLogicRect().GetSize() );
728     aP.X() -= aS.Width() / 2;
729     aP.Y() -= aS.Height() / 2;
730     aLogicRect = Rectangle( aP, aS );
731 
732     const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
733     const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
734     const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
735 
736     rtl::OUString sShapeType;
737     SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
738     Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
739     if ( pAny )
740         *pAny >>= sShapeType;
741     eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
742 
743     pAny = rGeometryItem.GetPropertyValueByName( sMirroredX );
744     if ( pAny )
745         *pAny >>= bFlipH;
746     pAny = rGeometryItem.GetPropertyValueByName( sMirroredY );
747     if ( pAny )
748         *pAny >>= bFlipV;
749 
750     if ( pCustomShapeObj->ISA( SdrObjCustomShape ) )    // should always be a SdrObjCustomShape, but you don't know
751         nRotateAngle = (sal_Int32)(((SdrObjCustomShape*)pCustomShapeObj)->GetObjectRotation() * 100.0);
752     else
753         nRotateAngle = pCustomShapeObj->GetRotateAngle();
754 
755     /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem );
756     switch( eSpType )
757     {
758         case mso_sptCan :                       nColorData = 0x20400000; break;
759         case mso_sptCube :                      nColorData = 0x302e0000; break;
760         case mso_sptActionButtonBlank :         nColorData = 0x502ce400; break;
761         case mso_sptActionButtonHome :          nColorData = 0x702ce4ce; break;
762         case mso_sptActionButtonHelp :          nColorData = 0x602ce4c0; break;
763         case mso_sptActionButtonInformation :   nColorData = 0x702ce4c5; break;
764         case mso_sptActionButtonBackPrevious :  nColorData = 0x602ce4c0; break;
765         case mso_sptActionButtonForwardNext :   nColorData = 0x602ce4c0; break;
766         case mso_sptActionButtonBeginning :     nColorData = 0x602ce4c0; break;
767         case mso_sptActionButtonEnd :           nColorData = 0x602ce4c0; break;
768         case mso_sptActionButtonReturn :        nColorData = 0x602ce4c0; break;
769         case mso_sptActionButtonDocument :      nColorData = 0x702ce4ec; break;
770         case mso_sptActionButtonSound :         nColorData = 0x602ce4c0; break;
771         case mso_sptActionButtonMovie :         nColorData = 0x602ce4c0; break;
772         case mso_sptBevel :                     nColorData = 0x502ce400; break;
773         case mso_sptFoldedCorner :              nColorData = 0x20e00000; break;
774         case mso_sptSmileyFace :                nColorData = 0x20e00000; break;
775         case mso_sptNil :
776         {
777             if( sShapeType.getLength() > 4 &&
778                 sShapeType.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "col-" )))
779             {
780                 nColorData = sShapeType.copy( 4 ).toInt32( 16 );
781             }
782         }
783         break;
784         case mso_sptCurvedLeftArrow :
785         case mso_sptCurvedRightArrow :
786         case mso_sptCurvedUpArrow :
787         case mso_sptCurvedDownArrow :           nColorData = 0x20d00000; break;
788         case mso_sptRibbon2 :                   nColorData = 0x30ee0000; break;
789         case mso_sptRibbon :                    nColorData = 0x30ee0000; break;
790 
791         case mso_sptEllipseRibbon2 :            nColorData = 0x30ee0000; break;
792         case mso_sptEllipseRibbon :             nColorData = 0x30ee0000; break;
793 
794         case mso_sptVerticalScroll :            nColorData = 0x30ee0000; break;
795         case mso_sptHorizontalScroll :          nColorData = 0x30ee0000; break;
796         default:
797             break;
798     }
799     fXScale = nCoordWidth == 0 ? 0.0 : (double)aLogicRect.GetWidth() / (double)nCoordWidth;
800     fYScale = nCoordHeight == 0 ? 0.0 : (double)aLogicRect.GetHeight() / (double)nCoordHeight;
801     if ( (sal_uInt32)nXRef != 0x80000000 && aLogicRect.GetHeight() )
802     {
803         fXRatio = (double)aLogicRect.GetWidth() / (double)aLogicRect.GetHeight();
804         if ( fXRatio > 1 )
805             fXScale /= fXRatio;
806         else
807             fXRatio = 1.0;
808     }
809     else
810         fXRatio = 1.0;
811     if ( (sal_uInt32)nYRef != 0x80000000 && aLogicRect.GetWidth() )
812     {
813         fYRatio = (double)aLogicRect.GetHeight() / (double)aLogicRect.GetWidth();
814         if ( fYRatio > 1 )
815             fYScale /= fYRatio;
816         else
817             fYRatio = 1.0;
818     }
819     else
820         fYRatio = 1.0;
821 
822     sal_Int32 i, nLength = seqEquations.getLength();
823 
824 
825     if ( nLength )
826     {
827         vNodesSharedPtr.resize( nLength );
828         for ( i = 0; i < seqEquations.getLength(); i++ )
829         {
830             try
831             {
832                 vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
833             }
834             catch ( EnhancedCustomShape::ParseError& )
835             {
836             }
837         }
838     }
839 }
840 double EnhancedCustomShape2d::GetEnumFunc( const EnumFunc eFunc ) const
841 {
842     double fRet = 0.0;
843     switch( eFunc )
844     {
845         case ENUM_FUNC_PI :         fRet = F_PI; break;
846         case ENUM_FUNC_LEFT :       fRet = 0.0; break;
847         case ENUM_FUNC_TOP :        fRet = 0.0; break;
848         case ENUM_FUNC_RIGHT :      fRet = (double)nCoordWidth * fXRatio;   break;
849         case ENUM_FUNC_BOTTOM :     fRet = (double)nCoordHeight * fYRatio; break;
850         case ENUM_FUNC_XSTRETCH :   fRet = nXRef; break;
851         case ENUM_FUNC_YSTRETCH :   fRet = nYRef; break;
852         case ENUM_FUNC_HASSTROKE :  fRet = bStroked ? 1.0 : 0.0; break;
853         case ENUM_FUNC_HASFILL :    fRet = bFilled ? 1.0 : 0.0; break;
854         case ENUM_FUNC_WIDTH :      fRet = nCoordWidth; break;
855         case ENUM_FUNC_HEIGHT :     fRet = nCoordHeight; break;
856         case ENUM_FUNC_LOGWIDTH :   fRet = aLogicRect.GetWidth(); break;
857         case ENUM_FUNC_LOGHEIGHT :  fRet = aLogicRect.GetHeight(); break;
858     }
859     return fRet;
860 }
861 double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex ) const
862 {
863     double fNumber = 0.0;
864     if ( nIndex < seqAdjustmentValues.getLength() )
865     {
866         if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
867             seqAdjustmentValues[ nIndex ].Value >>= fNumber;
868         else
869         {
870             sal_Int32 nNumber = 0;
871             seqAdjustmentValues[ nIndex ].Value >>= nNumber;
872             fNumber = (double)nNumber;
873         }
874     }
875     return fNumber;
876 }
877 double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
878 {
879     double fNumber = 0.0;
880     if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
881     {
882         if ( vNodesSharedPtr[ nIndex ].get() )
883         try
884         {
885             fNumber = (*vNodesSharedPtr[ nIndex ])();
886             if ( !rtl::math::isFinite( fNumber ) )
887                 fNumber = 0.0;
888         }
889         catch ( ... )
890         {
891             /* sal_Bool bUps = sal_True; */
892         }
893     }
894     return fNumber;
895 }
896 sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
897 {
898     sal_Int32 nNumber = nDefault;
899     if ( nIndex < seqAdjustmentValues.getLength() )
900     {
901         if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
902         {
903             double fNumber = 0;
904             seqAdjustmentValues[ nIndex ].Value >>= fNumber;
905             nNumber = (sal_Int32)fNumber;
906         }
907         else
908             seqAdjustmentValues[ nIndex ].Value >>= nNumber;
909     }
910     return nNumber;
911 }
912 sal_Bool EnhancedCustomShape2d::SetAdjustValueAsDouble( const double& rValue, const sal_Int32 nIndex )
913 {
914     sal_Bool bRetValue = sal_False;
915     if ( nIndex < seqAdjustmentValues.getLength() )
916     {
917         // updating our local adjustment sequence
918         seqAdjustmentValues[ nIndex ].Value <<= rValue;
919         seqAdjustmentValues[ nIndex ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
920         bRetValue = sal_True;
921     }
922     return bRetValue;
923 }
924 
925 Point EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair& rPair,
926                                         const sal_Bool bScale, const sal_Bool bReplaceGeoSize ) const
927 {
928     Point       aRetValue;
929     sal_Bool    bExchange = ( nFlags & DFF_CUSTOMSHAPE_EXCH ) != 0; // x <-> y
930     sal_uInt32  nPass = 0;
931     do
932     {
933         sal_uInt32  nIndex = nPass;
934 
935         if ( bExchange )
936             nIndex ^= 1;
937 
938         double      fVal;
939         const EnhancedCustomShapeParameter& rParameter = nIndex ? rPair.Second : rPair.First;
940         if ( nPass )    // height
941         {
942             GetParameter( fVal, rParameter, sal_False, bReplaceGeoSize );
943             fVal -= nCoordTop;
944             if ( bScale )
945             {
946                 fVal *= fYScale;
947 
948                 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_V )
949                     fVal = aLogicRect.GetHeight() - fVal;
950             }
951             aRetValue.Y() = (sal_Int32)fVal;
952         }
953         else            // width
954         {
955             GetParameter( fVal, rParameter, bReplaceGeoSize, sal_False );
956             fVal -= nCoordLeft;
957             if ( bScale )
958             {
959                 fVal *= fXScale;
960 
961                 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_H )
962                     fVal = aLogicRect.GetWidth() - fVal;
963             }
964             aRetValue.X() = (sal_Int32)fVal;
965         }
966     }
967     while ( ++nPass < 2 );
968     return aRetValue;
969 }
970 
971 sal_Bool EnhancedCustomShape2d::GetParameter( double& rRetValue, const EnhancedCustomShapeParameter& rParameter,
972                                                 const sal_Bool bReplaceGeoWidth, const sal_Bool bReplaceGeoHeight ) const
973 {
974     rRetValue = 0.0;
975     sal_Bool bRetValue = sal_False;
976     switch ( rParameter.Type )
977     {
978         case EnhancedCustomShapeParameterType::ADJUSTMENT :
979         {
980             sal_Int32 nAdjustmentIndex = 0;
981             if ( rParameter.Value >>= nAdjustmentIndex )
982             {
983                 rRetValue = GetAdjustValueAsDouble( nAdjustmentIndex );
984                 bRetValue = sal_True;
985             }
986         }
987         break;
988         case EnhancedCustomShapeParameterType::EQUATION :
989         {
990             sal_Int32 nEquationIndex = 0;
991             if ( rParameter.Value >>= nEquationIndex )
992             {
993                 rRetValue = GetEquationValueAsDouble( nEquationIndex );
994                 bRetValue = sal_True;
995             }
996         }
997         break;
998         case EnhancedCustomShapeParameterType::NORMAL :
999         {
1000             if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE )
1001             {
1002                 double fValue;
1003                 if ( rParameter.Value >>= fValue )
1004                 {
1005                     rRetValue = fValue;
1006                     bRetValue = sal_True;
1007                 }
1008             }
1009             else
1010             {
1011                 sal_Int32 nValue = 0;
1012                 if ( rParameter.Value >>= nValue )
1013                 {
1014                     rRetValue = nValue;
1015                     bRetValue = sal_True;
1016                     if ( bReplaceGeoWidth && ( nValue == nCoordWidth ) )
1017                         rRetValue *= fXRatio;
1018                     else if ( bReplaceGeoHeight && ( nValue == nCoordHeight ) )
1019                         rRetValue *= fYRatio;
1020                 }
1021             }
1022         }
1023         break;
1024         case EnhancedCustomShapeParameterType::LEFT :
1025         {
1026             rRetValue  = 0.0;
1027             bRetValue = sal_True;
1028         }
1029         break;
1030         case EnhancedCustomShapeParameterType::TOP :
1031         {
1032             rRetValue  = 0.0;
1033             bRetValue = sal_True;
1034         }
1035         break;
1036         case EnhancedCustomShapeParameterType::RIGHT :
1037         {
1038             rRetValue = nCoordWidth;
1039             bRetValue = sal_True;
1040         }
1041         break;
1042         case EnhancedCustomShapeParameterType::BOTTOM :
1043         {
1044             rRetValue = nCoordHeight;
1045             bRetValue = sal_True;
1046         }
1047         break;
1048     }
1049     return bRetValue;
1050 }
1051 
1052 // nLumDat 28-31 = number of luminance entries in nLumDat
1053 // nLumDat 27-24 = nLumDatEntry 0
1054 // nLumDat 23-20 = nLumDatEntry 1 ...
1055 // each 4bit entry is to be interpreted as a 10 percent signed luminance changing
1056 sal_Int32 EnhancedCustomShape2d::GetLuminanceChange( sal_uInt32 nIndex ) const
1057 {
1058     const sal_uInt32 nCount = nColorData >> 28;
1059     if ( !nCount )
1060         return 0;
1061 
1062     if ( nIndex >= nCount )
1063         nIndex = nCount - 1;
1064 
1065     const sal_Int32 nLumDat = nColorData << ( ( 1 + nIndex ) << 2 );
1066     return ( nLumDat >> 28 ) * 10;
1067 }
1068 
1069 Color EnhancedCustomShape2d::GetColorData( const Color& rFillColor, sal_uInt32 nIndex ) const
1070 {
1071     const sal_Int32 nLuminance = GetLuminanceChange(nIndex);
1072     if( !nLuminance )
1073         return rFillColor;
1074 
1075     basegfx::BColor aHSVColor=
1076         basegfx::tools::rgb2hsv(
1077             basegfx::BColor(rFillColor.GetRed()/255.0,
1078                             rFillColor.GetGreen()/255.0,
1079                             rFillColor.GetBlue()/255.0));
1080     if( nLuminance > 0 )
1081     {
1082         aHSVColor.setGreen(
1083             aHSVColor.getGreen() * (1.0-nLuminance/100.0));
1084         aHSVColor.setBlue(
1085             nLuminance/100.0 +
1086             (1.0-nLuminance/100.0)*aHSVColor.getBlue());
1087     }
1088     else if( nLuminance < 0 )
1089     {
1090         aHSVColor.setBlue(
1091             (1.0+nLuminance/100.0)*aHSVColor.getBlue());
1092     }
1093 
1094     aHSVColor = basegfx::tools::hsv2rgb(aHSVColor);
1095     return Color( (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(aHSVColor.getRed(),0.0,1.0) * 255.0 + 0.5 ),
1096                   (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(aHSVColor.getGreen(),0.0,1.0) * 255.0 + 0.5 ),
1097                   (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(aHSVColor.getBlue(),0.0,1.0) * 255.0 + 0.5 ) );
1098 }
1099 
1100 Rectangle EnhancedCustomShape2d::GetTextRect() const
1101 {
1102     sal_Int32 nIndex, nSize = seqTextFrames.getLength();
1103     if ( !nSize )
1104         return aLogicRect;
1105     nIndex = 0;
1106     if ( bTextFlow && ( nSize > 1 ) )
1107         nIndex++;
1108     Point aTopLeft( GetPoint( seqTextFrames[ nIndex ].TopLeft, sal_True, sal_True ) );
1109     Point aBottomRight( GetPoint( seqTextFrames[ nIndex ].BottomRight, sal_True, sal_True ) );
1110     if ( bFlipH )
1111     {
1112         aTopLeft.X() = aLogicRect.GetWidth() - aTopLeft.X();
1113         aBottomRight.X() = aLogicRect.GetWidth() - aBottomRight.X();
1114     }
1115     if ( bFlipV )
1116     {
1117         aTopLeft.Y() = aLogicRect.GetHeight() - aTopLeft.Y();
1118         aBottomRight.Y() = aLogicRect.GetHeight() - aBottomRight.Y();
1119     }
1120     Rectangle aRect( aTopLeft, aBottomRight );
1121     aRect.Move( aLogicRect.Left(), aLogicRect.Top() );
1122     aRect.Justify();
1123     return aRect;
1124 }
1125 
1126 sal_uInt32 EnhancedCustomShape2d::GetHdlCount() const
1127 {
1128     return seqHandles.getLength();
1129 }
1130 
1131 sal_Bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex, Point& rReturnPosition ) const
1132 {
1133     sal_Bool bRetValue = sal_False;
1134     if ( nIndex < GetHdlCount() )
1135     {
1136         Handle aHandle;
1137         if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1138         {
1139             if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1140             {
1141                 Point aReferencePoint( GetPoint( aHandle.aPolar, sal_True, sal_False ) );
1142 
1143                 double      fAngle;
1144                 double      fRadius;
1145                 GetParameter( fRadius, aHandle.aPosition.First, sal_False, sal_False );
1146                 GetParameter( fAngle,  aHandle.aPosition.Second, sal_False, sal_False );
1147 
1148                 double a = ( 360.0 - fAngle ) * F_PI180;
1149                 double dx = fRadius * fXScale;
1150                 double fX = dx * cos( a );
1151                 double fY =-dx * sin( a );
1152                 rReturnPosition =
1153                     Point(
1154                         Round( fX + aReferencePoint.X() ),
1155                         basegfx::fTools::equalZero(fXScale) ? aReferencePoint.Y() :
1156                         Round( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) );
1157             }
1158             else
1159             {
1160                 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1161                 {
1162                     if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1163                     {
1164                         com::sun::star::drawing::EnhancedCustomShapeParameter aFirst = aHandle.aPosition.First;
1165                         com::sun::star::drawing::EnhancedCustomShapeParameter aSecond = aHandle.aPosition.Second;
1166                         aHandle.aPosition.First = aSecond;
1167                         aHandle.aPosition.Second = aFirst;
1168                     }
1169                 }
1170                 rReturnPosition = GetPoint( aHandle.aPosition, sal_True, sal_False );
1171             }
1172             const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1173             if ( aGeoStat.nShearWink )
1174             {
1175                 double nTan = aGeoStat.nTan;
1176                 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1177                     nTan = -nTan;
1178                 ShearPoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1179             }
1180             if ( nRotateAngle )
1181             {
1182                 double a = nRotateAngle * F_PI18000;
1183                 RotatePoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1184             }
1185             if ( bFlipH )
1186                 rReturnPosition.X() = aLogicRect.GetWidth() - rReturnPosition.X();
1187             if ( bFlipV )
1188                 rReturnPosition.Y() = aLogicRect.GetHeight() - rReturnPosition.Y();
1189             rReturnPosition.Move( aLogicRect.Left(), aLogicRect.Top() );
1190             bRetValue = sal_True;
1191         }
1192     }
1193     return bRetValue;
1194 }
1195 
1196 sal_Bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex, const com::sun::star::awt::Point& rPosition )
1197 {
1198     sal_Bool bRetValue = sal_False;
1199     if ( nIndex < GetHdlCount() )
1200     {
1201         Handle aHandle;
1202         if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1203         {
1204             Point aP( rPosition.X, rPosition.Y );
1205             // apply the negative object rotation to the controller position
1206 
1207             aP.Move( -aLogicRect.Left(), -aLogicRect.Top() );
1208             if ( bFlipH )
1209                 aP.X() = aLogicRect.GetWidth() - aP.X();
1210             if ( bFlipV )
1211                 aP.Y() = aLogicRect.GetHeight() - aP.Y();
1212             if ( nRotateAngle )
1213             {
1214                 double a = -nRotateAngle * F_PI18000;
1215                 RotatePoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1216             }
1217             const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1218             if ( aGeoStat.nShearWink )
1219             {
1220                 double nTan = -aGeoStat.nTan;
1221                 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1222                     nTan = -nTan;
1223                 ShearPoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1224             }
1225 
1226             double fPos1 = aP.X();  //( bFlipH ) ? aLogicRect.GetWidth() - aP.X() : aP.X();
1227             double fPos2 = aP.Y();  //( bFlipV ) ? aLogicRect.GetHeight() -aP.Y() : aP.Y();
1228             fPos1 /= fXScale;
1229             fPos2 /= fYScale;
1230 
1231             if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1232             {
1233                 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1234                 {
1235                     double fX = fPos1;
1236                     double fY = fPos2;
1237                     fPos1 = fY;
1238                     fPos2 = fX;
1239                 }
1240             }
1241 
1242             sal_Int32 nFirstAdjustmentValue = -1, nSecondAdjustmentValue = -1;
1243 
1244             if ( aHandle.aPosition.First.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1245                 aHandle.aPosition.First.Value >>= nFirstAdjustmentValue;
1246             if ( aHandle.aPosition.Second.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1247                 aHandle.aPosition.Second.Value>>= nSecondAdjustmentValue;
1248 
1249             if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1250             {
1251                 double fXRef, fYRef, fAngle;
1252                 GetParameter( fXRef, aHandle.aPolar.First, sal_False, sal_False );
1253                 GetParameter( fYRef, aHandle.aPolar.Second, sal_False, sal_False );
1254                 const double fDX = fPos1 - fXRef;
1255                 fAngle = -( atan2( -fPos2 + fYRef, ( ( fDX == 0.0L ) ? 0.000000001 : fDX ) ) / F_PI180 );
1256                 double fX = ( fPos1 - fXRef );
1257                 double fY = ( fPos2 - fYRef );
1258                 double fRadius = sqrt( fX * fX + fY * fY );
1259                 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MINIMUM )
1260                 {
1261                     double fMin;
1262                     GetParameter( fMin,  aHandle.aRadiusRangeMinimum, sal_False, sal_False );
1263                     if ( fRadius < fMin )
1264                         fRadius = fMin;
1265                 }
1266                 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM )
1267                 {
1268                     double fMax;
1269                     GetParameter( fMax, aHandle.aRadiusRangeMaximum, sal_False, sal_False );
1270                     if ( fRadius > fMax )
1271                         fRadius = fMax;
1272                 }
1273                 if ( nFirstAdjustmentValue >= 0 )
1274                     SetAdjustValueAsDouble( fRadius, nFirstAdjustmentValue );
1275                 if ( nSecondAdjustmentValue >= 0 )
1276                     SetAdjustValueAsDouble( fAngle,  nSecondAdjustmentValue );
1277             }
1278             else
1279             {
1280                 if ( aHandle.nFlags & HANDLE_FLAGS_REFX )
1281                 {
1282                     nFirstAdjustmentValue = aHandle.nRefX;
1283                     fPos1 *= 100000.0;
1284                     fPos1 /= nCoordWidth;
1285                 }
1286                 if ( aHandle.nFlags & HANDLE_FLAGS_REFY )
1287                 {
1288                     nSecondAdjustmentValue = aHandle.nRefY;
1289                     fPos2 *= 100000.0;
1290                     fPos2 /= nCoordHeight;
1291                 }
1292                 if ( nFirstAdjustmentValue >= 0 )
1293                 {
1294                     if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MINIMUM )        // check if horizontal handle needs to be within a range
1295                     {
1296                         double fXMin;
1297                         GetParameter( fXMin, aHandle.aXRangeMinimum, sal_False, sal_False );
1298                         if ( fPos1 < fXMin )
1299                             fPos1 = fXMin;
1300                     }
1301                     if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MAXIMUM )        // check if horizontal handle needs to be within a range
1302                     {
1303                         double fXMax;
1304                         GetParameter( fXMax, aHandle.aXRangeMaximum, sal_False, sal_False );
1305                         if ( fPos1 > fXMax )
1306                             fPos1 = fXMax;
1307                     }
1308                     SetAdjustValueAsDouble( fPos1, nFirstAdjustmentValue );
1309                 }
1310                 if ( nSecondAdjustmentValue >= 0 )
1311                 {
1312                     if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MINIMUM )        // check if vertical handle needs to be within a range
1313                     {
1314                         double fYMin;
1315                         GetParameter( fYMin, aHandle.aYRangeMinimum, sal_False, sal_False );
1316                         if ( fPos2 < fYMin )
1317                             fPos2 = fYMin;
1318                     }
1319                     if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MAXIMUM )        // check if vertical handle needs to be within a range
1320                     {
1321                         double fYMax;
1322                         GetParameter( fYMax, aHandle.aYRangeMaximum, sal_False, sal_False );
1323                         if ( fPos2 > fYMax )
1324                             fPos2 = fYMax;
1325                     }
1326                     SetAdjustValueAsDouble( fPos2, nSecondAdjustmentValue );
1327                 }
1328             }
1329             // and writing them back into the GeometryItem
1330             SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)
1331                 (const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1332             const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
1333             com::sun::star::beans::PropertyValue aPropVal;
1334             aPropVal.Name = sAdjustmentValues;
1335             aPropVal.Value <<= seqAdjustmentValues;
1336             aGeometryItem.SetPropertyValue( aPropVal );
1337             pCustomShapeObj->SetMergedItem( aGeometryItem );
1338             bRetValue = sal_True;
1339         }
1340     }
1341     return bRetValue;
1342 }
1343 
1344 void EnhancedCustomShape2d::SwapStartAndEndArrow( SdrObject* pObj ) //#108274
1345 {
1346     XLineStartItem       aLineStart;
1347     aLineStart.SetLineStartValue(((XLineStartItem&)pObj->GetMergedItem( XATTR_LINEEND )).GetLineStartValue());
1348     XLineStartWidthItem  aLineStartWidth(((XLineStartWidthItem&)pObj->GetMergedItem( XATTR_LINEENDWIDTH )).GetValue());
1349     XLineStartCenterItem aLineStartCenter(((XLineStartCenterItem&)pObj->GetMergedItem( XATTR_LINEENDCENTER )).GetValue());
1350 
1351     XLineEndItem         aLineEnd;
1352     aLineEnd.SetLineEndValue(((XLineEndItem&)pObj->GetMergedItem( XATTR_LINESTART )).GetLineEndValue());
1353     XLineEndWidthItem    aLineEndWidth(((XLineEndWidthItem&)pObj->GetMergedItem( XATTR_LINESTARTWIDTH )).GetValue());
1354     XLineEndCenterItem   aLineEndCenter(((XLineEndCenterItem&)pObj->GetMergedItem( XATTR_LINESTARTCENTER )).GetValue());
1355 
1356     pObj->SetMergedItem( aLineStart );
1357     pObj->SetMergedItem( aLineStartWidth );
1358     pObj->SetMergedItem( aLineStartCenter );
1359     pObj->SetMergedItem( aLineEnd );
1360     pObj->SetMergedItem( aLineEndWidth );
1361     pObj->SetMergedItem( aLineEndCenter );
1362 }
1363 
1364 basegfx::B2DPolygon CreateArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, const sal_Bool bClockwise )
1365 {
1366     Rectangle aRect( rRect );
1367     Point aStart( rStart );
1368     Point aEnd( rEnd );
1369 
1370     sal_Int32 bSwapStartEndAngle = 0;
1371 
1372     if ( aRect.Left() > aRect.Right() )
1373         bSwapStartEndAngle ^= 0x01;
1374     if ( aRect.Top() > aRect.Bottom() )
1375         bSwapStartEndAngle ^= 0x11;
1376     if ( bSwapStartEndAngle )
1377     {
1378         aRect.Justify();
1379         if ( bSwapStartEndAngle & 1 )
1380         {
1381             Point aTmp( aStart );
1382             aStart = aEnd;
1383             aEnd = aTmp;
1384         }
1385     }
1386 
1387     Polygon aTempPoly( aRect, aStart, aEnd, POLY_ARC );
1388     basegfx::B2DPolygon aRetval;
1389 
1390     if ( bClockwise )
1391     {
1392         for ( sal_uInt16 j = aTempPoly.GetSize(); j--; )
1393         {
1394             aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1395         }
1396     }
1397     else
1398     {
1399         for ( sal_uInt16 j = 0; j < aTempPoly.GetSize(); j++ )
1400         {
1401             aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1402         }
1403     }
1404 
1405     return aRetval;
1406 }
1407 
1408 void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegmentInd, std::vector< SdrPathObj* >& rObjectList,
1409                                                                                         const sal_Bool bLineGeometryNeededOnly,
1410                                                                                         const sal_Bool bSortFilledObjectsToBack )
1411 {
1412     sal_Bool bNoFill = sal_False;
1413     sal_Bool bNoStroke = sal_False;
1414 
1415     basegfx::B2DPolyPolygon aNewB2DPolyPolygon;
1416     basegfx::B2DPolygon aNewB2DPolygon;
1417 
1418     sal_Int32 nCoordSize = seqCoordinates.getLength();
1419     sal_Int32 nSegInfoSize = seqSegments.getLength();
1420     if ( !nSegInfoSize )
1421     {
1422         const EnhancedCustomShapeParameterPair* pTmp = seqCoordinates.getArray();
1423 
1424         for ( sal_Int32 nPtNum(0L); nPtNum < nCoordSize; nPtNum++ )
1425         {
1426             const Point aTempPoint(GetPoint( *pTmp++, sal_True, sal_True ));
1427             aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1428         }
1429 
1430         aNewB2DPolygon.setClosed(true);
1431     }
1432     else
1433     {
1434         for ( ;rSegmentInd < nSegInfoSize; )
1435         {
1436             sal_Int16 nCommand = seqSegments[ rSegmentInd ].Command;
1437             sal_Int16 nPntCount= seqSegments[ rSegmentInd++ ].Count;
1438 
1439             switch ( nCommand )
1440             {
1441                 case NOFILL :
1442                     bNoFill = sal_True;
1443                 break;
1444                 case NOSTROKE :
1445                     bNoStroke = sal_True;
1446                 break;
1447                 case MOVETO :
1448                 {
1449                     if(aNewB2DPolygon.count() > 1L)
1450                     {
1451                         // #i76201# Add conversion to closed polygon when first and last points are equal
1452                         basegfx::tools::checkClosed(aNewB2DPolygon);
1453                         aNewB2DPolyPolygon.append(aNewB2DPolygon);
1454                     }
1455 
1456                     aNewB2DPolygon.clear();
1457 
1458                     if ( rSrcPt < nCoordSize )
1459                     {
1460                         const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1461                         aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1462                     }
1463                 }
1464                 break;
1465                 case ENDSUBPATH :
1466                 break;
1467                 case CLOSESUBPATH :
1468                 {
1469                     if(aNewB2DPolygon.count())
1470                     {
1471                         if(aNewB2DPolygon.count() > 1L)
1472                         {
1473                             aNewB2DPolygon.setClosed(true);
1474                             aNewB2DPolyPolygon.append(aNewB2DPolygon);
1475                         }
1476 
1477                         aNewB2DPolygon.clear();
1478                     }
1479                 }
1480                 break;
1481                 case CURVETO :
1482                 {
1483                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1484                     {
1485                         const Point aControlA(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1486                         const Point aControlB(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1487                         const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1488 
1489                         DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding control point (!)");
1490                         aNewB2DPolygon.appendBezierSegment(
1491                             basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1492                             basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1493                             basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1494                     }
1495                 }
1496                 break;
1497 
1498                 case ANGLEELLIPSE :
1499                 {
1500                     if(aNewB2DPolygon.count() > 1L)
1501                     {
1502                         // #i76201# Add conversion to closed polygon when first and last points are equal
1503                         basegfx::tools::checkClosed(aNewB2DPolygon);
1504                         aNewB2DPolyPolygon.append(aNewB2DPolygon);
1505                     }
1506 
1507                     aNewB2DPolygon.clear();
1508                 }
1509                 case ANGLEELLIPSETO :
1510                 {
1511                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1512                     {
1513                         // create a circle
1514                         Point _aCenter;
1515                         double fWidth, fHeight;
1516                         MSO_SPT eSpType = mso_sptEllipse;
1517                         const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
1518                         sal_Bool bIsDefaultViewBox = sal_False;
1519                         sal_Bool bIsDefaultPath = sal_False;
1520                         sal_Bool bIsMSEllipse = sal_False;
1521 
1522                         if( ( nCoordWidth == pDefCustomShape->nCoordWidth )
1523                             && ( nCoordHeight == pDefCustomShape->nCoordHeight ) )
1524                             bIsDefaultViewBox = sal_True;
1525                         sal_Int32 j, nCount = pDefCustomShape->nVertices;//==3
1526                         com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1527 
1528                         seqCoordinates1.realloc( nCount );
1529                         for ( j = 0; j < nCount; j++ )
1530                         {
1531                             seqCoordinates1[j] = seqCoordinates[ rSrcPt + j];
1532                         }
1533 
1534                         seqCoordinates2.realloc( nCount );
1535                         for ( j = 0; j < nCount; j++ )
1536                         {
1537                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].First, pDefCustomShape->pVertices[ j ].nValA );
1538                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].Second, pDefCustomShape->pVertices[ j ].nValB );
1539                         }
1540                         if(seqCoordinates1 == seqCoordinates2)
1541                             bIsDefaultPath = sal_True;
1542 
1543                         const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
1544                         rtl::OUString sShpType;
1545                         SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
1546                         Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
1547                         if ( pAny )
1548                             *pAny >>= sShpType;
1549                         if( sShpType.getLength() > 3 &&
1550                             sShpType.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "mso" ))){
1551                                 bIsMSEllipse = sal_True;
1552                         }
1553                         if( (! bIsDefaultPath   && ! bIsDefaultViewBox) || (bIsDefaultViewBox && bIsMSEllipse) /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1554                         {
1555                             _aCenter = GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True );
1556                             GetParameter( fWidth,  seqCoordinates[ rSrcPt + 1 ].First, sal_True, sal_False  );
1557                             GetParameter( fHeight,  seqCoordinates[ rSrcPt + 1 ].Second, sal_False, sal_True );
1558                             fWidth /= 2;
1559                             fHeight /= 2;
1560                         }else if( bIsDefaultPath && !bIsDefaultViewBox /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1561                         {
1562                             _aCenter.X() = nCoordWidth/2 * fXScale;
1563                             _aCenter.Y() = nCoordHeight/2 * fYScale;
1564                             fWidth = nCoordWidth/2;
1565                             fHeight = nCoordHeight/2;
1566 
1567                             const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) );
1568                             const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
1569                             com::sun::star::awt::Rectangle aViewBox;
1570                             if ( pViewBox && (*pViewBox >>= aViewBox ) )
1571                             {
1572                                 aViewBox.Width = pDefCustomShape->nCoordWidth;
1573                                 aViewBox.Height = pDefCustomShape->nCoordHeight;
1574                             }
1575                             com::sun::star::beans::PropertyValue aPropVal;
1576                             aPropVal.Name = sViewBox;
1577                             aPropVal.Value <<= aViewBox;
1578                             rGeometryItem.SetPropertyValue( aPropVal );
1579                             pCustomShapeObj->SetMergedItem( rGeometryItem );
1580                         }else{
1581                             _aCenter = GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True );
1582                             GetParameter( fWidth,  seqCoordinates[ rSrcPt + 1 ].First, sal_True, sal_False  );
1583                             GetParameter( fHeight,  seqCoordinates[ rSrcPt + 1 ].Second, sal_False, sal_True );
1584                         }
1585 
1586                         fWidth *= fXScale;
1587                         fHeight*= fYScale;
1588                         Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1589                         Size  aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1590                         Rectangle aRect( aP, aS );
1591                         if ( aRect.GetWidth() && aRect.GetHeight() )
1592                         {
1593                             double fStartAngle, fEndAngle;
1594                             GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First,  sal_False, sal_False );
1595                             GetParameter( fEndAngle  , seqCoordinates[ rSrcPt + 2 ].Second, sal_False, sal_False );
1596 
1597                             if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1598                             {
1599                                 if ( (sal_Int32)fStartAngle & 0x7fff0000 )  // SJ: if the angle was imported from our escher import, then the
1600                                     fStartAngle /= 65536.0;                 // value is shifted by 16. TODO: already change the fixed float to a
1601                                 if ( (sal_Int32)fEndAngle & 0x7fff0000 )    // double in the import filter
1602                                 {
1603                                     fEndAngle /= 65536.0;
1604                                     fEndAngle = fEndAngle + fStartAngle;
1605                                     if ( fEndAngle < 0 )
1606                                     {   // in the binary filter the endangle is the amount
1607                                         double fTemp = fStartAngle;
1608                                         fStartAngle = fEndAngle;
1609                                         fEndAngle = fTemp;
1610                                     }
1611                                 }
1612                                 double fCenterX = aRect.Center().X();
1613                                 double fCenterY = aRect.Center().Y();
1614                                 double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1615                                 double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1616                                 double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1617                                 double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1618                                 aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), sal_False));
1619                             }
1620                             else
1621                             {   /* SJ: TODO: this block should be replaced sometimes, because the current point
1622                                    is not set correct, it also does not use the correct moveto
1623                                    point if ANGLEELLIPSETO was used, but the method CreateArc
1624                                    is at the moment not able to draw full circles (if startangle is 0
1625                                    and endangle 360 nothing is painted :-( */
1626                                 sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1627                                 sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1628                                 Point aCenter( aRect.Center() );
1629 
1630                                 // append start point
1631                                 aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1632 
1633                                 // append four bezier segments
1634                                 aNewB2DPolygon.appendBezierSegment(
1635                                     basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1636                                     basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1637                                     basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1638 
1639                                 aNewB2DPolygon.appendBezierSegment(
1640                                     basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1641                                     basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1642                                     basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1643 
1644                                 aNewB2DPolygon.appendBezierSegment(
1645                                     basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1646                                     basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1647                                     basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1648 
1649                                 aNewB2DPolygon.appendBezierSegment(
1650                                     basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1651                                     basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1652                                     basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1653 
1654                                 // close, rescue last controlpoint, remove double last point
1655                                 basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1656                             }
1657                         }
1658                         rSrcPt += 3;
1659                     }
1660                 }
1661                 break;
1662 
1663                 case LINETO :
1664                 {
1665                     for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1666                     {
1667                         const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1668                         aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1669                     }
1670                 }
1671                 break;
1672 
1673                 case ARC :
1674                 case CLOCKWISEARC :
1675                 {
1676                     if(aNewB2DPolygon.count() > 1L)
1677                     {
1678                         // #i76201# Add conversion to closed polygon when first and last points are equal
1679                         basegfx::tools::checkClosed(aNewB2DPolygon);
1680                         aNewB2DPolyPolygon.append(aNewB2DPolygon);
1681                     }
1682 
1683                     aNewB2DPolygon.clear();
1684                 }
1685                 case ARCTO :
1686                 case CLOCKWISEARCTO :
1687                 {
1688                     sal_Bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1689                     sal_uInt32 nXor = bClockwise ? 3 : 2;
1690                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1691                     {
1692                         Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ), GetPoint( seqCoordinates[ rSrcPt + 1 ], sal_True, sal_True ) );
1693                         if ( aRect.GetWidth() && aRect.GetHeight() )
1694                         {
1695                             Point aCenter( aRect.Center() );
1696                             Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], sal_True, sal_True ) );
1697                             Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], sal_True, sal_True ) );
1698                             double fRatio = (double)aRect.GetHeight() / (double)aRect.GetWidth();
1699                             aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1700                             aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1701                             aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1702                             aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1703                             aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1704                         }
1705                         rSrcPt += 4;
1706                     }
1707                 }
1708                 break;
1709 
1710                 case ELLIPTICALQUADRANTX :
1711                 case ELLIPTICALQUADRANTY :
1712                 {
1713                     bool bFirstDirection(true);
1714                     basegfx::B2DPoint aControlPointA;
1715                     basegfx::B2DPoint aControlPointB;
1716 
1717                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1718                     {
1719                         sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1720                         Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ) );
1721 
1722                         if ( rSrcPt )   // we need a previous point
1723                         {
1724                             Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], sal_True, sal_True ) );
1725                             sal_Int32 nX, nY;
1726                             nX = aCurrent.X() - aPrev.X();
1727                             nY = aCurrent.Y() - aPrev.Y();
1728                             if ( ( nY ^ nX ) & 0x80000000 )
1729                             {
1730                                 if ( !i )
1731                                     bFirstDirection = true;
1732                                 else if ( !bFirstDirection )
1733                                     nModT ^= 1;
1734                             }
1735                             else
1736                             {
1737                                 if ( !i )
1738                                     bFirstDirection = false;
1739                                 else if ( bFirstDirection )
1740                                     nModT ^= 1;
1741                             }
1742                             if ( nModT )            // get the right corner
1743                             {
1744                                 nX = aCurrent.X();
1745                                 nY = aPrev.Y();
1746                             }
1747                             else
1748                             {
1749                                 nX = aPrev.X();
1750                                 nY = aCurrent.Y();
1751                             }
1752                             sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1753                             sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1754                             Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1755 
1756                             aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1757 
1758                             nXVec = ( nX - aCurrent.X() ) >> 1;
1759                             nYVec = ( nY - aCurrent.Y() ) >> 1;
1760                             Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1761 
1762                             aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1763 
1764                             aNewB2DPolygon.appendBezierSegment(
1765                                 aControlPointA,
1766                                 aControlPointB,
1767                                 basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1768                         }
1769                         else
1770                         {
1771                             aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1772                         }
1773 
1774                         rSrcPt++;
1775                     }
1776                 }
1777                 break;
1778 
1779 #ifdef DBG_CUSTOMSHAPE
1780                 case UNKNOWN :
1781                 default :
1782                 {
1783                     ByteString aString( "CustomShapes::unknown PolyFlagValue :" );
1784                     aString.Append( ByteString::CreateFromInt32( nCommand ) );
1785                     DBG_ERROR( aString.GetBuffer() );
1786                 }
1787                 break;
1788 #endif
1789             }
1790             if ( nCommand == ENDSUBPATH )
1791                 break;
1792         }
1793     }
1794     if ( rSegmentInd == nSegInfoSize )
1795         rSegmentInd++;
1796 
1797     if(aNewB2DPolygon.count() > 1L)
1798     {
1799         // #i76201# Add conversion to closed polygon when first and last points are equal
1800         basegfx::tools::checkClosed(aNewB2DPolygon);
1801         aNewB2DPolyPolygon.append(aNewB2DPolygon);
1802     }
1803 
1804     if(aNewB2DPolyPolygon.count())
1805     {
1806         // #i37011#
1807         bool bForceCreateTwoObjects(false);
1808 
1809         if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1810         {
1811             bForceCreateTwoObjects = true;
1812         }
1813 
1814         if(bLineGeometryNeededOnly)
1815         {
1816             bForceCreateTwoObjects = true;
1817             bNoFill = true;
1818             bNoStroke = false;
1819         }
1820 
1821         if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1822         {
1823             if(bFilled && !bNoFill)
1824             {
1825                 basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1826                 aClosedPolyPolygon.setClosed(true);
1827                 SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon);
1828                 SfxItemSet aTempSet(*this);
1829                 aTempSet.Put(SdrShadowItem(sal_False));
1830                 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1831                 pFill->SetMergedItemSet(aTempSet);
1832                 rObjectList.push_back(pFill);
1833             }
1834 
1835             if(!bNoStroke)
1836             {
1837                 // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
1838                 // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
1839                 // to correct the polygon (here: open it) using the type, the last edge may get lost.
1840                 // Thus, use a type that fits the polygon
1841                 SdrPathObj* pStroke = new SdrPathObj(
1842                     aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1843                     aNewB2DPolyPolygon);
1844                 SfxItemSet aTempSet(*this);
1845                 aTempSet.Put(SdrShadowItem(sal_False));
1846                 aTempSet.Put(XFillStyleItem(XFILL_NONE));
1847                 pStroke->SetMergedItemSet(aTempSet);
1848                 rObjectList.push_back(pStroke);
1849             }
1850         }
1851         else
1852         {
1853             SdrPathObj* pObj = 0;
1854             SfxItemSet aTempSet(*this);
1855             aTempSet.Put(SdrShadowItem(sal_False));
1856 
1857             if(bNoFill)
1858             {
1859                 // see comment above about OBJ_PLIN
1860                 pObj = new SdrPathObj(
1861                     aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1862                     aNewB2DPolyPolygon);
1863                 aTempSet.Put(XFillStyleItem(XFILL_NONE));
1864             }
1865             else
1866             {
1867                 aNewB2DPolyPolygon.setClosed(true);
1868                 pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon);
1869             }
1870 
1871             if(bNoStroke)
1872             {
1873                 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1874             }
1875 
1876             if(pObj)
1877             {
1878                 pObj->SetMergedItemSet(aTempSet);
1879                 rObjectList.push_back(pObj);
1880             }
1881         }
1882     }
1883 }
1884 
1885 void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
1886 {
1887     sal_Bool bAccent = sal_False;
1888     switch( eSpType )
1889     {
1890         case mso_sptCallout1 :
1891         case mso_sptBorderCallout1 :
1892         case mso_sptCallout90 :
1893         case mso_sptBorderCallout90 :
1894         default:
1895         break;
1896 
1897         case mso_sptAccentCallout1 :
1898         case mso_sptAccentBorderCallout1 :
1899         case mso_sptAccentCallout90 :
1900         case mso_sptAccentBorderCallout90 :
1901         {
1902             sal_uInt32 i, nLine = 0;
1903             for ( i = 0; i < vObjectList.size(); i++ )
1904             {
1905                 SdrPathObj* pObj( vObjectList[ i ] );
1906                 if(pObj->IsLine())
1907                 {
1908                     nLine++;
1909                     if ( nLine == nLineObjectCount )
1910                     {
1911                         pObj->ClearMergedItem( XATTR_LINESTART );
1912                         pObj->ClearMergedItem( XATTR_LINEEND );
1913                     }
1914                 }
1915             }
1916         }
1917         break;
1918 
1919         // switch start & end
1920         case mso_sptAccentCallout2 :
1921         case mso_sptAccentBorderCallout2 :
1922             bAccent = sal_True;
1923         case mso_sptCallout2 :
1924         case mso_sptBorderCallout2 :
1925         {
1926             sal_uInt32 i, nLine = 0;
1927             for ( i = 0; i < vObjectList.size(); i++ )
1928             {
1929                 SdrPathObj* pObj( vObjectList[ i ] );
1930                 if(pObj->IsLine())
1931                 {
1932                     nLine++;
1933                     if ( nLine == 1 )
1934                         pObj->ClearMergedItem( XATTR_LINEEND );
1935                     else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
1936                         pObj->ClearMergedItem( XATTR_LINESTART );
1937                     else
1938                     {
1939                         pObj->ClearMergedItem( XATTR_LINESTART );
1940                         pObj->ClearMergedItem( XATTR_LINEEND );
1941                     }
1942                 }
1943             }
1944         }
1945         break;
1946 
1947         case mso_sptAccentCallout3 :
1948         case mso_sptAccentBorderCallout3 :
1949             bAccent = sal_False;
1950         case mso_sptCallout3 :
1951         case mso_sptBorderCallout3 :
1952         {
1953             sal_uInt32 i, nLine = 0;
1954             for ( i = 0; i < vObjectList.size(); i++ )
1955             {
1956                 SdrPathObj* pObj( vObjectList[ i ] );
1957                 if(pObj->IsLine())
1958                 {
1959                     if ( nLine )
1960                     {
1961                         pObj->ClearMergedItem( XATTR_LINESTART );
1962                         pObj->ClearMergedItem( XATTR_LINEEND );
1963                     }
1964                     else
1965                         EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
1966 
1967                     nLine++;
1968                 }
1969             }
1970         }
1971         break;
1972     }
1973 }
1974 
1975 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
1976                                           sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
1977 {
1978     if ( !rObj.IsLine() )
1979     {
1980         const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1981         switch( eFillStyle )
1982         {
1983             default:
1984             case XFILL_SOLID:
1985             {
1986                 Color aFillColor;
1987                 if ( nColorCount )
1988                 {
1989                     aFillColor = GetColorData(
1990                         ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
1991                         std::min(nColorIndex, nColorCount-1) );
1992                     rObj.SetMergedItem( XFillColorItem( String(), aFillColor ) );
1993                 }
1994                 break;
1995             }
1996             case XFILL_GRADIENT:
1997             {
1998                 XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
1999                 if ( nColorCount )
2000                 {
2001                     aXGradient.SetStartColor(
2002                         GetColorData(
2003                             aXGradient.GetStartColor(),
2004                             std::min(nColorIndex, nColorCount-1) ));
2005                     aXGradient.SetEndColor(
2006                         GetColorData(
2007                             aXGradient.GetEndColor(),
2008                             std::min(nColorIndex, nColorCount-1) ));
2009                 }
2010 
2011                 rObj.SetMergedItem( XFillGradientItem( String(), aXGradient ) );
2012                 break;
2013             }
2014             case XFILL_HATCH:
2015             {
2016                 XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
2017                 if ( nColorCount )
2018                 {
2019                     aXHatch.SetColor(
2020                         GetColorData(
2021                             aXHatch.GetColor(),
2022                             std::min(nColorIndex, nColorCount-1) ));
2023                 }
2024 
2025                 rObj.SetMergedItem( XFillHatchItem( String(), aXHatch ) );
2026                 break;
2027             }
2028             case XFILL_BITMAP:
2029             {
2030                 if ( nColorCount )
2031                 {
2032                     Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2033 
2034                     aBitmap.Adjust(
2035                         static_cast< short > ( GetLuminanceChange(
2036                             std::min(nColorIndex, nColorCount-1))));
2037 
2038                     rObj.SetMergedItem(XFillBitmapItem(String(), Graphic(aBitmap)));
2039                 }
2040 
2041                 break;
2042             }
2043         }
2044 
2045         if ( nColorIndex < nColorCount )
2046             nColorIndex++;
2047     }
2048 }
2049 
2050 SdrObject* EnhancedCustomShape2d::CreatePathObj( sal_Bool bLineGeometryNeededOnly )
2051 {
2052     sal_Int32 nCoordSize = seqCoordinates.getLength();
2053     if ( !nCoordSize )
2054         return NULL;
2055 
2056     sal_uInt16 nSrcPt = 0;
2057     sal_uInt16 nSegmentInd = 0;
2058 
2059     std::vector< SdrPathObj* > vObjectList;
2060     sal_Bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
2061 
2062     while( nSegmentInd <= seqSegments.getLength() )
2063     {
2064         CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack );
2065     }
2066 
2067     SdrObject* pRet = NULL;
2068     sal_uInt32 i;
2069 
2070     if ( !vObjectList.empty() )
2071     {
2072         const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
2073         Color           aFillColor;
2074         sal_uInt32      nColorCount = nColorData >> 28;
2075         sal_uInt32      nColorIndex = 0;
2076 
2077         // #i37011# remove invisible objects
2078         if(!vObjectList.empty())
2079         {
2080             std::vector< SdrPathObj* > vTempList;
2081 
2082             for(i = 0L; i < vObjectList.size(); i++)
2083             {
2084                 SdrPathObj* pObj(vObjectList[i]);
2085                 const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
2086                 const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2087 
2088                 //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2089                 if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
2090                     delete pObj;
2091                 else
2092                     vTempList.push_back(pObj);
2093             }
2094 
2095             vObjectList = vTempList;
2096         }
2097 
2098         if(1L == vObjectList.size())
2099         {
2100             // a single object, correct some values
2101             AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2102         }
2103         else
2104         {
2105             sal_Int32 nLineObjectCount = 0;
2106             sal_Int32 nAreaObjectCount = 0;
2107 
2108             // correct some values and collect content data
2109             for ( i = 0; i < vObjectList.size(); i++ )
2110             {
2111                 SdrPathObj* pObj( vObjectList[ i ] );
2112 
2113                 if(pObj->IsLine())
2114                 {
2115                     nLineObjectCount++;
2116                 }
2117                 else
2118                 {
2119                     nAreaObjectCount++;
2120                     AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2121                 }
2122             }
2123 
2124             // #i88870# correct line arrows for callouts
2125             if ( nLineObjectCount )
2126                 CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2127 
2128             // sort objects so that filled ones are in front. Necessary
2129             // for some strange objects
2130             if ( bSortFilledObjectsToBack )
2131             {
2132                 std::vector< SdrPathObj* > vTempList;
2133 
2134                 for ( i = 0; i < vObjectList.size(); i++ )
2135                 {
2136                     SdrPathObj* pObj( vObjectList[ i ] );
2137 
2138                     if ( !pObj->IsLine() )
2139                     {
2140                         vTempList.push_back(pObj);
2141                     }
2142                 }
2143 
2144                 for ( i = 0; i < vObjectList.size(); i++ )
2145                 {
2146                     SdrPathObj* pObj( vObjectList[ i ] );
2147 
2148                     if ( pObj->IsLine() )
2149                     {
2150                         vTempList.push_back(pObj);
2151                     }
2152                 }
2153 
2154                 vObjectList = vTempList;
2155             }
2156         }
2157     }
2158 
2159     // #i37011#
2160     if(!vObjectList.empty())
2161     {
2162         // copy remaining objects to pRet
2163         if(vObjectList.size() > 1L)
2164         {
2165             pRet = new SdrObjGroup;
2166 
2167             for (i = 0L; i < vObjectList.size(); i++)
2168             {
2169                 SdrObject* pObj(vObjectList[i]);
2170                 pRet->GetSubList()->NbcInsertObject(pObj);
2171             }
2172         }
2173         else if(1L == vObjectList.size())
2174         {
2175             pRet = vObjectList[0L];
2176         }
2177 
2178         if(pRet)
2179         {
2180             // move to target position
2181             Rectangle aCurRect(pRet->GetSnapRect());
2182             aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2183             pRet->NbcSetSnapRect(aCurRect);
2184         }
2185     }
2186 
2187     return pRet;
2188 }
2189 
2190 SdrObject* EnhancedCustomShape2d::CreateObject( sal_Bool bLineGeometryNeededOnly )
2191 {
2192     SdrObject* pRet = NULL;
2193 
2194     if ( eSpType == mso_sptRectangle )
2195     {
2196         pRet = new SdrRectObj( aLogicRect );
2197 // SJ: not setting model, so we save a lot of broadcasting and the model is not modified any longer
2198 //      pRet->SetModel( pCustomShapeObj->GetModel() );
2199         pRet->SetMergedItemSet( *this );
2200     }
2201     if ( !pRet )
2202         pRet = CreatePathObj( bLineGeometryNeededOnly );
2203 
2204     return pRet;
2205 }
2206 
2207 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2208 {
2209     if ( pObj && seqGluePoints.getLength() )
2210     {
2211         sal_uInt32 i, nCount = seqGluePoints.getLength();
2212         for ( i = 0; i < nCount; i++ )
2213         {
2214             SdrGluePoint aGluePoint;
2215 
2216             aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], sal_True, sal_True ) );
2217             aGluePoint.SetPercent( sal_False );
2218 
2219 //          const Point& rPoint = GetPoint( seqGluePoints[ i ], sal_True, sal_True );
2220 //          double fXRel = rPoint.X();
2221 //          double fYRel = rPoint.Y();
2222 //          fXRel = aLogicRect.GetWidth() == 0 ? 0.0 : fXRel / aLogicRect.GetWidth() * 10000;
2223 //          fYRel = aLogicRect.GetHeight() == 0 ? 0.0 : fYRel / aLogicRect.GetHeight() * 10000;
2224 //          aGluePoint.SetPos( Point( (sal_Int32)fXRel, (sal_Int32)fYRel ) );
2225 //          aGluePoint.SetPercent( sal_True );
2226             aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2227             aGluePoint.SetEscDir( SDRESC_SMART );
2228             SdrGluePointList* pList = pObj->ForceGluePointList();
2229             if( pList )
2230                 /* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2231         }
2232     }
2233 }
2234 
2235 SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2236 {
2237     return CreateObject( sal_True );
2238 }
2239 
2240 
2241