Update ooo320-m1
[ooovba.git] / svx / source / customshapes / EnhancedCustomShape2d.cxx
blob16f48581bc55732fc689afdd16584e9db99d0c41
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EnhancedCustomShape2d.cxx,v $
10 * $Revision: 1.31.146.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include "EnhancedCustomShape2d.hxx"
34 #include "EnhancedCustomShapeGeometry.hxx"
35 #include "EnhancedCustomShapeTypeNames.hxx"
36 #include "EnhancedCustomShapeFunctionParser.hxx"
37 #include <svx/svdoashp.hxx>
38 #include <svx/svdtrans.hxx>
39 #include <svx/svdocirc.hxx>
40 #include <svx/svdogrp.hxx>
41 #include <svx/svdopath.hxx>
42 #ifndef _SVDOCAPT_HXX
43 #include <svx/svdocapt.hxx>
44 #endif
45 #include <svx/svdpage.hxx>
46 #include <svx/xflclit.hxx>
47 #include <svx/sdasaitm.hxx>
48 #include <svx/svdmodel.hxx>
49 #include <rtl/crc.h>
50 #include <rtl/math.hxx>
51 #include <svx/xfillit0.hxx>
52 #include <svx/xlnstit.hxx>
53 #include <svx/xlnedit.hxx>
54 #include <svx/xlnstwit.hxx>
55 #include <svx/xlnedwit.hxx>
56 #include <svx/xlnstcit.hxx>
57 #include <svx/xlnedcit.hxx>
58 #include <svx/xflgrit.hxx>
59 #include <svx/xflhtit.hxx>
60 #include <svx/xbtmpit.hxx>
61 #include <svx/xgrad.hxx>
62 #include <svx/xbitmap.hxx>
63 #include <svx/xhatch.hxx>
64 #include <com/sun/star/awt/Size.hpp>
65 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
66 #ifndef __COM_SUN_STAR_DRAWING_ENHANCEDCUSTOMSHAPESEGMENTCOMMAND_HPP__
67 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
68 #endif
69 #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
70 #include <boost/shared_ptr.hpp>
71 #endif
72 #include <basegfx/numeric/ftools.hxx>
73 #include <basegfx/color/bcolortools.hxx>
74 #include <basegfx/polygon/b2dpolygon.hxx>
76 // #i76201#
77 #include <basegfx/polygon/b2dpolygontools.hxx>
79 #include <math.h>
81 using namespace ::com::sun::star::uno;
82 using namespace ::com::sun::star::drawing;
83 using namespace ::com::sun::star::drawing::EnhancedCustomShapeSegmentCommand;
85 void EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nValue )
87 sal_uInt32 nDat = (sal_uInt32)nValue;
88 sal_Int32 nNewValue = nValue;
90 // check if this is a special point
91 if ( ( nDat >> 16 ) == 0x8000 )
93 nNewValue = (sal_uInt16)nDat;
94 rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
96 else
97 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
98 rParameter.Value <<= nNewValue;
101 rtl::OUString EnhancedCustomShape2d::GetEquation( const sal_uInt16 nFlags, sal_Int16 nP1, sal_Int16 nP2, sal_Int16 nP3 )
103 rtl::OUString aEquation;
104 sal_Bool b1Special = ( nFlags & 0x2000 ) != 0;
105 sal_Bool b2Special = ( nFlags & 0x4000 ) != 0;
106 sal_Bool b3Special = ( nFlags & 0x8000 ) != 0;
107 switch( nFlags & 0xff )
109 case 0 :
110 case 14 :
112 sal_Int32 nOptimize = 0;
113 if ( nP1 )
114 nOptimize |= 1;
115 if ( nP2 )
116 nOptimize |= 2;
117 if ( b1Special )
118 nOptimize |= 4;
119 if ( b2Special )
120 nOptimize |= 8;
121 switch( nOptimize )
123 case 0 :
124 break;
125 case 1 :
126 case 4 :
127 case 5 :
128 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
129 break;
130 case 2 :
131 case 8 :
132 case 10:
133 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
134 break;
135 default :
137 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
138 aEquation += rtl::OUString( (sal_Unicode)'+' );
139 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
141 break;
143 if ( b3Special || nP3 )
145 aEquation += rtl::OUString( (sal_Unicode)'-' );
146 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
149 break;
150 case 1 :
152 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
153 if ( b2Special || ( nP2 != 1 ) )
155 aEquation += rtl::OUString( (sal_Unicode)'*' );
156 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
158 if ( b3Special || ( ( nP3 != 1 ) && ( nP3 != 0 ) ) )
160 aEquation += rtl::OUString( (sal_Unicode)'/' );
161 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
164 break;
165 case 2 :
167 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "(" ) );
168 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
169 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "+" ) );
170 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
171 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")/2" ) );
173 break;
174 case 3 :
176 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "abs(" ) );
177 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
178 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
180 break;
181 case 4 :
183 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "min(" ) );
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 ( ")" ) );
189 break;
190 case 5 :
192 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "max(" ) );
193 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
194 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
195 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
196 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
198 break;
199 case 6 :
201 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "if(" ) );
202 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
203 aEquation += rtl::OUString( (sal_Unicode)',' );
204 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
205 aEquation += rtl::OUString( (sal_Unicode)',' );
206 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
207 aEquation += rtl::OUString( (sal_Unicode)')' );
209 break;
210 case 7 :
212 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sqrt(" ) );
213 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
214 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
215 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
216 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "+" ) );
217 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
218 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
219 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
220 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "+" ) );
221 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
222 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
223 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
224 aEquation += rtl::OUString( (sal_Unicode)')' );
226 break;
227 case 8 :
229 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "atan2(" ) );
230 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
231 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
232 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
233 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")/(pi/180)" ) );
235 break;
236 case 9 :
238 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
239 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*sin(" ) );
240 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
241 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))" ) );
243 break;
244 case 10 :
246 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
247 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*cos(" ) );
248 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
249 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))" ) );
251 break;
252 case 11 :
254 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
255 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
256 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "cos(atan2(" ) );
257 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
258 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
259 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
260 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "))" ) );
262 break;
263 case 12 :
265 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
266 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
267 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sin(atan2(" ) );
268 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
269 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "," ) );
270 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
271 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "))" ) );
273 break;
274 case 13 :
276 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sqrt(" ) );
277 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
278 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
280 break;
281 case 15 :
283 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
284 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*sqrt(1-(" ) );
285 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
286 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
287 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
288 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
289 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(" ) );
290 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
291 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
292 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
293 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "))" ) );
295 break;
296 case 16 :
298 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
299 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*tan(" ) );
300 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
301 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( ")" ) );
303 break;
304 case 0x80 :
306 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "sqrt(" ) );
307 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
308 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
309 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
310 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-" ) );
311 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
312 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*" ) );
313 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
314 aEquation += rtl::OUString( (sal_Unicode)')' );
316 break;
317 case 0x81 :
319 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "(cos(" ) );
320 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
321 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
322 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
323 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800)+sin(" ) );
324 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
325 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
326 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
327 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800))+10800" ) );
329 break;
330 case 0x82 :
332 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-(sin(" ) );
333 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
334 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
335 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
336 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800)-cos(" ) );
337 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
338 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "*(pi/180))*(" ) );
339 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
340 aEquation += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "-10800))+10800" ) );
342 break;
344 return aEquation;
347 void EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( rtl::OUString& rParameter, const sal_Int16 nPara, const sal_Bool bIsSpecialValue )
349 if ( bIsSpecialValue )
351 if ( nPara & 0x400 )
353 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "?" ) );
354 rParameter += rtl::OUString::valueOf( (sal_Int32)( nPara & 0xff ) );
355 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( " " ) );
357 else
359 switch( nPara )
361 case DFF_Prop_adjustValue :
362 case DFF_Prop_adjust2Value :
363 case DFF_Prop_adjust3Value :
364 case DFF_Prop_adjust4Value :
365 case DFF_Prop_adjust5Value :
366 case DFF_Prop_adjust6Value :
367 case DFF_Prop_adjust7Value :
368 case DFF_Prop_adjust8Value :
369 case DFF_Prop_adjust9Value :
370 case DFF_Prop_adjust10Value :
372 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "$" ) );
373 rParameter += rtl::OUString::valueOf( (sal_Int32)( nPara - DFF_Prop_adjustValue ) );
374 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( " " ) );
376 break;
377 case DFF_Prop_geoLeft :
379 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "left" ) );
381 break;
382 case DFF_Prop_geoTop :
384 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "top" ) );
386 break;
387 case DFF_Prop_geoRight :
389 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "right" ) );
391 break;
392 case DFF_Prop_geoBottom :
394 rParameter += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "bottom" ) );
396 break;
400 else
402 rParameter += rtl::OUString::valueOf( (sal_Int32)( nPara ) );
406 void EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nPara, const sal_Bool bIsSpecialValue, sal_Bool bHorz )
408 sal_Int32 nValue = 0;
409 if ( bIsSpecialValue )
411 if ( ( nPara >= 0x100 ) && ( nPara <= 0x107 ) )
413 nValue = nPara & 0xff;
414 rParameter.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
416 else if ( ( nPara >= 3 ) && ( nPara <= 0x82 ) )
418 nValue = nPara - 3;
419 rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
421 else if ( nPara == 0 )
423 nValue = 0;
424 if ( bHorz )
425 rParameter.Type = EnhancedCustomShapeParameterType::LEFT;
426 else
427 rParameter.Type = EnhancedCustomShapeParameterType::TOP;
429 else if ( nPara == 1 )
431 nValue = 0;
432 if ( bHorz )
433 rParameter.Type = EnhancedCustomShapeParameterType::RIGHT;
434 else
435 rParameter.Type = EnhancedCustomShapeParameterType::BOTTOM;
437 else if ( nPara == 2 ) // means to be centered, but should not be
438 { // used in our implementation
439 nValue = 5600;
440 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
442 else
444 nValue = nPara;
445 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
448 else
450 nValue = nPara;
451 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
453 rParameter.Value <<= nValue;
456 sal_Bool EnhancedCustomShape2d::ConvertSequenceToEnhancedCustomShape2dHandle(
457 const com::sun::star::beans::PropertyValues& rHandleProperties,
458 EnhancedCustomShape2d::Handle& rDestinationHandle )
460 sal_Bool bRetValue = sal_False;
461 sal_uInt32 i, nProperties = rHandleProperties.getLength();
462 if ( nProperties )
464 rDestinationHandle.nFlags = 0;
465 for ( i = 0; i < nProperties; i++ )
467 const com::sun::star::beans::PropertyValue& rPropVal = rHandleProperties[ i ];
469 const rtl::OUString sPosition ( RTL_CONSTASCII_USTRINGPARAM( "Position" ) );
470 const rtl::OUString sMirroredX ( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) );
471 const rtl::OUString sMirroredY ( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) );
472 const rtl::OUString sSwitched ( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) );
473 const rtl::OUString sPolar ( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) );
474 // const rtl::OUString sMap ( RTL_CONSTASCII_USTRINGPARAM( "Map" ) );
475 const rtl::OUString sRadiusRangeMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) );
476 const rtl::OUString sRadiusRangeMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) );
477 const rtl::OUString sRangeXMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) );
478 const rtl::OUString sRangeXMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) );
479 const rtl::OUString sRangeYMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) );
480 const rtl::OUString sRangeYMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) );
482 if ( rPropVal.Name.equals( sPosition ) )
484 if ( rPropVal.Value >>= rDestinationHandle.aPosition )
485 bRetValue = sal_True;
487 else if ( rPropVal.Name.equals( sMirroredX ) )
489 sal_Bool bMirroredX = sal_Bool();
490 if ( rPropVal.Value >>= bMirroredX )
492 if ( bMirroredX )
493 rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_X;
496 else if ( rPropVal.Name.equals( sMirroredY ) )
498 sal_Bool bMirroredY = sal_Bool();
499 if ( rPropVal.Value >>= bMirroredY )
501 if ( bMirroredY )
502 rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_Y;
505 else if ( rPropVal.Name.equals( sSwitched ) )
507 sal_Bool bSwitched = sal_Bool();
508 if ( rPropVal.Value >>= bSwitched )
510 if ( bSwitched )
511 rDestinationHandle.nFlags |= HANDLE_FLAGS_SWITCHED;
514 else if ( rPropVal.Name.equals( sPolar ) )
516 if ( rPropVal.Value >>= rDestinationHandle.aPolar )
517 rDestinationHandle.nFlags |= HANDLE_FLAGS_POLAR;
519 /* seems not to be used.
520 else if ( rPropVal.Name.equals( sMap ) )
522 com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap;
523 if ( rPropVal.Value >>= aMap )
525 if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) )
526 rDestinationHandle.Flags |= 0x800;
527 if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) )
528 rDestinationHandle.Flags |= 0x1000;
529 rDestinationHandle.Flags |= 0x10;
533 else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) )
535 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMinimum )
536 rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MINIMUM;
538 else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) )
540 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMaximum )
541 rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM;
543 else if ( rPropVal.Name.equals( sRangeXMinimum ) )
545 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMinimum )
546 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MINIMUM;
548 else if ( rPropVal.Name.equals( sRangeXMaximum ) )
550 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMaximum )
551 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MAXIMUM;
553 else if ( rPropVal.Name.equals( sRangeYMinimum ) )
555 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMinimum )
556 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MINIMUM;
558 else if ( rPropVal.Name.equals( sRangeYMaximum ) )
560 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMaximum )
561 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MAXIMUM;
565 return bRetValue;
568 const sal_Int32* EnhancedCustomShape2d::ApplyShapeAttributes( const SdrCustomShapeGeometryItem& rGeometryItem )
570 const sal_Int32* pDefData = NULL;
571 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
572 if ( pDefCustomShape )
573 pDefData = pDefCustomShape->pDefData;
575 //////////////////////
576 // AdjustmentValues //
577 //////////////////////
578 const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
579 const Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sAdjustmentValues );
580 if ( pAny )
581 *pAny >>= seqAdjustmentValues;
583 ///////////////
584 // Coordsize //
585 ///////////////
586 const rtl::OUString sViewBox( RTL_CONSTASCII_USTRINGPARAM ( "ViewBox" ) );
587 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
588 com::sun::star::awt::Rectangle aViewBox;
589 if ( pViewBox && (*pViewBox >>= aViewBox ) )
591 nCoordLeft = aViewBox.X;
592 nCoordTop = aViewBox.Y;
593 nCoordWidth = labs( aViewBox.Width );
594 nCoordHeight= labs( aViewBox.Height);
596 const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM ( "Path" ) );
598 //////////////////////
599 // Path/Coordinates //
600 //////////////////////
601 const rtl::OUString sCoordinates( RTL_CONSTASCII_USTRINGPARAM ( "Coordinates" ) );
602 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
603 if ( pAny )
604 *pAny >>= seqCoordinates;
606 /////////////////////
607 // Path/GluePoints //
608 /////////////////////
609 const rtl::OUString sGluePoints( RTL_CONSTASCII_USTRINGPARAM ( "GluePoints" ) );
610 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
611 if ( pAny )
612 *pAny >>= seqGluePoints;
614 ///////////////////
615 // Path/Segments //
616 ///////////////////
617 const rtl::OUString sSegments( RTL_CONSTASCII_USTRINGPARAM ( "Segments" ) );
618 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSegments );
619 if ( pAny )
620 *pAny >>= seqSegments;
622 ///////////////////
623 // Path/StretchX //
624 ///////////////////
625 const rtl::OUString sStretchX( RTL_CONSTASCII_USTRINGPARAM ( "StretchX" ) );
626 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchX );
627 if ( pAny )
629 sal_Int32 nStretchX = 0;
630 if ( *pAny >>= nStretchX )
631 nXRef = nStretchX;
634 ///////////////////
635 // Path/StretchY //
636 ///////////////////
637 const rtl::OUString sStretchY( RTL_CONSTASCII_USTRINGPARAM ( "StretchY" ) );
638 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchY );
639 if ( pAny )
641 sal_Int32 nStretchY = 0;
642 if ( *pAny >>= nStretchY )
643 nYRef = nStretchY;
646 /////////////////////
647 // Path/TextFrames //
648 /////////////////////
649 const rtl::OUString sTextFrames( RTL_CONSTASCII_USTRINGPARAM ( "TextFrames" ) );
650 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
651 if ( pAny )
652 *pAny >>= seqTextFrames;
654 ///////////////
655 // Equations //
656 ///////////////
657 const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
658 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
659 if ( pAny )
660 *pAny >>= seqEquations;
662 /////////////
663 // Handles //
664 /////////////
665 const rtl::OUString sHandles( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
666 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sHandles );
667 if ( pAny )
668 *pAny >>= seqHandles;
670 return pDefData;
673 EnhancedCustomShape2d::~EnhancedCustomShape2d()
677 EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
678 SfxItemSet ( pAObj->GetMergedItemSet() ),
679 pCustomShapeObj ( pAObj ),
680 eSpType ( mso_sptNil ),
681 nCoordLeft ( 0 ),
682 nCoordTop ( 0 ),
683 nCoordWidth ( 21600 ),
684 nCoordHeight ( 21600 ),
685 nXRef ( 0x80000000 ),
686 nYRef ( 0x80000000 ),
687 nFlags ( 0 ),
688 nColorData ( 0 ),
689 bTextFlow ( sal_False ),
690 bFilled ( ((const XFillStyleItem&)pAObj->GetMergedItem( XATTR_FILLSTYLE )).GetValue() != XFILL_NONE ),
691 bStroked ( ((const XLineStyleItem&)pAObj->GetMergedItem( XATTR_LINESTYLE )).GetValue() != XLINE_NONE ),
692 bFlipH ( sal_False ),
693 bFlipV ( sal_False )
695 // bTextFlow needs to be set before clearing the TextDirection Item
697 ClearItem( SDRATTR_TEXTDIRECTION ); //SJ: vertical writing is not required, by removing this item no outliner is created
699 // For primitive rendering, shadow handling is done completely based on the geometry, so i removed it here
700 ClearItem(SDRATTR_SHADOW);
702 Point aP( pCustomShapeObj->GetSnapRect().Center() );
703 Size aS( pCustomShapeObj->GetLogicRect().GetSize() );
704 aP.X() -= aS.Width() / 2;
705 aP.Y() -= aS.Height() / 2;
706 aLogicRect = Rectangle( aP, aS );
708 const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
709 const rtl::OUString sMirroredX( RTL_CONSTASCII_USTRINGPARAM ( "MirroredX" ) );
710 const rtl::OUString sMirroredY( RTL_CONSTASCII_USTRINGPARAM ( "MirroredY" ) );
712 rtl::OUString sShapeType;
713 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
714 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
715 if ( pAny )
716 *pAny >>= sShapeType;
717 eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
719 pAny = rGeometryItem.GetPropertyValueByName( sMirroredX );
720 if ( pAny )
721 *pAny >>= bFlipH;
722 pAny = rGeometryItem.GetPropertyValueByName( sMirroredY );
723 if ( pAny )
724 *pAny >>= bFlipV;
726 if ( pCustomShapeObj->ISA( SdrObjCustomShape ) ) // should always be a SdrObjCustomShape, but you don't know
727 nRotateAngle = (sal_Int32)(((SdrObjCustomShape*)pCustomShapeObj)->GetObjectRotation() * 100.0);
728 else
729 nRotateAngle = pCustomShapeObj->GetRotateAngle();
731 /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem );
732 switch( eSpType )
734 case mso_sptCan : nColorData = 0x20400000; break;
735 case mso_sptCube : nColorData = 0x302e0000; break;
736 case mso_sptActionButtonBlank : nColorData = 0x502ce400; break;
737 case mso_sptActionButtonHome : nColorData = 0x702ce4ce; break;
738 case mso_sptActionButtonHelp : nColorData = 0x602ce4c0; break;
739 case mso_sptActionButtonInformation : nColorData = 0x702ce4c5; break;
740 case mso_sptActionButtonBackPrevious : nColorData = 0x602ce4c0; break;
741 case mso_sptActionButtonForwardNext : nColorData = 0x602ce4c0; break;
742 case mso_sptActionButtonBeginning : nColorData = 0x602ce4c0; break;
743 case mso_sptActionButtonEnd : nColorData = 0x602ce4c0; break;
744 case mso_sptActionButtonReturn : nColorData = 0x602ce4c0; break;
745 case mso_sptActionButtonDocument : nColorData = 0x702ce4ec; break;
746 case mso_sptActionButtonSound : nColorData = 0x602ce4c0; break;
747 case mso_sptActionButtonMovie : nColorData = 0x602ce4c0; break;
748 case mso_sptBevel : nColorData = 0x502ce400; break;
749 case mso_sptFoldedCorner : nColorData = 0x20e00000; break;
750 case mso_sptSmileyFace : nColorData = 0x20e00000; break;
751 case mso_sptNil :
753 if( sShapeType.getLength() > 4 &&
754 sShapeType.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "col-" )))
756 nColorData = sShapeType.copy( 4 ).toInt32( 16 );
759 break;
760 case mso_sptCurvedLeftArrow :
761 case mso_sptCurvedRightArrow :
762 case mso_sptCurvedUpArrow :
763 case mso_sptCurvedDownArrow : nColorData = 0x2d000000; break;
764 case mso_sptRibbon2 : nColorData = 0x30ee0000; break;
765 case mso_sptRibbon : nColorData = 0x30ee0000; break;
767 case mso_sptEllipseRibbon2 : nColorData = 0x30ee0000; break;
768 case mso_sptEllipseRibbon : nColorData = 0x30ee0000; break;
770 case mso_sptVerticalScroll : nColorData = 0x30ee0000; break;
771 case mso_sptHorizontalScroll : nColorData = 0x30ee0000; break;
772 default:
773 break;
775 fXScale = nCoordWidth == 0 ? 0.0 : (double)aLogicRect.GetWidth() / (double)nCoordWidth;
776 fYScale = nCoordHeight == 0 ? 0.0 : (double)aLogicRect.GetHeight() / (double)nCoordHeight;
777 if ( (sal_uInt32)nXRef != 0x80000000 && aLogicRect.GetHeight() )
779 fXRatio = (double)aLogicRect.GetWidth() / (double)aLogicRect.GetHeight();
780 if ( fXRatio > 1 )
781 fXScale /= fXRatio;
782 else
783 fXRatio = 1.0;
785 else
786 fXRatio = 1.0;
787 if ( (sal_uInt32)nYRef != 0x80000000 && aLogicRect.GetWidth() )
789 fYRatio = (double)aLogicRect.GetHeight() / (double)aLogicRect.GetWidth();
790 if ( fYRatio > 1 )
791 fYScale /= fYRatio;
792 else
793 fYRatio = 1.0;
795 else
796 fYRatio = 1.0;
798 sal_Int32 i, nLength = seqEquations.getLength();
801 if ( nLength )
803 vNodesSharedPtr.resize( nLength );
804 for ( i = 0; i < seqEquations.getLength(); i++ )
808 vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
810 catch ( EnhancedCustomShape::ParseError& )
816 double EnhancedCustomShape2d::GetEnumFunc( const EnumFunc eFunc ) const
818 double fRet = 0.0;
819 switch( eFunc )
821 case ENUM_FUNC_PI : fRet = F_PI; break;
822 case ENUM_FUNC_LEFT : fRet = 0.0; break;
823 case ENUM_FUNC_TOP : fRet = 0.0; break;
824 case ENUM_FUNC_RIGHT : fRet = (double)nCoordWidth * fXRatio; break;
825 case ENUM_FUNC_BOTTOM : fRet = (double)nCoordHeight * fYRatio; break;
826 case ENUM_FUNC_XSTRETCH : fRet = nXRef; break;
827 case ENUM_FUNC_YSTRETCH : fRet = nYRef; break;
828 case ENUM_FUNC_HASSTROKE : fRet = bStroked ? 1.0 : 0.0; break;
829 case ENUM_FUNC_HASFILL : fRet = bFilled ? 1.0 : 0.0; break;
830 case ENUM_FUNC_WIDTH : fRet = nCoordWidth; break;
831 case ENUM_FUNC_HEIGHT : fRet = nCoordHeight; break;
832 case ENUM_FUNC_LOGWIDTH : fRet = aLogicRect.GetWidth(); break;
833 case ENUM_FUNC_LOGHEIGHT : fRet = aLogicRect.GetHeight(); break;
835 return fRet;
837 double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex ) const
839 double fNumber = 0.0;
840 if ( nIndex < seqAdjustmentValues.getLength() )
842 if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
843 seqAdjustmentValues[ nIndex ].Value >>= fNumber;
844 else
846 sal_Int32 nNumber = 0;
847 seqAdjustmentValues[ nIndex ].Value >>= nNumber;
848 fNumber = (double)nNumber;
851 return fNumber;
853 double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
855 double fNumber = 0.0;
856 if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
858 if ( vNodesSharedPtr[ nIndex ].get() )
861 fNumber = (*vNodesSharedPtr[ nIndex ])();
862 if ( !rtl::math::isFinite( fNumber ) )
863 fNumber = 0.0;
865 catch ( ... )
867 /* sal_Bool bUps = sal_True; */
870 return fNumber;
872 sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
874 sal_Int32 nNumber = nDefault;
875 if ( nIndex < seqAdjustmentValues.getLength() )
877 if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
879 double fNumber = 0;
880 seqAdjustmentValues[ nIndex ].Value >>= fNumber;
881 nNumber = (sal_Int32)fNumber;
883 else
884 seqAdjustmentValues[ nIndex ].Value >>= nNumber;
886 return nNumber;
888 sal_Bool EnhancedCustomShape2d::SetAdjustValueAsDouble( const double& rValue, const sal_Int32 nIndex )
890 sal_Bool bRetValue = sal_False;
891 if ( nIndex < seqAdjustmentValues.getLength() )
893 // updating our local adjustment sequence
894 seqAdjustmentValues[ nIndex ].Value <<= rValue;
895 seqAdjustmentValues[ nIndex ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
896 bRetValue = sal_True;
898 return bRetValue;
901 Point EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair& rPair,
902 const sal_Bool bScale, const sal_Bool bReplaceGeoSize ) const
904 Point aRetValue;
905 sal_Bool bExchange = ( nFlags & DFF_CUSTOMSHAPE_EXCH ) != 0; // x <-> y
906 sal_uInt32 nPass = 0;
909 sal_uInt32 nIndex = nPass;
911 if ( bExchange )
912 nIndex ^= 1;
914 double fVal;
915 const EnhancedCustomShapeParameter& rParameter = nIndex ? rPair.Second : rPair.First;
916 if ( nPass ) // height
918 GetParameter( fVal, rParameter, sal_False, bReplaceGeoSize );
919 fVal -= nCoordTop;
920 if ( bScale )
922 fVal *= fYScale;
924 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_V )
925 fVal = aLogicRect.GetHeight() - fVal;
927 aRetValue.Y() = (sal_Int32)fVal;
929 else // width
931 GetParameter( fVal, rParameter, bReplaceGeoSize, sal_False );
932 fVal -= nCoordLeft;
933 if ( bScale )
935 fVal *= fXScale;
937 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_H )
938 fVal = aLogicRect.GetWidth() - fVal;
940 aRetValue.X() = (sal_Int32)fVal;
943 while ( ++nPass < 2 );
944 return aRetValue;
947 sal_Bool EnhancedCustomShape2d::GetParameter( double& rRetValue, const EnhancedCustomShapeParameter& rParameter,
948 const sal_Bool bReplaceGeoWidth, const sal_Bool bReplaceGeoHeight ) const
950 rRetValue = 0.0;
951 sal_Bool bRetValue = sal_False;
952 switch ( rParameter.Type )
954 case EnhancedCustomShapeParameterType::ADJUSTMENT :
956 sal_Int32 nAdjustmentIndex = 0;
957 if ( rParameter.Value >>= nAdjustmentIndex )
959 rRetValue = GetAdjustValueAsDouble( nAdjustmentIndex );
960 bRetValue = sal_True;
963 break;
964 case EnhancedCustomShapeParameterType::EQUATION :
966 sal_Int32 nEquationIndex = 0;
967 if ( rParameter.Value >>= nEquationIndex )
969 rRetValue = GetEquationValueAsDouble( nEquationIndex );
970 bRetValue = sal_True;
973 break;
974 case EnhancedCustomShapeParameterType::NORMAL :
976 if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE )
978 double fValue;
979 if ( rParameter.Value >>= fValue )
981 rRetValue = fValue;
982 bRetValue = sal_True;
985 else
987 sal_Int32 nValue = 0;
988 if ( rParameter.Value >>= nValue )
990 rRetValue = nValue;
991 bRetValue = sal_True;
992 if ( bReplaceGeoWidth && ( nValue == nCoordWidth ) )
993 rRetValue *= fXRatio;
994 else if ( bReplaceGeoHeight && ( nValue == nCoordHeight ) )
995 rRetValue *= fYRatio;
999 break;
1000 case EnhancedCustomShapeParameterType::LEFT :
1002 rRetValue = 0.0;
1003 bRetValue = sal_True;
1005 break;
1006 case EnhancedCustomShapeParameterType::TOP :
1008 rRetValue = 0.0;
1009 bRetValue = sal_True;
1011 break;
1012 case EnhancedCustomShapeParameterType::RIGHT :
1014 rRetValue = nCoordWidth;
1015 bRetValue = sal_True;
1017 break;
1018 case EnhancedCustomShapeParameterType::BOTTOM :
1020 rRetValue = nCoordHeight;
1021 bRetValue = sal_True;
1023 break;
1025 return bRetValue;
1028 // nLumDat 28-31 = number of luminance entries in nLumDat
1029 // nLumDat 27-24 = nLumDatEntry 0
1030 // nLumDat 23-20 = nLumDatEntry 1 ...
1031 // each 4bit entry is to be interpreted as a 10 percent signed luminance changing
1032 sal_Int32 EnhancedCustomShape2d::GetLuminanceChange( sal_uInt32 nIndex ) const
1034 const sal_uInt32 nCount = nColorData >> 28;
1035 if ( !nCount )
1036 return 0;
1038 if ( nIndex >= nCount )
1039 nIndex = nCount - 1;
1041 const sal_Int32 nLumDat = nColorData << ( ( 1 + nIndex ) << 2 );
1042 return ( nLumDat >> 28 ) * 10;
1045 Color EnhancedCustomShape2d::GetColorData( const Color& rFillColor, sal_uInt32 nIndex ) const
1047 const sal_Int32 nLuminance = GetLuminanceChange(nIndex);
1048 if( !nLuminance )
1049 return rFillColor;
1051 basegfx::BColor aHSVColor=
1052 basegfx::tools::rgb2hsv(
1053 basegfx::BColor(rFillColor.GetRed()/255.0,
1054 rFillColor.GetGreen()/255.0,
1055 rFillColor.GetBlue()/255.0));
1056 if( nLuminance > 0 )
1058 aHSVColor.setGreen(
1059 aHSVColor.getGreen() * (1.0-nLuminance/100.0));
1060 aHSVColor.setBlue(
1061 nLuminance/100.0 +
1062 (1.0-nLuminance/100.0)*aHSVColor.getBlue());
1064 else if( nLuminance < 0 )
1066 aHSVColor.setBlue(
1067 (1.0+nLuminance/100.0)*aHSVColor.getBlue());
1070 aHSVColor = basegfx::tools::hsv2rgb(aHSVColor);
1071 return Color( (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(aHSVColor.getRed(),0.0,1.0) * 255.0 + 0.5 ),
1072 (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(aHSVColor.getGreen(),0.0,1.0) * 255.0 + 0.5 ),
1073 (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(aHSVColor.getBlue(),0.0,1.0) * 255.0 + 0.5 ) );
1076 Rectangle EnhancedCustomShape2d::GetTextRect() const
1078 sal_Int32 nIndex, nSize = seqTextFrames.getLength();
1079 if ( !nSize )
1080 return aLogicRect;
1081 nIndex = 0;
1082 if ( bTextFlow && ( nSize > 1 ) )
1083 nIndex++;
1084 Point aTopLeft( GetPoint( seqTextFrames[ nIndex ].TopLeft, sal_True, sal_True ) );
1085 Point aBottomRight( GetPoint( seqTextFrames[ nIndex ].BottomRight, sal_True, sal_True ) );
1086 if ( bFlipH )
1088 aTopLeft.X() = aLogicRect.GetWidth() - aTopLeft.X();
1089 aBottomRight.X() = aLogicRect.GetWidth() - aBottomRight.X();
1091 if ( bFlipV )
1093 aTopLeft.Y() = aLogicRect.GetHeight() - aTopLeft.Y();
1094 aBottomRight.Y() = aLogicRect.GetHeight() - aBottomRight.Y();
1096 Rectangle aRect( aTopLeft, aBottomRight );
1097 aRect.Move( aLogicRect.Left(), aLogicRect.Top() );
1098 aRect.Justify();
1099 return aRect;
1102 sal_uInt32 EnhancedCustomShape2d::GetHdlCount() const
1104 return seqHandles.getLength();
1107 sal_Bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex, Point& rReturnPosition ) const
1109 sal_Bool bRetValue = sal_False;
1110 if ( nIndex < GetHdlCount() )
1112 Handle aHandle;
1113 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1115 if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1117 Point aReferencePoint( GetPoint( aHandle.aPolar, sal_True, sal_False ) );
1119 double fAngle;
1120 double fRadius;
1121 GetParameter( fRadius, aHandle.aPosition.First, sal_False, sal_False );
1122 GetParameter( fAngle, aHandle.aPosition.Second, sal_False, sal_False );
1124 double a = ( 360.0 - fAngle ) * F_PI180;
1125 double dx = fRadius * fXScale;
1126 double fX = dx * cos( a );
1127 double fY =-dx * sin( a );
1128 rReturnPosition =
1129 Point(
1130 Round( fX + aReferencePoint.X() ),
1131 basegfx::fTools::equalZero(fXScale) ? aReferencePoint.Y() :
1132 Round( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) );
1134 else
1136 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1138 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1140 com::sun::star::drawing::EnhancedCustomShapeParameter aFirst = aHandle.aPosition.First;
1141 com::sun::star::drawing::EnhancedCustomShapeParameter aSecond = aHandle.aPosition.Second;
1142 aHandle.aPosition.First = aSecond;
1143 aHandle.aPosition.Second = aFirst;
1146 rReturnPosition = GetPoint( aHandle.aPosition, sal_True, sal_False );
1148 const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1149 if ( aGeoStat.nShearWink )
1151 double nTan = aGeoStat.nTan;
1152 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1153 nTan = -nTan;
1154 ShearPoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1156 if ( nRotateAngle )
1158 double a = nRotateAngle * F_PI18000;
1159 RotatePoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1161 if ( bFlipH )
1162 rReturnPosition.X() = aLogicRect.GetWidth() - rReturnPosition.X();
1163 if ( bFlipV )
1164 rReturnPosition.Y() = aLogicRect.GetHeight() - rReturnPosition.Y();
1165 rReturnPosition.Move( aLogicRect.Left(), aLogicRect.Top() );
1166 bRetValue = sal_True;
1169 return bRetValue;
1172 sal_Bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex, const com::sun::star::awt::Point& rPosition )
1174 sal_Bool bRetValue = sal_False;
1175 if ( nIndex < GetHdlCount() )
1177 Handle aHandle;
1178 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1180 sal_Bool bAdjFirst = aHandle.aPosition.First.Type == EnhancedCustomShapeParameterType::ADJUSTMENT;
1181 sal_Bool bAdjSecond= aHandle.aPosition.Second.Type == EnhancedCustomShapeParameterType::ADJUSTMENT;
1182 if ( bAdjFirst || bAdjSecond )
1184 Point aP( rPosition.X, rPosition.Y );
1185 // apply the negative object rotation to the controller position
1187 aP.Move( -aLogicRect.Left(), -aLogicRect.Top() );
1188 if ( bFlipH )
1189 aP.X() = aLogicRect.GetWidth() - aP.X();
1190 if ( bFlipV )
1191 aP.Y() = aLogicRect.GetHeight() - aP.Y();
1192 if ( nRotateAngle )
1194 double a = -nRotateAngle * F_PI18000;
1195 RotatePoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1197 const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1198 if ( aGeoStat.nShearWink )
1200 double nTan = -aGeoStat.nTan;
1201 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1202 nTan = -nTan;
1203 ShearPoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1206 double fPos1 = aP.X(); //( bFlipH ) ? aLogicRect.GetWidth() - aP.X() : aP.X();
1207 double fPos2 = aP.Y(); //( bFlipV ) ? aLogicRect.GetHeight() -aP.Y() : aP.Y();
1208 fPos1 /= fXScale;
1209 fPos2 /= fYScale;
1211 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1213 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1215 double fX = fPos1;
1216 double fY = fPos2;
1217 fPos1 = fY;
1218 fPos2 = fX;
1222 sal_Int32 nFirstAdjustmentValue = 0, nSecondAdjustmentValue = 0;
1223 aHandle.aPosition.First.Value >>= nFirstAdjustmentValue;
1224 aHandle.aPosition.Second.Value>>= nSecondAdjustmentValue;
1226 if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1228 double fXRef, fYRef, fAngle;
1229 GetParameter( fXRef, aHandle.aPolar.First, sal_False, sal_False );
1230 GetParameter( fYRef, aHandle.aPolar.Second, sal_False, sal_False );
1231 const double fDX = fPos1 - fXRef;
1232 fAngle = -( atan2( -fPos2 + fYRef, ( ( fDX == 0.0L ) ? 0.000000001 : fDX ) ) / F_PI180 );
1233 double fX = ( fPos1 - fXRef );
1234 double fY = ( fPos2 - fYRef );
1235 double fRadius = sqrt( fX * fX + fY * fY );
1236 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MINIMUM )
1238 double fMin;
1239 GetParameter( fMin, aHandle.aRadiusRangeMinimum, sal_False, sal_False );
1240 if ( fRadius < fMin )
1241 fRadius = fMin;
1243 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM )
1245 double fMax;
1246 GetParameter( fMax, aHandle.aRadiusRangeMaximum, sal_False, sal_False );
1247 if ( fRadius > fMax )
1248 fRadius = fMax;
1250 if ( bAdjFirst )
1251 SetAdjustValueAsDouble( fRadius, nFirstAdjustmentValue );
1252 if ( bAdjSecond )
1253 SetAdjustValueAsDouble( fAngle, nSecondAdjustmentValue );
1255 else
1257 if ( bAdjFirst )
1259 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MINIMUM ) // check if horizontal handle needs to be within a range
1261 double fXMin;
1262 GetParameter( fXMin, aHandle.aXRangeMinimum, sal_False, sal_False );
1263 if ( fPos1 < fXMin )
1264 fPos1 = fXMin;
1266 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MAXIMUM ) // check if horizontal handle needs to be within a range
1268 double fXMax;
1269 GetParameter( fXMax, aHandle.aXRangeMaximum, sal_False, sal_False );
1270 if ( fPos1 > fXMax )
1271 fPos1 = fXMax;
1273 SetAdjustValueAsDouble( fPos1, nFirstAdjustmentValue );
1275 if ( bAdjSecond )
1277 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MINIMUM ) // check if vertical handle needs to be within a range
1279 double fYMin;
1280 GetParameter( fYMin, aHandle.aYRangeMinimum, sal_False, sal_False );
1281 if ( fPos2 < fYMin )
1282 fPos2 = fYMin;
1284 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MAXIMUM ) // check if vertical handle needs to be within a range
1286 double fYMax;
1287 GetParameter( fYMax, aHandle.aYRangeMaximum, sal_False, sal_False );
1288 if ( fPos2 > fYMax )
1289 fPos2 = fYMax;
1291 SetAdjustValueAsDouble( fPos2, nSecondAdjustmentValue );
1294 // and writing them back into the GeometryItem
1295 SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)
1296 (const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1297 const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM ( "AdjustmentValues" ) );
1298 com::sun::star::beans::PropertyValue aPropVal;
1299 aPropVal.Name = sAdjustmentValues;
1300 aPropVal.Value <<= seqAdjustmentValues;
1301 aGeometryItem.SetPropertyValue( aPropVal );
1302 pCustomShapeObj->SetMergedItem( aGeometryItem );
1303 bRetValue = sal_True;
1307 return bRetValue;
1310 void EnhancedCustomShape2d::SwapStartAndEndArrow( SdrObject* pObj ) //#108274
1312 XLineStartItem aLineStart;
1313 aLineStart.SetLineStartValue(((XLineStartItem&)pObj->GetMergedItem( XATTR_LINEEND )).GetLineStartValue());
1314 XLineStartWidthItem aLineStartWidth(((XLineStartWidthItem&)pObj->GetMergedItem( XATTR_LINEENDWIDTH )).GetValue());
1315 XLineStartCenterItem aLineStartCenter(((XLineStartCenterItem&)pObj->GetMergedItem( XATTR_LINEENDCENTER )).GetValue());
1317 XLineEndItem aLineEnd;
1318 aLineEnd.SetLineEndValue(((XLineEndItem&)pObj->GetMergedItem( XATTR_LINESTART )).GetLineEndValue());
1319 XLineEndWidthItem aLineEndWidth(((XLineEndWidthItem&)pObj->GetMergedItem( XATTR_LINESTARTWIDTH )).GetValue());
1320 XLineEndCenterItem aLineEndCenter(((XLineEndCenterItem&)pObj->GetMergedItem( XATTR_LINESTARTCENTER )).GetValue());
1322 pObj->SetMergedItem( aLineStart );
1323 pObj->SetMergedItem( aLineStartWidth );
1324 pObj->SetMergedItem( aLineStartCenter );
1325 pObj->SetMergedItem( aLineEnd );
1326 pObj->SetMergedItem( aLineEndWidth );
1327 pObj->SetMergedItem( aLineEndCenter );
1330 basegfx::B2DPolygon CreateArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, const sal_Bool bClockwise )
1332 Rectangle aRect( rRect );
1333 Point aStart( rStart );
1334 Point aEnd( rEnd );
1336 sal_Int32 bSwapStartEndAngle = 0;
1338 if ( aRect.Left() > aRect.Right() )
1339 bSwapStartEndAngle ^= 0x01;
1340 if ( aRect.Top() > aRect.Bottom() )
1341 bSwapStartEndAngle ^= 0x11;
1342 if ( bSwapStartEndAngle )
1344 aRect.Justify();
1345 if ( bSwapStartEndAngle & 1 )
1347 Point aTmp( aStart );
1348 aStart = aEnd;
1349 aEnd = aTmp;
1353 Polygon aTempPoly( aRect, aStart, aEnd, POLY_ARC );
1354 basegfx::B2DPolygon aRetval;
1356 if ( bClockwise )
1358 for ( sal_uInt16 j = aTempPoly.GetSize(); j--; )
1360 aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1363 else
1365 for ( sal_uInt16 j = 0; j < aTempPoly.GetSize(); j++ )
1367 aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1371 return aRetval;
1374 void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegmentInd, std::vector< SdrPathObj* >& rObjectList,
1375 const sal_Bool bLineGeometryNeededOnly,
1376 const sal_Bool bSortFilledObjectsToBack )
1378 sal_Bool bNoFill = sal_False;
1379 sal_Bool bNoStroke = sal_False;
1381 basegfx::B2DPolyPolygon aNewB2DPolyPolygon;
1382 basegfx::B2DPolygon aNewB2DPolygon;
1384 sal_Int32 nCoordSize = seqCoordinates.getLength();
1385 sal_Int32 nSegInfoSize = seqSegments.getLength();
1386 if ( !nSegInfoSize )
1388 const EnhancedCustomShapeParameterPair* pTmp = seqCoordinates.getArray();
1390 for ( sal_Int32 nPtNum(0L); nPtNum < nCoordSize; nPtNum++ )
1392 const Point aTempPoint(GetPoint( *pTmp++, sal_True, sal_True ));
1393 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1396 aNewB2DPolygon.setClosed(true);
1398 else
1400 for ( ;rSegmentInd < nSegInfoSize; )
1402 sal_Int16 nCommand = seqSegments[ rSegmentInd ].Command;
1403 sal_Int16 nPntCount= seqSegments[ rSegmentInd++ ].Count;
1405 switch ( nCommand )
1407 case NOFILL :
1408 bNoFill = sal_True;
1409 break;
1410 case NOSTROKE :
1411 bNoStroke = sal_True;
1412 break;
1413 case MOVETO :
1415 if(aNewB2DPolygon.count() > 1L)
1417 // #i76201# Add conversion to closed polygon when first and last points are equal
1418 basegfx::tools::checkClosed(aNewB2DPolygon);
1419 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1422 aNewB2DPolygon.clear();
1424 if ( rSrcPt < nCoordSize )
1426 const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1427 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1430 break;
1431 case ENDSUBPATH :
1432 break;
1433 case CLOSESUBPATH :
1435 if(aNewB2DPolygon.count())
1437 if(aNewB2DPolygon.count() > 1L)
1439 aNewB2DPolygon.setClosed(true);
1440 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1443 aNewB2DPolygon.clear();
1446 break;
1447 case CURVETO :
1449 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1451 const Point aControlA(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1452 const Point aControlB(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1453 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1455 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding control point (!)");
1456 aNewB2DPolygon.appendBezierSegment(
1457 basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1458 basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1459 basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1462 break;
1464 case ANGLEELLIPSE :
1466 if(aNewB2DPolygon.count() > 1L)
1468 // #i76201# Add conversion to closed polygon when first and last points are equal
1469 basegfx::tools::checkClosed(aNewB2DPolygon);
1470 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1473 aNewB2DPolygon.clear();
1475 case ANGLEELLIPSETO :
1477 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1479 // create a circle
1480 Point _aCenter( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ) );
1481 double fWidth, fHeight;
1482 GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, sal_True, sal_False );
1483 GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, sal_False, sal_True );
1484 fWidth *= fXScale;
1485 fHeight*= fYScale;
1486 Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1487 Size aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1488 Rectangle aRect( aP, aS );
1489 if ( aRect.GetWidth() && aRect.GetHeight() )
1491 double fStartAngle, fEndAngle;
1492 GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First, sal_False, sal_False );
1493 GetParameter( fEndAngle , seqCoordinates[ rSrcPt + 2 ].Second, sal_False, sal_False );
1495 if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1497 if ( (sal_Int32)fStartAngle & 0x7fff0000 ) // SJ: if the angle was imported from our escher import, then the
1498 fStartAngle /= 65536.0; // value is shifted by 16. TODO: already change the fixed float to a
1499 if ( (sal_Int32)fEndAngle & 0x7fff0000 ) // double in the import filter
1501 fEndAngle /= 65536.0;
1502 fEndAngle = fEndAngle + fStartAngle;
1503 if ( fEndAngle < 0 )
1504 { // in the binary filter the endangle is the amount
1505 double fTemp = fStartAngle;
1506 fStartAngle = fEndAngle;
1507 fEndAngle = fTemp;
1510 double fCenterX = aRect.Center().X();
1511 double fCenterY = aRect.Center().Y();
1512 double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1513 double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1514 double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1515 double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1516 aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), sal_False));
1518 else
1519 { /* SJ: TODO: this block should be replaced sometimes, because the current point
1520 is not set correct, it also does not use the correct moveto
1521 point if ANGLEELLIPSETO was used, but the method CreateArc
1522 is at the moment not able to draw full circles (if startangle is 0
1523 and endangle 360 nothing is painted :-( */
1524 sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1525 sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1526 Point aCenter( aRect.Center() );
1528 // append start point
1529 aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1531 // append four bezier segments
1532 aNewB2DPolygon.appendBezierSegment(
1533 basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1534 basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1535 basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1537 aNewB2DPolygon.appendBezierSegment(
1538 basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1539 basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1540 basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1542 aNewB2DPolygon.appendBezierSegment(
1543 basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1544 basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1545 basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1547 aNewB2DPolygon.appendBezierSegment(
1548 basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1549 basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1550 basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1552 // close, rescue last controlpoint, remove double last point
1553 basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1556 rSrcPt += 3;
1559 break;
1561 case LINETO :
1563 for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1565 const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], sal_True, sal_True ));
1566 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1569 break;
1571 case ARC :
1572 case CLOCKWISEARC :
1574 if(aNewB2DPolygon.count() > 1L)
1576 // #i76201# Add conversion to closed polygon when first and last points are equal
1577 basegfx::tools::checkClosed(aNewB2DPolygon);
1578 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1581 aNewB2DPolygon.clear();
1583 case ARCTO :
1584 case CLOCKWISEARCTO :
1586 sal_Bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1587 sal_uInt32 nXor = bClockwise ? 3 : 2;
1588 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1590 Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ), GetPoint( seqCoordinates[ rSrcPt + 1 ], sal_True, sal_True ) );
1591 if ( aRect.GetWidth() && aRect.GetHeight() )
1593 Point aCenter( aRect.Center() );
1594 Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], sal_True, sal_True ) );
1595 Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], sal_True, sal_True ) );
1596 double fRatio = (double)aRect.GetHeight() / (double)aRect.GetWidth();
1597 aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1598 aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1599 aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) * fRatio ) + aCenter.X();
1600 aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1601 aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1603 rSrcPt += 4;
1606 break;
1608 case ELLIPTICALQUADRANTX :
1609 case ELLIPTICALQUADRANTY :
1611 bool bFirstDirection(true);
1612 basegfx::B2DPoint aControlPointA;
1613 basegfx::B2DPoint aControlPointB;
1615 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1617 sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1618 Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], sal_True, sal_True ) );
1620 if ( rSrcPt ) // we need a previous point
1622 Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], sal_True, sal_True ) );
1623 sal_Int32 nX, nY;
1624 nX = aCurrent.X() - aPrev.X();
1625 nY = aCurrent.Y() - aPrev.Y();
1626 if ( ( nY ^ nX ) & 0x80000000 )
1628 if ( !i )
1629 bFirstDirection = true;
1630 else if ( !bFirstDirection )
1631 nModT ^= 1;
1633 else
1635 if ( !i )
1636 bFirstDirection = false;
1637 else if ( bFirstDirection )
1638 nModT ^= 1;
1640 if ( nModT ) // get the right corner
1642 nX = aCurrent.X();
1643 nY = aPrev.Y();
1645 else
1647 nX = aPrev.X();
1648 nY = aCurrent.Y();
1650 sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1651 sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1652 Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1654 aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1656 nXVec = ( nX - aCurrent.X() ) >> 1;
1657 nYVec = ( nY - aCurrent.Y() ) >> 1;
1658 Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1660 aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1662 aNewB2DPolygon.appendBezierSegment(
1663 aControlPointA,
1664 aControlPointB,
1665 basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1667 else
1669 aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1672 rSrcPt++;
1675 break;
1677 #ifdef DBG_CUSTOMSHAPE
1678 case UNKNOWN :
1679 default :
1681 ByteString aString( "CustomShapes::unknown PolyFlagValue :" );
1682 aString.Append( ByteString::CreateFromInt32( nCommand ) );
1683 DBG_ERROR( aString.GetBuffer() );
1685 break;
1686 #endif
1688 if ( nCommand == ENDSUBPATH )
1689 break;
1692 if ( rSegmentInd == nSegInfoSize )
1693 rSegmentInd++;
1695 if(aNewB2DPolygon.count() > 1L)
1697 // #i76201# Add conversion to closed polygon when first and last points are equal
1698 basegfx::tools::checkClosed(aNewB2DPolygon);
1699 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1702 if(aNewB2DPolyPolygon.count())
1704 if( !bLineGeometryNeededOnly )
1706 // hack aNewB2DPolyPolygon to fill logic rect - this is
1707 // needed to produce gradient fills that look like mso
1708 aNewB2DPolygon.clear();
1709 aNewB2DPolygon.append(basegfx::B2DPoint(0,0));
1710 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1712 aNewB2DPolygon.clear();
1713 aNewB2DPolygon.append(basegfx::B2DPoint(aLogicRect.GetWidth(),
1714 aLogicRect.GetHeight()));
1715 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1717 // #i37011#
1718 bool bForceCreateTwoObjects(false);
1720 if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1722 bForceCreateTwoObjects = true;
1725 if(bLineGeometryNeededOnly)
1727 bForceCreateTwoObjects = true;
1728 bNoFill = true;
1729 bNoStroke = false;
1732 if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1734 if(bFilled && !bNoFill)
1736 basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1737 aClosedPolyPolygon.setClosed(true);
1738 SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon);
1739 SfxItemSet aTempSet(*this);
1740 aTempSet.Put(SdrShadowItem(sal_False));
1741 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1742 pFill->SetMergedItemSet(aTempSet);
1743 rObjectList.push_back(pFill);
1746 if(!bNoStroke)
1748 // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
1749 // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
1750 // to correct the polygon (here: open it) using the type, the last edge may get lost.
1751 // Thus, use a type that fits the polygon
1752 SdrPathObj* pStroke = new SdrPathObj(
1753 aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1754 aNewB2DPolyPolygon);
1755 SfxItemSet aTempSet(*this);
1756 aTempSet.Put(SdrShadowItem(sal_False));
1757 aTempSet.Put(XFillStyleItem(XFILL_NONE));
1758 pStroke->SetMergedItemSet(aTempSet);
1759 rObjectList.push_back(pStroke);
1762 else
1764 SdrPathObj* pObj = 0;
1765 SfxItemSet aTempSet(*this);
1766 aTempSet.Put(SdrShadowItem(sal_False));
1768 if(bNoFill)
1770 // see comment above about OBJ_PLIN
1771 pObj = new SdrPathObj(
1772 aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
1773 aNewB2DPolyPolygon);
1774 aTempSet.Put(XFillStyleItem(XFILL_NONE));
1776 else
1778 aNewB2DPolyPolygon.setClosed(true);
1779 pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon);
1782 if(bNoStroke)
1784 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1787 if(pObj)
1789 pObj->SetMergedItemSet(aTempSet);
1790 rObjectList.push_back(pObj);
1796 void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
1798 sal_Bool bAccent = sal_False;
1799 switch( eSpType )
1801 case mso_sptCallout1 :
1802 case mso_sptBorderCallout1 :
1803 case mso_sptCallout90 :
1804 case mso_sptBorderCallout90 :
1805 default:
1806 break;
1808 case mso_sptAccentCallout1 :
1809 case mso_sptAccentBorderCallout1 :
1810 case mso_sptAccentCallout90 :
1811 case mso_sptAccentBorderCallout90 :
1813 sal_uInt32 i, nLine = 0;
1814 for ( i = 0; i < vObjectList.size(); i++ )
1816 SdrPathObj* pObj( vObjectList[ i ] );
1817 if(pObj->IsLine())
1819 nLine++;
1820 if ( nLine == nLineObjectCount )
1822 pObj->ClearMergedItem( XATTR_LINESTART );
1823 pObj->ClearMergedItem( XATTR_LINEEND );
1828 break;
1830 // switch start & end
1831 case mso_sptAccentCallout2 :
1832 case mso_sptAccentBorderCallout2 :
1833 bAccent = sal_True;
1834 case mso_sptCallout2 :
1835 case mso_sptBorderCallout2 :
1837 sal_uInt32 i, nLine = 0;
1838 for ( i = 0; i < vObjectList.size(); i++ )
1840 SdrPathObj* pObj( vObjectList[ i ] );
1841 if(pObj->IsLine())
1843 nLine++;
1844 if ( nLine == 1 )
1845 pObj->ClearMergedItem( XATTR_LINEEND );
1846 else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
1847 pObj->ClearMergedItem( XATTR_LINESTART );
1848 else
1850 pObj->ClearMergedItem( XATTR_LINESTART );
1851 pObj->ClearMergedItem( XATTR_LINEEND );
1856 break;
1858 case mso_sptAccentCallout3 :
1859 case mso_sptAccentBorderCallout3 :
1860 bAccent = sal_False;
1861 case mso_sptCallout3 :
1862 case mso_sptBorderCallout3 :
1864 sal_uInt32 i, nLine = 0;
1865 for ( i = 0; i < vObjectList.size(); i++ )
1867 SdrPathObj* pObj( vObjectList[ i ] );
1868 if(pObj->IsLine())
1870 if ( nLine )
1872 pObj->ClearMergedItem( XATTR_LINESTART );
1873 pObj->ClearMergedItem( XATTR_LINEEND );
1875 else
1876 EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
1878 nLine++;
1882 break;
1886 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
1887 sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
1889 if ( !rObj.IsLine() )
1891 const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1892 switch( eFillStyle )
1894 default:
1895 case XFILL_SOLID:
1897 Color aFillColor;
1898 if ( nColorCount )
1900 aFillColor = GetColorData(
1901 ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
1902 std::min(nColorIndex, nColorCount-1) );
1903 rObj.SetMergedItem( XFillColorItem( String(), aFillColor ) );
1905 break;
1907 case XFILL_GRADIENT:
1909 XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
1910 if ( nColorCount )
1912 aXGradient.SetStartColor(
1913 GetColorData(
1914 aXGradient.GetStartColor(),
1915 std::min(nColorIndex, nColorCount-1) ));
1916 aXGradient.SetEndColor(
1917 GetColorData(
1918 aXGradient.GetEndColor(),
1919 std::min(nColorIndex, nColorCount-1) ));
1922 rObj.SetMergedItem( XFillGradientItem( String(), aXGradient ) );
1923 break;
1925 case XFILL_HATCH:
1927 XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
1928 if ( nColorCount )
1930 aXHatch.SetColor(
1931 GetColorData(
1932 aXHatch.GetColor(),
1933 std::min(nColorIndex, nColorCount-1) ));
1936 rObj.SetMergedItem( XFillHatchItem( String(), aXHatch ) );
1937 break;
1939 case XFILL_BITMAP:
1941 Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetBitmapValue().GetBitmap());
1942 if ( nColorCount )
1944 aBitmap.Adjust(
1945 static_cast< short > ( GetLuminanceChange(
1946 std::min(nColorIndex, nColorCount-1))));
1949 rObj.SetMergedItem( XFillBitmapItem( String(), aBitmap ) );
1950 break;
1954 if ( nColorIndex < nColorCount )
1955 nColorIndex++;
1959 SdrObject* EnhancedCustomShape2d::CreatePathObj( sal_Bool bLineGeometryNeededOnly )
1961 sal_Int32 nCoordSize = seqCoordinates.getLength();
1962 if ( !nCoordSize )
1963 return NULL;
1965 sal_uInt16 nSrcPt = 0;
1966 sal_uInt16 nSegmentInd = 0;
1968 std::vector< SdrPathObj* > vObjectList;
1969 sal_Bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
1971 while( nSegmentInd <= seqSegments.getLength() )
1973 CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack );
1976 SdrObject* pRet = NULL;
1977 sal_uInt32 i;
1979 if ( vObjectList.size() )
1981 const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
1982 Color aFillColor;
1983 sal_uInt32 nColorCount = nColorData >> 28;
1984 sal_uInt32 nColorIndex = 0;
1986 // #i37011# remove invisible objects
1987 if(vObjectList.size())
1989 std::vector< SdrPathObj* > vTempList;
1991 for(i = 0L; i < vObjectList.size(); i++)
1993 SdrPathObj* pObj(vObjectList[i]);
1994 const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
1995 const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
1997 //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
1998 if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
1999 delete pObj;
2000 else
2001 vTempList.push_back(pObj);
2004 vObjectList = vTempList;
2007 if(1L == vObjectList.size())
2009 // a single object, correct some values
2010 AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2012 else
2014 sal_Int32 nLineObjectCount = 0;
2015 sal_Int32 nAreaObjectCount = 0;
2017 // correct some values and collect content data
2018 for ( i = 0; i < vObjectList.size(); i++ )
2020 SdrPathObj* pObj( vObjectList[ i ] );
2022 if(pObj->IsLine())
2024 nLineObjectCount++;
2026 else
2028 nAreaObjectCount++;
2029 AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2033 // #i88870# correct line arrows for callouts
2034 if ( nLineObjectCount )
2035 CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2037 // sort objects so that filled ones are in front. Necessary
2038 // for some strange objects
2039 if ( bSortFilledObjectsToBack )
2041 std::vector< SdrPathObj* > vTempList;
2043 for ( i = 0; i < vObjectList.size(); i++ )
2045 SdrPathObj* pObj( vObjectList[ i ] );
2047 if ( !pObj->IsLine() )
2049 vTempList.push_back(pObj);
2053 for ( i = 0; i < vObjectList.size(); i++ )
2055 SdrPathObj* pObj( vObjectList[ i ] );
2057 if ( pObj->IsLine() )
2059 vTempList.push_back(pObj);
2063 vObjectList = vTempList;
2068 // #i37011#
2069 if(vObjectList.size())
2071 // copy remaining objects to pRet
2072 if(vObjectList.size() > 1L)
2074 pRet = new SdrObjGroup;
2076 for (i = 0L; i < vObjectList.size(); i++)
2078 SdrObject* pObj(vObjectList[i]);
2079 pRet->GetSubList()->NbcInsertObject(pObj);
2082 else if(1L == vObjectList.size())
2084 pRet = vObjectList[0L];
2087 if(pRet)
2089 // move to target position
2090 Rectangle aCurRect(pRet->GetSnapRect());
2091 aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2092 pRet->NbcSetSnapRect(aCurRect);
2096 return pRet;
2099 SdrObject* EnhancedCustomShape2d::CreateObject( sal_Bool bLineGeometryNeededOnly )
2101 SdrObject* pRet = NULL;
2103 if ( eSpType == mso_sptRectangle )
2105 pRet = new SdrRectObj( aLogicRect );
2106 // SJ: not setting model, so we save a lot of broadcasting and the model is not modified any longer
2107 // pRet->SetModel( pCustomShapeObj->GetModel() );
2108 pRet->SetMergedItemSet( *this );
2110 if ( !pRet )
2111 pRet = CreatePathObj( bLineGeometryNeededOnly );
2113 return pRet;
2116 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2118 if ( pObj && seqGluePoints.getLength() )
2120 sal_uInt32 i, nCount = seqGluePoints.getLength();
2121 for ( i = 0; i < nCount; i++ )
2123 SdrGluePoint aGluePoint;
2125 aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], sal_True, sal_True ) );
2126 aGluePoint.SetPercent( sal_False );
2128 // const Point& rPoint = GetPoint( seqGluePoints[ i ], sal_True, sal_True );
2129 // double fXRel = rPoint.X();
2130 // double fYRel = rPoint.Y();
2131 // fXRel = aLogicRect.GetWidth() == 0 ? 0.0 : fXRel / aLogicRect.GetWidth() * 10000;
2132 // fYRel = aLogicRect.GetHeight() == 0 ? 0.0 : fYRel / aLogicRect.GetHeight() * 10000;
2133 // aGluePoint.SetPos( Point( (sal_Int32)fXRel, (sal_Int32)fYRel ) );
2134 // aGluePoint.SetPercent( sal_True );
2135 aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2136 aGluePoint.SetEscDir( SDRESC_SMART );
2137 SdrGluePointList* pList = pObj->ForceGluePointList();
2138 if( pList )
2139 /* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2144 SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2146 return CreateObject( sal_True );