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