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