xref: /AOO41X/main/svx/source/customshapes/EnhancedCustomShape2d.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
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_Int32 nP1, sal_Int32 nP2, sal_Int32 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_Int32 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 ( nPntCount )
1501                     {
1502                         if(aNewB2DPolygon.count() > 1L)
1503                         {
1504                             // #i76201# Add conversion to closed polygon when first and last points are equal
1505                             basegfx::tools::checkClosed(aNewB2DPolygon);
1506                             aNewB2DPolyPolygon.append(aNewB2DPolygon);
1507                         }
1508                         aNewB2DPolygon.clear();
1509                     }
1510                 }
1511                 case ANGLEELLIPSETO :
1512                 {
1513                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1514                     {
1515                         // create a circle
1516                         Point _aCenter;
1517                         double fWidth, fHeight;
1518                         MSO_SPT eSpType = mso_sptEllipse;
1519                         const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
1520                         sal_Bool bIsDefaultViewBox = sal_False;
1521                         sal_Bool bIsDefaultPath = sal_False;
1522                         sal_Bool bIsMSEllipse = sal_False;
1523 
1524                         if( ( nCoordWidth == pDefCustomShape->nCoordWidth )
1525                             && ( nCoordHeight == pDefCustomShape->nCoordHeight ) )
1526                             bIsDefaultViewBox = sal_True;
1527                         sal_Int32 j, nCount = pDefCustomShape->nVertices;//==3
1528                         com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1529 
1530                         seqCoordinates1.realloc( nCount );
1531                         for ( j = 0; j < nCount; j++ )
1532                         {
1533                             seqCoordinates1[j] = seqCoordinates[ rSrcPt + j];
1534                         }
1535 
1536                         seqCoordinates2.realloc( nCount );
1537                         for ( j = 0; j < nCount; j++ )
1538                         {
1539                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].First, pDefCustomShape->pVertices[ j ].nValA );
1540                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].Second, pDefCustomShape->pVertices[ j ].nValB );
1541                         }
1542                         if(seqCoordinates1 == seqCoordinates2)
1543                             bIsDefaultPath = sal_True;
1544 
1545                         const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
1546                         rtl::OUString sShpType;
1547                         SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
1548                         Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
1549                         if ( pAny )
1550                             *pAny >>= sShpType;
1551                         if( sShpType.getLength() > 3 &&
1552                             sShpType.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "mso" ))){
1553                                 bIsMSEllipse = sal_True;
1554                         }
1555                         if( (! bIsDefaultPath   && ! bIsDefaultViewBox) || (bIsDefaultViewBox && bIsMSEllipse) /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1556                         {
1557                             _aCenter = GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True );
1558                             GetParameter( fWidth,  seqCoordinates[ rSrcPt + 1 ].First, sal_True, sal_False  );
1559                             GetParameter( fHeight,  seqCoordinates[ rSrcPt + 1 ].Second, sal_False, sal_True );
1560                             fWidth /= 2;
1561                             fHeight /= 2;
1562                         }else if( bIsDefaultPath && !bIsDefaultViewBox /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1563                         {
1564                             _aCenter.X() = nCoordWidth/2 * fXScale;
1565                             _aCenter.Y() = nCoordHeight/2 * fYScale;
1566                             fWidth = nCoordWidth/2;
1567                             fHeight = nCoordHeight/2;
1568 
1569                             const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) );
1570                             const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
1571                             com::sun::star::awt::Rectangle aViewBox;
1572                             if ( pViewBox && (*pViewBox >>= aViewBox ) )
1573                             {
1574                                 aViewBox.Width = pDefCustomShape->nCoordWidth;
1575                                 aViewBox.Height = pDefCustomShape->nCoordHeight;
1576                             }
1577                             com::sun::star::beans::PropertyValue aPropVal;
1578                             aPropVal.Name = sViewBox;
1579                             aPropVal.Value <<= aViewBox;
1580                             rGeometryItem.SetPropertyValue( aPropVal );
1581                             pCustomShapeObj->SetMergedItem( rGeometryItem );
1582                         }else{
1583                             _aCenter = GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True );
1584                             GetParameter( fWidth,  seqCoordinates[ rSrcPt + 1 ].First, sal_True, sal_False  );
1585                             GetParameter( fHeight,  seqCoordinates[ rSrcPt + 1 ].Second, sal_False, sal_True );
1586                         }
1587 
1588                         fWidth *= fXScale;
1589                         fHeight*= fYScale;
1590                         Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1591                         Size  aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1592                         Rectangle aRect( aP, aS );
1593                         if ( aRect.GetWidth() && aRect.GetHeight() )
1594                         {
1595                             double fStartAngle, fEndAngle;
1596                             GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First,  sal_False, sal_False );
1597                             GetParameter( fEndAngle  , seqCoordinates[ rSrcPt + 2 ].Second, sal_False, sal_False );
1598 
1599                             if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1600                             {
1601                                 if ( (sal_Int32)fStartAngle & 0x7fff0000 )  // SJ: if the angle was imported from our escher import, then the
1602                                     fStartAngle /= 65536.0;                 // value is shifted by 16. TODO: already change the fixed float to a
1603                                 if ( (sal_Int32)fEndAngle & 0x7fff0000 )    // double in the import filter
1604                                 {
1605                                     fEndAngle /= 65536.0;
1606                                     fEndAngle = fEndAngle + fStartAngle;
1607                                     if ( fEndAngle < 0 )
1608                                     {   // in the binary filter the endangle is the amount
1609                                         double fTemp = fStartAngle;
1610                                         fStartAngle = fEndAngle;
1611                                         fEndAngle = fTemp;
1612                                     }
1613                                 }
1614                                 double fCenterX = aRect.Center().X();
1615                                 double fCenterY = aRect.Center().Y();
1616                                 double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1617                                 double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1618                                 double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1619                                 double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1620                                 aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), sal_False));
1621                             }
1622                             else
1623                             {   /* SJ: TODO: this block should be replaced sometimes, because the current point
1624                                    is not set correct, it also does not use the correct moveto
1625                                    point if ANGLEELLIPSETO was used, but the method CreateArc
1626                                    is at the moment not able to draw full circles (if startangle is 0
1627                                    and endangle 360 nothing is painted :-( */
1628                                 sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1629                                 sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1630                                 Point aCenter( aRect.Center() );
1631 
1632                                 // append start point
1633                                 aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1634 
1635                                 // append four bezier segments
1636                                 aNewB2DPolygon.appendBezierSegment(
1637                                     basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1638                                     basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1639                                     basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1640 
1641                                 aNewB2DPolygon.appendBezierSegment(
1642                                     basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1643                                     basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1644                                     basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1645 
1646                                 aNewB2DPolygon.appendBezierSegment(
1647                                     basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1648                                     basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1649                                     basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1650 
1651                                 aNewB2DPolygon.appendBezierSegment(
1652                                     basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1653                                     basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1654                                     basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1655 
1656                                 // close, rescue last controlpoint, remove double last point
1657                                 basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1658                             }
1659                         }
1660                         rSrcPt += 3;
1661                     }
1662                 }
1663                 break;
1664 
1665                 case LINETO :
1666                 {
1667                     for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1668                     {
1669                         const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1670                         aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1671                     }
1672                 }
1673                 break;
1674 
1675                 case ARC :
1676                 case CLOCKWISEARC :
1677                 {
1678                     if(aNewB2DPolygon.count() > 1L)
1679                     {
1680                         // #i76201# Add conversion to closed polygon when first and last points are equal
1681                         basegfx::tools::checkClosed(aNewB2DPolygon);
1682                         aNewB2DPolyPolygon.append(aNewB2DPolygon);
1683                     }
1684 
1685                     aNewB2DPolygon.clear();
1686                 }
1687                 case ARCTO :
1688                 case CLOCKWISEARCTO :
1689                 {
1690                     sal_Bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1691                     sal_uInt32 nXor = bClockwise ? 3 : 2;
1692                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1693                     {
1694                         Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ), GetPoint( seqCoordinates[ rSrcPt + 1 ], sal_True, sal_True ) );
1695                         if ( aRect.GetWidth() && aRect.GetHeight() )
1696                         {
1697                             Point aCenter( aRect.Center() );
1698                             Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], sal_True, sal_True ) );
1699                             Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], sal_True, sal_True ) );
1700                             double fRatio = (double)aRect.GetHeight() / (double)aRect.GetWidth();
1701                             aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1702                             aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1703                             aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1704                             aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1705                             aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1706                         }
1707                         rSrcPt += 4;
1708                     }
1709                 }
1710                 break;
1711 
1712                 case ELLIPTICALQUADRANTX :
1713                 case ELLIPTICALQUADRANTY :
1714                 {
1715                     bool bFirstDirection(true);
1716                     basegfx::B2DPoint aControlPointA;
1717                     basegfx::B2DPoint aControlPointB;
1718 
1719                     for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1720                     {
1721                         sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1722                         Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ) );
1723 
1724                         if ( rSrcPt )   // we need a previous point
1725                         {
1726                             Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], sal_True, sal_True ) );
1727                             sal_Int32 nX, nY;
1728                             nX = aCurrent.X() - aPrev.X();
1729                             nY = aCurrent.Y() - aPrev.Y();
1730                             if ( ( nY ^ nX ) & 0x80000000 )
1731                             {
1732                                 if ( !i )
1733                                     bFirstDirection = true;
1734                                 else if ( !bFirstDirection )
1735                                     nModT ^= 1;
1736                             }
1737                             else
1738                             {
1739                                 if ( !i )
1740                                     bFirstDirection = false;
1741                                 else if ( bFirstDirection )
1742                                     nModT ^= 1;
1743                             }
1744                             if ( nModT )            // get the right corner
1745                             {
1746                                 nX = aCurrent.X();
1747                                 nY = aPrev.Y();
1748                             }
1749                             else
1750                             {
1751                                 nX = aPrev.X();
1752                                 nY = aCurrent.Y();
1753                             }
1754                             sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1755                             sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1756                             Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1757 
1758                             aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1759 
1760                             nXVec = ( nX - aCurrent.X() ) >> 1;
1761                             nYVec = ( nY - aCurrent.Y() ) >> 1;
1762                             Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1763 
1764                             aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1765 
1766                             aNewB2DPolygon.appendBezierSegment(
1767                                 aControlPointA,
1768                                 aControlPointB,
1769                                 basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1770                         }
1771                         else
1772                         {
1773                             aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1774                         }
1775 
1776                         rSrcPt++;
1777                     }
1778                 }
1779                 break;
1780 
1781 #ifdef DBG_CUSTOMSHAPE
1782                 case UNKNOWN :
1783                 default :
1784                 {
1785                     ByteString aString( "CustomShapes::unknown PolyFlagValue :" );
1786                     aString.Append( ByteString::CreateFromInt32( nCommand ) );
1787                     DBG_ERROR( aString.GetBuffer() );
1788                 }
1789                 break;
1790 #endif
1791             }
1792             if ( nCommand == ENDSUBPATH )
1793                 break;
1794         }
1795     }
1796     if ( rSegmentInd == nSegInfoSize )
1797         rSegmentInd++;
1798 
1799     if(aNewB2DPolygon.count() > 1L)
1800     {
1801         // #i76201# Add conversion to closed polygon when first and last points are equal
1802         basegfx::tools::checkClosed(aNewB2DPolygon);
1803         aNewB2DPolyPolygon.append(aNewB2DPolygon);
1804     }
1805 
1806     if(aNewB2DPolyPolygon.count())
1807     {
1808         // #i37011#
1809         bool bForceCreateTwoObjects(false);
1810 
1811         if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1812         {
1813             bForceCreateTwoObjects = true;
1814         }
1815 
1816         if(bLineGeometryNeededOnly)
1817         {
1818             bForceCreateTwoObjects = true;
1819             bNoFill = true;
1820             bNoStroke = false;
1821         }
1822 
1823         if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1824         {
1825             if(bFilled && !bNoFill)
1826             {
1827                 basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1828                 aClosedPolyPolygon.setClosed(true);
1829                 SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon);
1830                 SfxItemSet aTempSet(*this);
1831                 aTempSet.Put(SdrShadowItem(sal_False));
1832                 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1833                 pFill->SetMergedItemSet(aTempSet);
1834                 rObjectList.push_back(pFill);
1835             }
1836 
1837             if(!bNoStroke)
1838             {
1839                 // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
1840                 // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
1841                 // to correct the polygon (here: open it) using the type, the last edge may get lost.
1842                 // Thus, use a type that fits the polygon
1843                 SdrPathObj* pStroke = new SdrPathObj(
1844                     aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1845                     aNewB2DPolyPolygon);
1846                 SfxItemSet aTempSet(*this);
1847                 aTempSet.Put(SdrShadowItem(sal_False));
1848                 aTempSet.Put(XFillStyleItem(XFILL_NONE));
1849                 pStroke->SetMergedItemSet(aTempSet);
1850                 rObjectList.push_back(pStroke);
1851             }
1852         }
1853         else
1854         {
1855             SdrPathObj* pObj = 0;
1856             SfxItemSet aTempSet(*this);
1857             aTempSet.Put(SdrShadowItem(sal_False));
1858 
1859             if(bNoFill)
1860             {
1861                 // see comment above about OBJ_PLIN
1862                 pObj = new SdrPathObj(
1863                     aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1864                     aNewB2DPolyPolygon);
1865                 aTempSet.Put(XFillStyleItem(XFILL_NONE));
1866             }
1867             else
1868             {
1869                 aNewB2DPolyPolygon.setClosed(true);
1870                 pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon);
1871             }
1872 
1873             if(bNoStroke)
1874             {
1875                 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1876             }
1877 
1878             if(pObj)
1879             {
1880                 pObj->SetMergedItemSet(aTempSet);
1881                 rObjectList.push_back(pObj);
1882             }
1883         }
1884     }
1885 }
1886 
1887 void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
1888 {
1889     sal_Bool bAccent = sal_False;
1890     switch( eSpType )
1891     {
1892         case mso_sptCallout1 :
1893         case mso_sptBorderCallout1 :
1894         case mso_sptCallout90 :
1895         case mso_sptBorderCallout90 :
1896         default:
1897         break;
1898 
1899         case mso_sptAccentCallout1 :
1900         case mso_sptAccentBorderCallout1 :
1901         case mso_sptAccentCallout90 :
1902         case mso_sptAccentBorderCallout90 :
1903         {
1904             sal_uInt32 i, nLine = 0;
1905             for ( i = 0; i < vObjectList.size(); i++ )
1906             {
1907                 SdrPathObj* pObj( vObjectList[ i ] );
1908                 if(pObj->IsLine())
1909                 {
1910                     nLine++;
1911                     if ( nLine == nLineObjectCount )
1912                     {
1913                         pObj->ClearMergedItem( XATTR_LINESTART );
1914                         pObj->ClearMergedItem( XATTR_LINEEND );
1915                     }
1916                 }
1917             }
1918         }
1919         break;
1920 
1921         // switch start & end
1922         case mso_sptAccentCallout2 :
1923         case mso_sptAccentBorderCallout2 :
1924             bAccent = sal_True;
1925         case mso_sptCallout2 :
1926         case mso_sptBorderCallout2 :
1927         {
1928             sal_uInt32 i, nLine = 0;
1929             for ( i = 0; i < vObjectList.size(); i++ )
1930             {
1931                 SdrPathObj* pObj( vObjectList[ i ] );
1932                 if(pObj->IsLine())
1933                 {
1934                     nLine++;
1935                     if ( nLine == 1 )
1936                         pObj->ClearMergedItem( XATTR_LINEEND );
1937                     else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
1938                         pObj->ClearMergedItem( XATTR_LINESTART );
1939                     else
1940                     {
1941                         pObj->ClearMergedItem( XATTR_LINESTART );
1942                         pObj->ClearMergedItem( XATTR_LINEEND );
1943                     }
1944                 }
1945             }
1946         }
1947         break;
1948 
1949         case mso_sptAccentCallout3 :
1950         case mso_sptAccentBorderCallout3 :
1951             bAccent = sal_False;
1952         case mso_sptCallout3 :
1953         case mso_sptBorderCallout3 :
1954         {
1955             sal_uInt32 i, nLine = 0;
1956             for ( i = 0; i < vObjectList.size(); i++ )
1957             {
1958                 SdrPathObj* pObj( vObjectList[ i ] );
1959                 if(pObj->IsLine())
1960                 {
1961                     if ( nLine )
1962                     {
1963                         pObj->ClearMergedItem( XATTR_LINESTART );
1964                         pObj->ClearMergedItem( XATTR_LINEEND );
1965                     }
1966                     else
1967                         EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
1968 
1969                     nLine++;
1970                 }
1971             }
1972         }
1973         break;
1974     }
1975 }
1976 
1977 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
1978                                           sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
1979 {
1980     if ( !rObj.IsLine() )
1981     {
1982         const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1983         switch( eFillStyle )
1984         {
1985             default:
1986             case XFILL_SOLID:
1987             {
1988                 Color aFillColor;
1989                 if ( nColorCount )
1990                 {
1991                     aFillColor = GetColorData(
1992                         ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
1993                         std::min(nColorIndex, nColorCount-1) );
1994                     rObj.SetMergedItem( XFillColorItem( String(), aFillColor ) );
1995                 }
1996                 break;
1997             }
1998             case XFILL_GRADIENT:
1999             {
2000                 XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
2001                 if ( nColorCount )
2002                 {
2003                     aXGradient.SetStartColor(
2004                         GetColorData(
2005                             aXGradient.GetStartColor(),
2006                             std::min(nColorIndex, nColorCount-1) ));
2007                     aXGradient.SetEndColor(
2008                         GetColorData(
2009                             aXGradient.GetEndColor(),
2010                             std::min(nColorIndex, nColorCount-1) ));
2011                 }
2012 
2013                 rObj.SetMergedItem( XFillGradientItem( String(), aXGradient ) );
2014                 break;
2015             }
2016             case XFILL_HATCH:
2017             {
2018                 XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
2019                 if ( nColorCount )
2020                 {
2021                     aXHatch.SetColor(
2022                         GetColorData(
2023                             aXHatch.GetColor(),
2024                             std::min(nColorIndex, nColorCount-1) ));
2025                 }
2026 
2027                 rObj.SetMergedItem( XFillHatchItem( String(), aXHatch ) );
2028                 break;
2029             }
2030             case XFILL_BITMAP:
2031             {
2032                 if ( nColorCount )
2033                 {
2034                     Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2035 
2036                     aBitmap.Adjust(
2037                         static_cast< short > ( GetLuminanceChange(
2038                             std::min(nColorIndex, nColorCount-1))));
2039 
2040                     rObj.SetMergedItem(XFillBitmapItem(String(), Graphic(aBitmap)));
2041                 }
2042 
2043                 break;
2044             }
2045         }
2046 
2047         if ( nColorIndex < nColorCount )
2048             nColorIndex++;
2049     }
2050 }
2051 
2052 SdrObject* EnhancedCustomShape2d::CreatePathObj( sal_Bool bLineGeometryNeededOnly )
2053 {
2054     sal_Int32 nCoordSize = seqCoordinates.getLength();
2055     if ( !nCoordSize )
2056         return NULL;
2057 
2058     sal_uInt16 nSrcPt = 0;
2059     sal_uInt16 nSegmentInd = 0;
2060 
2061     std::vector< SdrPathObj* > vObjectList;
2062     sal_Bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
2063 
2064     while( nSegmentInd <= seqSegments.getLength() )
2065     {
2066         CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack );
2067     }
2068 
2069     SdrObject* pRet = NULL;
2070     sal_uInt32 i;
2071 
2072     if ( !vObjectList.empty() )
2073     {
2074         const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
2075         Color           aFillColor;
2076         sal_uInt32      nColorCount = nColorData >> 28;
2077         sal_uInt32      nColorIndex = 0;
2078 
2079         // #i37011# remove invisible objects
2080         if(!vObjectList.empty())
2081         {
2082             std::vector< SdrPathObj* > vTempList;
2083 
2084             for(i = 0L; i < vObjectList.size(); i++)
2085             {
2086                 SdrPathObj* pObj(vObjectList[i]);
2087                 const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
2088                 const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2089 
2090                 //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2091                 if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
2092                     delete pObj;
2093                 else
2094                     vTempList.push_back(pObj);
2095             }
2096 
2097             vObjectList = vTempList;
2098         }
2099 
2100         if(1L == vObjectList.size())
2101         {
2102             // a single object, correct some values
2103             AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2104         }
2105         else
2106         {
2107             sal_Int32 nLineObjectCount = 0;
2108             sal_Int32 nAreaObjectCount = 0;
2109 
2110             // correct some values and collect content data
2111             for ( i = 0; i < vObjectList.size(); i++ )
2112             {
2113                 SdrPathObj* pObj( vObjectList[ i ] );
2114 
2115                 if(pObj->IsLine())
2116                 {
2117                     nLineObjectCount++;
2118                 }
2119                 else
2120                 {
2121                     nAreaObjectCount++;
2122                     AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2123                 }
2124             }
2125 
2126             // #i88870# correct line arrows for callouts
2127             if ( nLineObjectCount )
2128                 CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2129 
2130             // sort objects so that filled ones are in front. Necessary
2131             // for some strange objects
2132             if ( bSortFilledObjectsToBack )
2133             {
2134                 std::vector< SdrPathObj* > vTempList;
2135 
2136                 for ( i = 0; i < vObjectList.size(); i++ )
2137                 {
2138                     SdrPathObj* pObj( vObjectList[ i ] );
2139 
2140                     if ( !pObj->IsLine() )
2141                     {
2142                         vTempList.push_back(pObj);
2143                     }
2144                 }
2145 
2146                 for ( i = 0; i < vObjectList.size(); i++ )
2147                 {
2148                     SdrPathObj* pObj( vObjectList[ i ] );
2149 
2150                     if ( pObj->IsLine() )
2151                     {
2152                         vTempList.push_back(pObj);
2153                     }
2154                 }
2155 
2156                 vObjectList = vTempList;
2157             }
2158         }
2159     }
2160 
2161     // #i37011#
2162     if(!vObjectList.empty())
2163     {
2164         // copy remaining objects to pRet
2165         if(vObjectList.size() > 1L)
2166         {
2167             pRet = new SdrObjGroup;
2168 
2169             for (i = 0L; i < vObjectList.size(); i++)
2170             {
2171                 SdrObject* pObj(vObjectList[i]);
2172                 pRet->GetSubList()->NbcInsertObject(pObj);
2173             }
2174         }
2175         else if(1L == vObjectList.size())
2176         {
2177             pRet = vObjectList[0L];
2178         }
2179 
2180         if(pRet)
2181         {
2182             // move to target position
2183             Rectangle aCurRect(pRet->GetSnapRect());
2184             aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2185             pRet->NbcSetSnapRect(aCurRect);
2186         }
2187     }
2188 
2189     return pRet;
2190 }
2191 
2192 SdrObject* EnhancedCustomShape2d::CreateObject( sal_Bool bLineGeometryNeededOnly )
2193 {
2194     SdrObject* pRet = NULL;
2195 
2196     if ( eSpType == mso_sptRectangle )
2197     {
2198         pRet = new SdrRectObj( aLogicRect );
2199 // SJ: not setting model, so we save a lot of broadcasting and the model is not modified any longer
2200 //      pRet->SetModel( pCustomShapeObj->GetModel() );
2201         pRet->SetMergedItemSet( *this );
2202     }
2203     if ( !pRet )
2204         pRet = CreatePathObj( bLineGeometryNeededOnly );
2205 
2206     return pRet;
2207 }
2208 
2209 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2210 {
2211     if ( pObj && seqGluePoints.getLength() )
2212     {
2213         sal_uInt32 i, nCount = seqGluePoints.getLength();
2214         for ( i = 0; i < nCount; i++ )
2215         {
2216             SdrGluePoint aGluePoint;
2217 
2218             aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], sal_True, sal_True ) );
2219             aGluePoint.SetPercent( sal_False );
2220 
2221 //          const Point& rPoint = GetPoint( seqGluePoints[ i ], sal_True, sal_True );
2222 //          double fXRel = rPoint.X();
2223 //          double fYRel = rPoint.Y();
2224 //          fXRel = aLogicRect.GetWidth() == 0 ? 0.0 : fXRel / aLogicRect.GetWidth() * 10000;
2225 //          fYRel = aLogicRect.GetHeight() == 0 ? 0.0 : fYRel / aLogicRect.GetHeight() * 10000;
2226 //          aGluePoint.SetPos( Point( (sal_Int32)fXRel, (sal_Int32)fYRel ) );
2227 //          aGluePoint.SetPercent( sal_True );
2228             aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2229             aGluePoint.SetEscDir( SDRESC_SMART );
2230             SdrGluePointList* pList = pObj->ForceGluePointList();
2231             if( pList )
2232                 /* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2233         }
2234     }
2235 }
2236 
2237 SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2238 {
2239     return CreateObject( sal_True );
2240 }
2241 
2242 
2243