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