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