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