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