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