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