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