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_Int16 nP1, sal_Int16 nP2, sal_Int16 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_Int16 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(aNewB2DPolygon.count() > 1L)
1501 					{
1502 						// #i76201# Add conversion to closed polygon when first and last points are equal
1503 						basegfx::tools::checkClosed(aNewB2DPolygon);
1504 						aNewB2DPolyPolygon.append(aNewB2DPolygon);
1505 					}
1506 
1507 					aNewB2DPolygon.clear();
1508 				}
1509 				case ANGLEELLIPSETO :
1510 				{
1511 					for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1512 					{
1513 						// create a circle
1514 						Point _aCenter( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ) );
1515 						double fWidth, fHeight;
1516 						GetParameter( fWidth,  seqCoordinates[ rSrcPt + 1 ].First, sal_True, sal_False  );
1517 						GetParameter( fHeight,  seqCoordinates[ rSrcPt + 1 ].Second, sal_False, sal_True );
1518 						fWidth *= fXScale;
1519 						fHeight*= fYScale;
1520 						Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1521 						Size  aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1522 						Rectangle aRect( aP, aS );
1523 						if ( aRect.GetWidth() && aRect.GetHeight() )
1524 						{
1525 							double fStartAngle, fEndAngle;
1526 							GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First,  sal_False, sal_False );
1527 							GetParameter( fEndAngle  , seqCoordinates[ rSrcPt + 2 ].Second, sal_False, sal_False );
1528 
1529 							if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1530 							{
1531 								if ( (sal_Int32)fStartAngle & 0x7fff0000 )	// SJ: if the angle was imported from our escher import, then the
1532 									fStartAngle /= 65536.0;					// value is shifted by 16. TODO: already change the fixed float to a
1533 								if ( (sal_Int32)fEndAngle & 0x7fff0000 )	// double in the import filter
1534 								{
1535 									fEndAngle /= 65536.0;
1536 									fEndAngle = fEndAngle + fStartAngle;
1537 									if ( fEndAngle < 0 )
1538 									{	// in the binary filter the endangle is the amount
1539 										double fTemp = fStartAngle;
1540 										fStartAngle = fEndAngle;
1541 										fEndAngle = fTemp;
1542 									}
1543 								}
1544 								double fCenterX = aRect.Center().X();
1545 								double fCenterY = aRect.Center().Y();
1546 								double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1547 								double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1548 								double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1549 								double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1550 								aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), sal_False));
1551 							}
1552 							else
1553 							{	/* SJ: TODO: this block should be replaced sometimes, because the current point
1554 								   is not set correct, it also does not use the correct moveto
1555 								   point if ANGLEELLIPSETO was used, but the method CreateArc
1556 								   is at the moment not able to draw full circles (if startangle is 0
1557 								   and endangle 360 nothing is painted :-( */
1558 								sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1559 								sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1560 								Point aCenter( aRect.Center() );
1561 
1562 								// append start point
1563 								aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1564 
1565 								// append four bezier segments
1566 								aNewB2DPolygon.appendBezierSegment(
1567 									basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1568 									basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1569 									basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1570 
1571 								aNewB2DPolygon.appendBezierSegment(
1572 									basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1573 									basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1574 									basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1575 
1576 								aNewB2DPolygon.appendBezierSegment(
1577 									basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1578 									basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1579 									basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1580 
1581 								aNewB2DPolygon.appendBezierSegment(
1582 									basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1583 									basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1584 									basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1585 
1586 								// close, rescue last controlpoint, remove double last point
1587 								basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1588 							}
1589 						}
1590 						rSrcPt += 3;
1591 					}
1592 				}
1593 				break;
1594 
1595 				case LINETO :
1596 				{
1597 					for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1598 					{
1599 						const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1600 						aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1601 					}
1602 				}
1603 				break;
1604 
1605 				case ARC :
1606 				case CLOCKWISEARC :
1607 				{
1608 					if(aNewB2DPolygon.count() > 1L)
1609 					{
1610 						// #i76201# Add conversion to closed polygon when first and last points are equal
1611 						basegfx::tools::checkClosed(aNewB2DPolygon);
1612 						aNewB2DPolyPolygon.append(aNewB2DPolygon);
1613 					}
1614 
1615 					aNewB2DPolygon.clear();
1616 				}
1617 				case ARCTO :
1618 				case CLOCKWISEARCTO :
1619 				{
1620 					sal_Bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1621 					sal_uInt32 nXor = bClockwise ? 3 : 2;
1622 					for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1623 					{
1624 						Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ), GetPoint( seqCoordinates[ rSrcPt + 1 ], sal_True, sal_True ) );
1625 						if ( aRect.GetWidth() && aRect.GetHeight() )
1626 						{
1627 							Point aCenter( aRect.Center() );
1628 							Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], sal_True, sal_True ) );
1629 							Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], sal_True, sal_True ) );
1630 							double fRatio = (double)aRect.GetHeight() / (double)aRect.GetWidth();
1631 							aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1632 							aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1633 							aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1634 							aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1635 							aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1636 						}
1637 						rSrcPt += 4;
1638 					}
1639 				}
1640 				break;
1641 
1642 				case ELLIPTICALQUADRANTX :
1643 				case ELLIPTICALQUADRANTY :
1644 				{
1645 					bool bFirstDirection(true);
1646 					basegfx::B2DPoint aControlPointA;
1647 					basegfx::B2DPoint aControlPointB;
1648 
1649 					for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1650 					{
1651 						sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1652 						Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ) );
1653 
1654 						if ( rSrcPt )	// we need a previous point
1655 						{
1656 							Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], sal_True, sal_True ) );
1657 							sal_Int32 nX, nY;
1658 							nX = aCurrent.X() - aPrev.X();
1659 							nY = aCurrent.Y() - aPrev.Y();
1660 							if ( ( nY ^ nX ) & 0x80000000 )
1661 							{
1662 								if ( !i )
1663 									bFirstDirection = true;
1664 								else if ( !bFirstDirection )
1665 									nModT ^= 1;
1666 							}
1667 							else
1668 							{
1669 								if ( !i )
1670 									bFirstDirection = false;
1671 								else if ( bFirstDirection )
1672 									nModT ^= 1;
1673 							}
1674 							if ( nModT )			// get the right corner
1675 							{
1676 								nX = aCurrent.X();
1677 								nY = aPrev.Y();
1678 							}
1679 							else
1680 							{
1681 								nX = aPrev.X();
1682 								nY = aCurrent.Y();
1683 							}
1684 							sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1685 							sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1686 							Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1687 
1688 							aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1689 
1690 							nXVec = ( nX - aCurrent.X() ) >> 1;
1691 							nYVec = ( nY - aCurrent.Y() ) >> 1;
1692 							Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1693 
1694 							aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1695 
1696 							aNewB2DPolygon.appendBezierSegment(
1697 								aControlPointA,
1698 								aControlPointB,
1699 								basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1700 						}
1701 						else
1702 						{
1703 							aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1704 						}
1705 
1706 						rSrcPt++;
1707 					}
1708 				}
1709 				break;
1710 
1711 #ifdef DBG_CUSTOMSHAPE
1712 				case UNKNOWN :
1713 				default :
1714 				{
1715 					ByteString aString( "CustomShapes::unknown PolyFlagValue :" );
1716 					aString.Append( ByteString::CreateFromInt32( nCommand ) );
1717 					DBG_ERROR( aString.GetBuffer() );
1718 				}
1719 				break;
1720 #endif
1721 			}
1722 			if ( nCommand == ENDSUBPATH )
1723 				break;
1724 		}
1725 	}
1726 	if ( rSegmentInd == nSegInfoSize )
1727 		rSegmentInd++;
1728 
1729 	if(aNewB2DPolygon.count() > 1L)
1730 	{
1731 		// #i76201# Add conversion to closed polygon when first and last points are equal
1732 		basegfx::tools::checkClosed(aNewB2DPolygon);
1733 		aNewB2DPolyPolygon.append(aNewB2DPolygon);
1734 	}
1735 
1736 	if(aNewB2DPolyPolygon.count())
1737 	{
1738 		// #i37011#
1739 		bool bForceCreateTwoObjects(false);
1740 
1741 		if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1742 		{
1743 			bForceCreateTwoObjects = true;
1744 		}
1745 
1746 		if(bLineGeometryNeededOnly)
1747 		{
1748 			bForceCreateTwoObjects = true;
1749 			bNoFill = true;
1750 			bNoStroke = false;
1751 		}
1752 
1753 		if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1754 		{
1755 			if(bFilled && !bNoFill)
1756 			{
1757 				basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1758 				aClosedPolyPolygon.setClosed(true);
1759 				SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon);
1760 				SfxItemSet aTempSet(*this);
1761 				aTempSet.Put(SdrShadowItem(sal_False));
1762 				aTempSet.Put(XLineStyleItem(XLINE_NONE));
1763 				pFill->SetMergedItemSet(aTempSet);
1764 				rObjectList.push_back(pFill);
1765 			}
1766 
1767 			if(!bNoStroke)
1768 			{
1769 				// there is no reason to use OBJ_PLIN here when the polygon is actually closed,
1770 				// the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
1771 				// to correct the polygon (here: open it) using the type, the last edge may get lost.
1772 				// Thus, use a type that fits the polygon
1773 				SdrPathObj* pStroke = new SdrPathObj(
1774 					aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1775 					aNewB2DPolyPolygon);
1776 				SfxItemSet aTempSet(*this);
1777 				aTempSet.Put(SdrShadowItem(sal_False));
1778 				aTempSet.Put(XFillStyleItem(XFILL_NONE));
1779 				pStroke->SetMergedItemSet(aTempSet);
1780 				rObjectList.push_back(pStroke);
1781 			}
1782 		}
1783 		else
1784 		{
1785 			SdrPathObj* pObj = 0;
1786 			SfxItemSet aTempSet(*this);
1787 			aTempSet.Put(SdrShadowItem(sal_False));
1788 
1789 			if(bNoFill)
1790 			{
1791 				// see comment above about OBJ_PLIN
1792 				pObj = new SdrPathObj(
1793 					aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1794 					aNewB2DPolyPolygon);
1795 				aTempSet.Put(XFillStyleItem(XFILL_NONE));
1796 			}
1797 			else
1798 			{
1799 				aNewB2DPolyPolygon.setClosed(true);
1800 				pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon);
1801 			}
1802 
1803 			if(bNoStroke)
1804 			{
1805 				aTempSet.Put(XLineStyleItem(XLINE_NONE));
1806 			}
1807 
1808 			if(pObj)
1809 			{
1810 				pObj->SetMergedItemSet(aTempSet);
1811 				rObjectList.push_back(pObj);
1812 			}
1813 		}
1814 	}
1815 }
1816 
1817 void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
1818 {
1819 	sal_Bool bAccent = sal_False;
1820 	switch( eSpType )
1821 	{
1822 		case mso_sptCallout1 :
1823 		case mso_sptBorderCallout1 :
1824 		case mso_sptCallout90 :
1825 		case mso_sptBorderCallout90 :
1826 		default:
1827 		break;
1828 
1829 		case mso_sptAccentCallout1 :
1830 		case mso_sptAccentBorderCallout1 :
1831 		case mso_sptAccentCallout90 :
1832 		case mso_sptAccentBorderCallout90 :
1833 		{
1834 			sal_uInt32 i, nLine = 0;
1835 			for ( i = 0; i < vObjectList.size(); i++ )
1836 			{
1837 				SdrPathObj* pObj( vObjectList[ i ] );
1838 				if(pObj->IsLine())
1839 				{
1840 					nLine++;
1841 					if ( nLine == nLineObjectCount )
1842 					{
1843 						pObj->ClearMergedItem( XATTR_LINESTART );
1844 						pObj->ClearMergedItem( XATTR_LINEEND );
1845 					}
1846 				}
1847 			}
1848 		}
1849 		break;
1850 
1851 		// switch start & end
1852 		case mso_sptAccentCallout2 :
1853 		case mso_sptAccentBorderCallout2 :
1854 			bAccent = sal_True;
1855 		case mso_sptCallout2 :
1856 		case mso_sptBorderCallout2 :
1857 		{
1858 			sal_uInt32 i, nLine = 0;
1859 			for ( i = 0; i < vObjectList.size(); i++ )
1860 			{
1861 				SdrPathObj* pObj( vObjectList[ i ] );
1862 				if(pObj->IsLine())
1863 				{
1864 					nLine++;
1865 					if ( nLine == 1 )
1866 						pObj->ClearMergedItem( XATTR_LINEEND );
1867 					else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
1868 						pObj->ClearMergedItem( XATTR_LINESTART );
1869 					else
1870 					{
1871 						pObj->ClearMergedItem( XATTR_LINESTART );
1872 						pObj->ClearMergedItem( XATTR_LINEEND );
1873 					}
1874 				}
1875 			}
1876 		}
1877 		break;
1878 
1879 		case mso_sptAccentCallout3 :
1880 		case mso_sptAccentBorderCallout3 :
1881 			bAccent = sal_False;
1882 		case mso_sptCallout3 :
1883 		case mso_sptBorderCallout3 :
1884 		{
1885 			sal_uInt32 i, nLine = 0;
1886 			for ( i = 0; i < vObjectList.size(); i++ )
1887 			{
1888 				SdrPathObj* pObj( vObjectList[ i ] );
1889 				if(pObj->IsLine())
1890 				{
1891 					if ( nLine )
1892 					{
1893 						pObj->ClearMergedItem( XATTR_LINESTART );
1894 						pObj->ClearMergedItem( XATTR_LINEEND );
1895 					}
1896 					else
1897 						EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
1898 
1899 					nLine++;
1900 				}
1901 			}
1902 		}
1903 		break;
1904 	}
1905 }
1906 
1907 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
1908                                           sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
1909 {
1910     if ( !rObj.IsLine() )
1911     {
1912         const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1913         switch( eFillStyle )
1914         {
1915             default:
1916             case XFILL_SOLID:
1917             {
1918                 Color aFillColor;
1919                 if ( nColorCount )
1920                 {
1921                     aFillColor = GetColorData(
1922                         ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
1923                         std::min(nColorIndex, nColorCount-1) );
1924                     rObj.SetMergedItem( XFillColorItem( String(), aFillColor ) );
1925                 }
1926                 break;
1927             }
1928             case XFILL_GRADIENT:
1929             {
1930                 XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
1931                 if ( nColorCount )
1932                 {
1933                     aXGradient.SetStartColor(
1934                         GetColorData(
1935                             aXGradient.GetStartColor(),
1936                             std::min(nColorIndex, nColorCount-1) ));
1937                     aXGradient.SetEndColor(
1938                         GetColorData(
1939                             aXGradient.GetEndColor(),
1940                             std::min(nColorIndex, nColorCount-1) ));
1941                 }
1942 
1943                 rObj.SetMergedItem( XFillGradientItem( String(), aXGradient ) );
1944                 break;
1945             }
1946             case XFILL_HATCH:
1947             {
1948                 XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
1949                 if ( nColorCount )
1950                 {
1951                     aXHatch.SetColor(
1952                         GetColorData(
1953                             aXHatch.GetColor(),
1954                             std::min(nColorIndex, nColorCount-1) ));
1955                 }
1956 
1957                 rObj.SetMergedItem( XFillHatchItem( String(), aXHatch ) );
1958                 break;
1959             }
1960             case XFILL_BITMAP:
1961             {
1962                 if ( nColorCount )
1963                 {
1964                     Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
1965 
1966                     aBitmap.Adjust(
1967                         static_cast< short > ( GetLuminanceChange(
1968                             std::min(nColorIndex, nColorCount-1))));
1969 
1970                     rObj.SetMergedItem(XFillBitmapItem(String(), Graphic(aBitmap)));
1971                 }
1972 
1973                 break;
1974             }
1975         }
1976 
1977         if ( nColorIndex < nColorCount )
1978             nColorIndex++;
1979     }
1980 }
1981 
1982 SdrObject* EnhancedCustomShape2d::CreatePathObj( sal_Bool bLineGeometryNeededOnly )
1983 {
1984 	sal_Int32 nCoordSize = seqCoordinates.getLength();
1985 	if ( !nCoordSize )
1986 		return NULL;
1987 
1988 	sal_uInt16 nSrcPt = 0;
1989 	sal_uInt16 nSegmentInd = 0;
1990 
1991 	std::vector< SdrPathObj* > vObjectList;
1992 	sal_Bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
1993 
1994 	while( nSegmentInd <= seqSegments.getLength() )
1995 	{
1996 		CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack );
1997 	}
1998 
1999 	SdrObject* pRet = NULL;
2000 	sal_uInt32 i;
2001 
2002 	if ( !vObjectList.empty() )
2003 	{
2004 		const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
2005 		Color			aFillColor;
2006 		sal_uInt32		nColorCount = nColorData >> 28;
2007 		sal_uInt32		nColorIndex	= 0;
2008 
2009 		// #i37011# remove invisible objects
2010 		if(!vObjectList.empty())
2011 		{
2012 			std::vector< SdrPathObj* > vTempList;
2013 
2014 			for(i = 0L; i < vObjectList.size(); i++)
2015 			{
2016 				SdrPathObj* pObj(vObjectList[i]);
2017 				const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
2018                 const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2019 
2020 				//SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2021 				if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
2022 					delete pObj;
2023 				else
2024 					vTempList.push_back(pObj);
2025 			}
2026 
2027 			vObjectList = vTempList;
2028 		}
2029 
2030 		if(1L == vObjectList.size())
2031 		{
2032 			// a single object, correct some values
2033             AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2034 		}
2035 		else
2036 		{
2037 			sal_Int32 nLineObjectCount = 0;
2038 			sal_Int32 nAreaObjectCount = 0;
2039 
2040 			// correct some values and collect content data
2041 			for ( i = 0; i < vObjectList.size(); i++ )
2042 			{
2043 				SdrPathObj* pObj( vObjectList[ i ] );
2044 
2045 				if(pObj->IsLine())
2046 				{
2047 					nLineObjectCount++;
2048 				}
2049 				else
2050 				{
2051 					nAreaObjectCount++;
2052                     AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2053 				}
2054 			}
2055 
2056 			// #i88870# correct line arrows for callouts
2057 			if ( nLineObjectCount )
2058 				CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2059 
2060 			// sort objects so that filled ones are in front. Necessary
2061 			// for some strange objects
2062 			if ( bSortFilledObjectsToBack )
2063 			{
2064 				std::vector< SdrPathObj* > vTempList;
2065 
2066 				for ( i = 0; i < vObjectList.size(); i++ )
2067 				{
2068 					SdrPathObj* pObj( vObjectList[ i ] );
2069 
2070 					if ( !pObj->IsLine() )
2071 					{
2072 						vTempList.push_back(pObj);
2073 					}
2074 				}
2075 
2076 				for ( i = 0; i < vObjectList.size(); i++ )
2077 				{
2078 					SdrPathObj* pObj( vObjectList[ i ] );
2079 
2080 					if ( pObj->IsLine() )
2081 					{
2082 						vTempList.push_back(pObj);
2083 					}
2084 				}
2085 
2086 				vObjectList = vTempList;
2087 			}
2088 		}
2089 	}
2090 
2091 	// #i37011#
2092 	if(!vObjectList.empty())
2093 	{
2094 		// copy remaining objects to pRet
2095 		if(vObjectList.size() > 1L)
2096 		{
2097 	        pRet = new SdrObjGroup;
2098 
2099 			for (i = 0L; i < vObjectList.size(); i++)
2100 			{
2101 				SdrObject* pObj(vObjectList[i]);
2102 				pRet->GetSubList()->NbcInsertObject(pObj);
2103 			}
2104 		}
2105 		else if(1L == vObjectList.size())
2106 		{
2107 			pRet = vObjectList[0L];
2108 		}
2109 
2110 		if(pRet)
2111 		{
2112 			// move to target position
2113 			Rectangle aCurRect(pRet->GetSnapRect());
2114 			aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2115 			pRet->NbcSetSnapRect(aCurRect);
2116 		}
2117 	}
2118 
2119 	return pRet;
2120 }
2121 
2122 SdrObject* EnhancedCustomShape2d::CreateObject( sal_Bool bLineGeometryNeededOnly )
2123 {
2124 	SdrObject* pRet = NULL;
2125 
2126 	if ( eSpType == mso_sptRectangle )
2127 	{
2128 		pRet = new SdrRectObj( aLogicRect );
2129 // SJ: not setting model, so we save a lot of broadcasting and the model is not modified any longer
2130 //		pRet->SetModel( pCustomShapeObj->GetModel() );
2131 		pRet->SetMergedItemSet( *this );
2132 	}
2133 	if ( !pRet )
2134 		pRet = CreatePathObj( bLineGeometryNeededOnly );
2135 
2136 	return pRet;
2137 }
2138 
2139 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2140 {
2141 	if ( pObj && seqGluePoints.getLength() )
2142 	{
2143 		sal_uInt32 i, nCount = seqGluePoints.getLength();
2144 		for ( i = 0; i < nCount; i++ )
2145 		{
2146 			SdrGluePoint aGluePoint;
2147 
2148 			aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], sal_True, sal_True ) );
2149 			aGluePoint.SetPercent( sal_False );
2150 
2151 //			const Point& rPoint = GetPoint( seqGluePoints[ i ], sal_True, sal_True );
2152 //			double fXRel = rPoint.X();
2153 //			double fYRel = rPoint.Y();
2154 //			fXRel = aLogicRect.GetWidth() == 0 ? 0.0 : fXRel / aLogicRect.GetWidth() * 10000;
2155 //			fYRel = aLogicRect.GetHeight() == 0 ? 0.0 : fYRel / aLogicRect.GetHeight() * 10000;
2156 //			aGluePoint.SetPos( Point( (sal_Int32)fXRel, (sal_Int32)fYRel ) );
2157 //			aGluePoint.SetPercent( sal_True );
2158 			aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2159 			aGluePoint.SetEscDir( SDRESC_SMART );
2160 			SdrGluePointList* pList = pObj->ForceGluePointList();
2161 			if( pList )
2162 				/* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2163 		}
2164 	}
2165 }
2166 
2167 SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2168 {
2169 	return CreateObject( sal_True );
2170 }
2171 
2172 
2173