fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShape2d.cxx
blobf17e145d2d47b48d248226ee4fc912dc0936e7b6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svx/EnhancedCustomShape2d.hxx"
21 #include "svx/EnhancedCustomShapeGeometry.hxx"
22 #include "svx/EnhancedCustomShapeTypeNames.hxx"
23 #include <svx/svdoashp.hxx>
24 #include <svx/svdtrans.hxx>
25 #include <svx/svdocirc.hxx>
26 #include <svx/svdogrp.hxx>
27 #include <svx/svdopath.hxx>
28 #include <svx/svdocapt.hxx>
29 #include <svx/svdpage.hxx>
30 #include <svx/xflclit.hxx>
31 #include <svx/sdasaitm.hxx>
32 #include <svx/svdmodel.hxx>
33 #include <rtl/crc.h>
34 #include <rtl/math.hxx>
35 #include <svx/xfillit0.hxx>
36 #include <svx/xlnstit.hxx>
37 #include <svx/xlnedit.hxx>
38 #include <svx/xlnstwit.hxx>
39 #include <svx/xlnedwit.hxx>
40 #include <svx/xlnstcit.hxx>
41 #include <svx/xlnedcit.hxx>
42 #include <svx/xflgrit.hxx>
43 #include <svx/xflhtit.hxx>
44 #include <svx/xbtmpit.hxx>
45 #include <svx/xgrad.hxx>
46 #include <svx/xhatch.hxx>
47 #include <com/sun/star/awt/Size.hpp>
48 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
49 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
50 #include <boost/shared_ptr.hpp>
51 #include <basegfx/numeric/ftools.hxx>
52 #include <basegfx/color/bcolortools.hxx>
53 #include <basegfx/polygon/b2dpolygon.hxx>
55 // #i76201#
56 #include <basegfx/polygon/b2dpolygontools.hxx>
57 #include <rtl/strbuf.hxx>
58 #include <math.h>
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::drawing;
62 using namespace ::com::sun::star::drawing::EnhancedCustomShapeSegmentCommand;
64 void EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nValue )
66 sal_uInt32 nDat = (sal_uInt32)nValue;
67 sal_Int32 nNewValue = nValue;
69 // check if this is a special point
70 if ( ( nDat >> 16 ) == 0x8000 )
72 nNewValue = (sal_uInt16)nDat;
73 rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
75 else
76 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
77 rParameter.Value <<= nNewValue;
80 OUString EnhancedCustomShape2d::GetEquation( const sal_uInt16 nFlags, sal_Int32 nP1, sal_Int32 nP2, sal_Int32 nP3 )
82 OUString aEquation;
83 bool b1Special = ( nFlags & 0x2000 ) != 0;
84 bool b2Special = ( nFlags & 0x4000 ) != 0;
85 bool b3Special = ( nFlags & 0x8000 ) != 0;
86 switch( nFlags & 0xff )
88 case 0 :
89 case 14 :
91 sal_Int32 nOptimize = 0;
92 if ( nP1 )
93 nOptimize |= 1;
94 if ( nP2 )
95 nOptimize |= 2;
96 if ( b1Special )
97 nOptimize |= 4;
98 if ( b2Special )
99 nOptimize |= 8;
100 switch( nOptimize )
102 case 0 :
103 break;
104 case 1 :
105 case 4 :
106 case 5 :
107 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
108 break;
109 case 2 :
110 case 8 :
111 case 10:
112 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
113 break;
114 default :
116 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
117 aEquation += OUString( (sal_Unicode)'+' );
118 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
120 break;
122 if ( b3Special || nP3 )
124 aEquation += OUString( (sal_Unicode)'-' );
125 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
128 break;
129 case 1 :
131 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
132 if ( b2Special || ( nP2 != 1 ) )
134 aEquation += OUString( (sal_Unicode)'*' );
135 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
137 if ( b3Special || ( ( nP3 != 1 ) && ( nP3 != 0 ) ) )
139 aEquation += OUString( (sal_Unicode)'/' );
140 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
143 break;
144 case 2 :
146 aEquation += "(";
147 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
148 aEquation += "+";
149 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
150 aEquation += ")/2";
152 break;
153 case 3 :
155 aEquation += "abs(";
156 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
157 aEquation += ")";
159 break;
160 case 4 :
162 aEquation += "min(";
163 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
164 aEquation += ",";
165 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
166 aEquation += ")";
168 break;
169 case 5 :
171 aEquation += "max(";
172 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
173 aEquation += ",";
174 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
175 aEquation += ")";
177 break;
178 case 6 :
180 aEquation += "if(";
181 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
182 aEquation += OUString( (sal_Unicode)',' );
183 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
184 aEquation += OUString( (sal_Unicode)',' );
185 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
186 aEquation += OUString( (sal_Unicode)')' );
188 break;
189 case 7 :
191 aEquation += "sqrt(";
192 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
193 aEquation += "*";
194 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
195 aEquation += "+";
196 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
197 aEquation += "*";
198 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
199 aEquation += "+";
200 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
201 aEquation += "*";
202 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
203 aEquation += OUString( (sal_Unicode)')' );
205 break;
206 case 8 :
208 aEquation += "atan2(";
209 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
210 aEquation += ",";
211 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
212 aEquation += ")/(pi/180)";
214 break;
215 case 9 :
217 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
218 aEquation += "*sin(";
219 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
220 aEquation += "*(pi/180))";
222 break;
223 case 10 :
225 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
226 aEquation += "*cos(";
227 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
228 aEquation += "*(pi/180))";
230 break;
231 case 11 :
233 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
234 aEquation += "*cos(atan2(";
235 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
236 aEquation += ",";
237 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
238 aEquation += "))";
240 break;
241 case 12 :
243 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
244 aEquation += "*sin(atan2(";
245 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
246 aEquation += ",";
247 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
248 aEquation += "))";
250 break;
251 case 13 :
253 aEquation += "sqrt(";
254 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
255 aEquation += ")";
257 break;
258 case 15 :
260 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
261 aEquation += "*sqrt(1-(";
262 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
263 aEquation += "/";
264 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
265 aEquation += ")";
266 aEquation += "*(";
267 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
268 aEquation += "/";
269 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
270 aEquation += "))";
272 break;
273 case 16 :
275 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
276 aEquation += "*tan(";
277 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
278 aEquation += ")";
280 break;
281 case 0x80 :
283 aEquation += "sqrt(";
284 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
285 aEquation += "*";
286 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
287 aEquation += "-";
288 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
289 aEquation += "*";
290 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
291 aEquation += OUString( (sal_Unicode)')' );
293 break;
294 case 0x81 :
296 aEquation += "(cos(";
297 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
298 aEquation += "*(pi/180))*(";
299 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
300 aEquation += "-10800)+sin(";
301 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
302 aEquation += "*(pi/180))*(";
303 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
304 aEquation += "-10800))+10800";
306 break;
307 case 0x82 :
309 aEquation += "-(sin(";
310 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
311 aEquation += "*(pi/180))*(";
312 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
313 aEquation += "-10800)-cos(";
314 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
315 aEquation += "*(pi/180))*(";
316 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
317 aEquation += "-10800))+10800";
319 break;
321 return aEquation;
324 void EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( OUString& rParameter, const sal_Int32 nPara, const bool bIsSpecialValue )
326 if ( bIsSpecialValue )
328 if ( nPara & 0x400 )
330 rParameter += "?";
331 rParameter += OUString::valueOf( (sal_Int32)( nPara & 0xff ) );
332 rParameter += " ";
334 else
336 switch( nPara )
338 case DFF_Prop_adjustValue :
339 case DFF_Prop_adjust2Value :
340 case DFF_Prop_adjust3Value :
341 case DFF_Prop_adjust4Value :
342 case DFF_Prop_adjust5Value :
343 case DFF_Prop_adjust6Value :
344 case DFF_Prop_adjust7Value :
345 case DFF_Prop_adjust8Value :
346 case DFF_Prop_adjust9Value :
347 case DFF_Prop_adjust10Value :
349 rParameter += "$";
350 rParameter += OUString::valueOf( (sal_Int32)( nPara - DFF_Prop_adjustValue ) );
351 rParameter += " ";
353 break;
354 case DFF_Prop_geoLeft :
356 rParameter += "left";
358 break;
359 case DFF_Prop_geoTop :
361 rParameter += "top";
363 break;
364 case DFF_Prop_geoRight :
366 rParameter += "right";
368 break;
369 case DFF_Prop_geoBottom :
371 rParameter += "bottom";
373 break;
377 else
379 rParameter += OUString::valueOf( (sal_Int32)( nPara ) );
383 void EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nPara, const bool bIsSpecialValue, bool bHorz )
385 sal_Int32 nValue = 0;
386 if ( bIsSpecialValue )
388 if ( ( nPara >= 0x100 ) && ( nPara <= 0x107 ) )
390 nValue = nPara & 0xff;
391 rParameter.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
393 else if ( ( nPara >= 3 ) && ( nPara <= 0x82 ) )
395 nValue = nPara - 3;
396 rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
398 else if ( nPara == 0 )
400 nValue = 0;
401 if ( bHorz )
402 rParameter.Type = EnhancedCustomShapeParameterType::LEFT;
403 else
404 rParameter.Type = EnhancedCustomShapeParameterType::TOP;
406 else if ( nPara == 1 )
408 nValue = 0;
409 if ( bHorz )
410 rParameter.Type = EnhancedCustomShapeParameterType::RIGHT;
411 else
412 rParameter.Type = EnhancedCustomShapeParameterType::BOTTOM;
414 else if ( nPara == 2 ) // means to be centered, but should not be
415 { // used in our implementation
416 nValue = 5600;
417 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
419 else
421 nValue = nPara;
422 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
425 else
427 nValue = nPara;
428 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
430 rParameter.Value <<= nValue;
433 bool EnhancedCustomShape2d::ConvertSequenceToEnhancedCustomShape2dHandle(
434 const com::sun::star::beans::PropertyValues& rHandleProperties,
435 EnhancedCustomShape2d::Handle& rDestinationHandle )
437 bool bRetValue = false;
438 sal_uInt32 i, nProperties = rHandleProperties.getLength();
439 if ( nProperties )
441 rDestinationHandle.nFlags = 0;
442 for ( i = 0; i < nProperties; i++ )
444 const com::sun::star::beans::PropertyValue& rPropVal = rHandleProperties[ i ];
446 const OUString sPosition ( "Position" );
447 const OUString sMirroredX ( "MirroredX" );
448 const OUString sMirroredY ( "MirroredY" );
449 const OUString sSwitched ( "Switched" );
450 const OUString sPolar ( "Polar" );
451 const OUString sRefX ( "RefX" );
452 const OUString sRefY ( "RefY" );
453 const OUString sRefAngle ( "RefAngle" );
454 const OUString sRefR ( "RefR" );
455 const OUString sRadiusRangeMinimum ( "RadiusRangeMinimum" );
456 const OUString sRadiusRangeMaximum ( "RadiusRangeMaximum" );
457 const OUString sRangeXMinimum ( "RangeXMinimum" );
458 const OUString sRangeXMaximum ( "RangeXMaximum" );
459 const OUString sRangeYMinimum ( "RangeYMinimum" );
460 const OUString sRangeYMaximum ( "RangeYMaximum" );
462 if ( rPropVal.Name == sPosition )
464 if ( rPropVal.Value >>= rDestinationHandle.aPosition )
465 bRetValue = true;
467 else if ( rPropVal.Name == sMirroredX )
469 sal_Bool bMirroredX = sal_Bool();
470 if ( rPropVal.Value >>= bMirroredX )
472 if ( bMirroredX )
473 rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_X;
476 else if ( rPropVal.Name == sMirroredY )
478 sal_Bool bMirroredY = sal_Bool();
479 if ( rPropVal.Value >>= bMirroredY )
481 if ( bMirroredY )
482 rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_Y;
485 else if ( rPropVal.Name == sSwitched )
487 sal_Bool bSwitched = sal_Bool();
488 if ( rPropVal.Value >>= bSwitched )
490 if ( bSwitched )
491 rDestinationHandle.nFlags |= HANDLE_FLAGS_SWITCHED;
494 else if ( rPropVal.Name == sPolar )
496 if ( rPropVal.Value >>= rDestinationHandle.aPolar )
497 rDestinationHandle.nFlags |= HANDLE_FLAGS_POLAR;
499 else if ( rPropVal.Name == sRefX )
501 if ( rPropVal.Value >>= rDestinationHandle.nRefX )
502 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFX;
504 else if ( rPropVal.Name == sRefY )
506 if ( rPropVal.Value >>= rDestinationHandle.nRefY )
507 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFY;
509 else if ( rPropVal.Name == sRefAngle )
511 if ( rPropVal.Value >>= rDestinationHandle.nRefAngle )
512 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFANGLE;
514 else if ( rPropVal.Name == sRefR )
516 if ( rPropVal.Value >>= rDestinationHandle.nRefR )
517 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFR;
519 else if ( rPropVal.Name == sRadiusRangeMinimum )
521 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMinimum )
522 rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MINIMUM;
524 else if ( rPropVal.Name == sRadiusRangeMaximum )
526 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMaximum )
527 rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM;
529 else if ( rPropVal.Name == sRangeXMinimum )
531 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMinimum )
532 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MINIMUM;
534 else if ( rPropVal.Name == sRangeXMaximum )
536 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMaximum )
537 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MAXIMUM;
539 else if ( rPropVal.Name == sRangeYMinimum )
541 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMinimum )
542 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MINIMUM;
544 else if ( rPropVal.Name == sRangeYMaximum )
546 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMaximum )
547 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MAXIMUM;
551 return bRetValue;
554 const sal_Int32* EnhancedCustomShape2d::ApplyShapeAttributes( const SdrCustomShapeGeometryItem& rGeometryItem )
556 const sal_Int32* pDefData = NULL;
557 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
558 if ( pDefCustomShape )
559 pDefData = pDefCustomShape->pDefData;
561 //////////////////////
562 // AdjustmentValues //
563 //////////////////////
564 const OUString sAdjustmentValues( "AdjustmentValues" );
565 const Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sAdjustmentValues );
566 if ( pAny )
567 *pAny >>= seqAdjustmentValues;
569 ///////////////
570 // Coordsize //
571 ///////////////
572 const OUString sViewBox( "ViewBox" );
573 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
574 com::sun::star::awt::Rectangle aViewBox;
575 if ( pViewBox && (*pViewBox >>= aViewBox ) )
577 nCoordLeft = aViewBox.X;
578 nCoordTop = aViewBox.Y;
579 nCoordWidthG = labs( aViewBox.Width );
580 nCoordHeightG = labs( aViewBox.Height);
582 const OUString sPath( "Path" );
584 //////////////////////
585 // Path/Coordinates //
586 //////////////////////
587 const OUString sCoordinates( "Coordinates" );
588 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
589 if ( pAny )
590 *pAny >>= seqCoordinates;
592 /////////////////////
593 // Path/GluePoints //
594 /////////////////////
595 const OUString sGluePoints( "GluePoints" );
596 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
597 if ( pAny )
598 *pAny >>= seqGluePoints;
600 ///////////////////
601 // Path/Segments //
602 ///////////////////
603 const OUString sSegments( "Segments" );
604 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSegments );
605 if ( pAny )
606 *pAny >>= seqSegments;
608 //////////////////////
609 // Path/SubViewSize //
610 //////////////////////
611 const OUString sSubViewSize( "SubViewSize" );
612 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSubViewSize );
613 if ( pAny )
614 *pAny >>= seqSubViewSize;
616 ///////////////////
617 // Path/StretchX //
618 ///////////////////
619 const OUString sStretchX( "StretchX" );
620 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchX );
621 if ( pAny )
623 sal_Int32 nStretchX = 0;
624 if ( *pAny >>= nStretchX )
625 nXRef = nStretchX;
628 ///////////////////
629 // Path/StretchY //
630 ///////////////////
631 const OUString sStretchY( "StretchY" );
632 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchY );
633 if ( pAny )
635 sal_Int32 nStretchY = 0;
636 if ( *pAny >>= nStretchY )
637 nYRef = nStretchY;
640 /////////////////////
641 // Path/TextFrames //
642 /////////////////////
643 const OUString sTextFrames( "TextFrames" );
644 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
645 if ( pAny )
646 *pAny >>= seqTextFrames;
648 ///////////////
649 // Equations //
650 ///////////////
651 const OUString sEquations( "Equations" );
652 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
653 if ( pAny )
654 *pAny >>= seqEquations;
656 /////////////
657 // Handles //
658 /////////////
659 const OUString sHandles( "Handles" );
660 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sHandles );
661 if ( pAny )
662 *pAny >>= seqHandles;
664 return pDefData;
667 EnhancedCustomShape2d::~EnhancedCustomShape2d()
671 void EnhancedCustomShape2d::SetPathSize( sal_Int32 nIndex )
673 sal_Int32 nWidth = 0;
674 sal_Int32 nHeight = 0;
676 if ( seqSubViewSize.getLength() && nIndex < seqSubViewSize.getLength() ) {
677 nWidth = seqSubViewSize[ nIndex ].Width;
678 nHeight = seqSubViewSize[ nIndex ].Height;
679 OSL_TRACE("set subpath %d size: %d x %d", nIndex, nWidth, nHeight);
682 if ( nWidth && nHeight ) {
683 nCoordWidth = nWidth;
684 nCoordHeight = nHeight;
685 } else {
686 nCoordWidth = nCoordWidthG;
687 nCoordHeight = nCoordHeightG;
690 fXScale = nCoordWidth == 0 ? 0.0 : (double)aLogicRect.GetWidth() / (double)nCoordWidth;
691 fYScale = nCoordHeight == 0 ? 0.0 : (double)aLogicRect.GetHeight() / (double)nCoordHeight;
692 if ( bOOXMLShape )
694 OSL_TRACE("ooxml shape, path width: %d height: %d", nCoordWidth, nCoordHeight);
695 if ( nCoordWidth == 0 )
696 fXScale = 1.0;
697 if ( nCoordHeight == 0 )
698 fYScale = 1.0;
700 if ( (sal_uInt32)nXRef != 0x80000000 && aLogicRect.GetHeight() )
702 fXRatio = (double)aLogicRect.GetWidth() / (double)aLogicRect.GetHeight();
703 if ( fXRatio > 1 )
704 fXScale /= fXRatio;
705 else
706 fXRatio = 1.0;
708 else
709 fXRatio = 1.0;
710 if ( (sal_uInt32)nYRef != 0x80000000 && aLogicRect.GetWidth() )
712 fYRatio = (double)aLogicRect.GetHeight() / (double)aLogicRect.GetWidth();
713 if ( fYRatio > 1 )
714 fYScale /= fYRatio;
715 else
716 fYRatio = 1.0;
718 else
719 fYRatio = 1.0;
722 EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
723 SfxItemSet ( pAObj->GetMergedItemSet() ),
724 pCustomShapeObj ( pAObj ),
725 eSpType ( mso_sptNil ),
726 nCoordLeft ( 0 ),
727 nCoordTop ( 0 ),
728 nCoordWidthG ( 21600 ),
729 nCoordHeightG ( 21600 ),
730 bOOXMLShape ( sal_False ),
731 nXRef ( 0x80000000 ),
732 nYRef ( 0x80000000 ),
733 nFlags ( 0 ),
734 nColorData ( 0 ),
735 bTextFlow ( sal_False ),
736 bFilled ( ((const XFillStyleItem&)pAObj->GetMergedItem( XATTR_FILLSTYLE )).GetValue() != XFILL_NONE ),
737 bStroked ( ((const XLineStyleItem&)pAObj->GetMergedItem( XATTR_LINESTYLE )).GetValue() != XLINE_NONE ),
738 bFlipH ( sal_False ),
739 bFlipV ( sal_False )
741 // bTextFlow needs to be set before clearing the TextDirection Item
743 ClearItem( SDRATTR_TEXTDIRECTION ); //SJ: vertical writing is not required, by removing this item no outliner is created
745 // #i105323# For 2D AtoShapes, the shadow attirbute does not need to be applied to any
746 // of the constucted helper SdrObjects. This would lead to problems since the shadow
747 // of one helper object would fall on one helper object behind it (e.g. with the
748 // eyes of the smiley shape). This is not wanted; instead a single shadow 'behind'
749 // the AutoShape visualisation is wanted. This is done with primitive functionailty
750 // now in SdrCustomShapePrimitive2D::create2DDecomposition, but only for 2D objects
751 // (see there and in EnhancedCustomShape3d::Create3DObject to read more).
752 // This exception may be removed later when AutoShapes will create primitives directly.
753 // So, currently remove the ShadowAttribute from the ItemSet to not apply it to any
754 // 2D helper shape.
755 ClearItem(SDRATTR_SHADOW);
757 Point aP( pCustomShapeObj->GetSnapRect().Center() );
758 Size aS( pCustomShapeObj->GetLogicRect().GetSize() );
759 aP.X() -= aS.Width() / 2;
760 aP.Y() -= aS.Height() / 2;
761 aLogicRect = Rectangle( aP, aS );
763 const OUString sType( "Type" );
764 const OUString sMirroredX( "MirroredX" );
765 const OUString sMirroredY( "MirroredY" );
767 OUString sShapeType;
768 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
769 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
770 if ( pAny ) {
771 *pAny >>= sShapeType;
772 bOOXMLShape = ( sShapeType.startsWith("ooxml-") );
773 OSL_TRACE("shape type: %s %d", OUStringToOString( sShapeType, RTL_TEXTENCODING_ASCII_US ).getStr(), bOOXMLShape);
775 eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
777 pAny = rGeometryItem.GetPropertyValueByName( sMirroredX );
778 if ( pAny )
779 *pAny >>= bFlipH;
780 pAny = rGeometryItem.GetPropertyValueByName( sMirroredY );
781 if ( pAny )
782 *pAny >>= bFlipV;
784 if ( pCustomShapeObj->ISA( SdrObjCustomShape ) ) // should always be a SdrObjCustomShape, but you don't know
785 nRotateAngle = (sal_Int32)(((SdrObjCustomShape*)pCustomShapeObj)->GetObjectRotation() * 100.0);
786 else
787 nRotateAngle = pCustomShapeObj->GetRotateAngle();
789 /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem );
790 SetPathSize();
792 switch( eSpType )
794 case mso_sptCan : nColorData = 0x20400000; break;
795 case mso_sptCube : nColorData = 0x302e0000; break;
796 case mso_sptActionButtonBlank : nColorData = 0x502ce400; break;
797 case mso_sptActionButtonHome : nColorData = 0x702ce4ce; break;
798 case mso_sptActionButtonHelp : nColorData = 0x602ce4c0; break;
799 case mso_sptActionButtonInformation : nColorData = 0x702ce4c5; break;
800 case mso_sptActionButtonBackPrevious : nColorData = 0x602ce4c0; break;
801 case mso_sptActionButtonForwardNext : nColorData = 0x602ce4c0; break;
802 case mso_sptActionButtonBeginning : nColorData = 0x602ce4c0; break;
803 case mso_sptActionButtonEnd : nColorData = 0x602ce4c0; break;
804 case mso_sptActionButtonReturn : nColorData = 0x602ce4c0; break;
805 case mso_sptActionButtonDocument : nColorData = 0x702ce4ec; break;
806 case mso_sptActionButtonSound : nColorData = 0x602ce4c0; break;
807 case mso_sptActionButtonMovie : nColorData = 0x602ce4c0; break;
808 case mso_sptBevel : nColorData = 0x502ce400; break;
809 case mso_sptFoldedCorner : nColorData = 0x20e00000; break;
810 case mso_sptSmileyFace : nColorData = 0x20e00000; break;
811 case mso_sptNil :
813 if( sShapeType.getLength() > 4 &&
814 sShapeType.match( "col-" ))
816 nColorData = sShapeType.copy( 4 ).toInt32( 16 );
819 break;
820 case mso_sptCurvedLeftArrow :
821 case mso_sptCurvedRightArrow :
822 case mso_sptCurvedUpArrow :
823 case mso_sptCurvedDownArrow : nColorData = 0x20d00000; break;
824 case mso_sptRibbon2 : nColorData = 0x30ee0000; break;
825 case mso_sptRibbon : nColorData = 0x30ee0000; break;
827 case mso_sptEllipseRibbon2 : nColorData = 0x30ee0000; break;
828 case mso_sptEllipseRibbon : nColorData = 0x30ee0000; break;
830 case mso_sptVerticalScroll : nColorData = 0x30ee0000; break;
831 case mso_sptHorizontalScroll : nColorData = 0x30ee0000; break;
832 default:
833 break;
836 sal_Int32 i, nLength = seqEquations.getLength();
838 if ( nLength )
840 vNodesSharedPtr.resize( nLength );
841 vEquationResults.resize( nLength );
842 for ( i = 0; i < seqEquations.getLength(); i++ )
844 vEquationResults[ i ].bReady = sal_False;
847 vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
849 catch ( EnhancedCustomShape::ParseError& )
851 OSL_TRACE("error: equation number: %d, parser failed ( %s )",
852 i, OUStringToOString( seqEquations[ i ], RTL_TEXTENCODING_ASCII_US ).getStr());
857 double EnhancedCustomShape2d::GetEnumFunc( const EnumFunc eFunc ) const
859 double fRet = 0.0;
860 switch( eFunc )
862 case ENUM_FUNC_PI : fRet = F_PI; break;
863 case ENUM_FUNC_LEFT : fRet = 0.0; break;
864 case ENUM_FUNC_TOP : fRet = 0.0; break;
865 case ENUM_FUNC_RIGHT : fRet = (double)nCoordWidth * fXRatio; break;
866 case ENUM_FUNC_BOTTOM : fRet = (double)nCoordHeight * fYRatio; break;
867 case ENUM_FUNC_XSTRETCH : fRet = nXRef; break;
868 case ENUM_FUNC_YSTRETCH : fRet = nYRef; break;
869 case ENUM_FUNC_HASSTROKE : fRet = bStroked ? 1.0 : 0.0; break;
870 case ENUM_FUNC_HASFILL : fRet = bFilled ? 1.0 : 0.0; break;
871 case ENUM_FUNC_WIDTH : fRet = nCoordWidth; break;
872 case ENUM_FUNC_HEIGHT : fRet = nCoordHeight; break;
873 case ENUM_FUNC_LOGWIDTH : fRet = aLogicRect.GetWidth(); break;
874 case ENUM_FUNC_LOGHEIGHT : fRet = aLogicRect.GetHeight(); break;
876 return fRet;
878 double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex ) const
880 double fNumber = 0.0;
881 if ( nIndex < seqAdjustmentValues.getLength() )
883 if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
884 seqAdjustmentValues[ nIndex ].Value >>= fNumber;
885 else
887 sal_Int32 nNumber = 0;
888 seqAdjustmentValues[ nIndex ].Value >>= nNumber;
889 fNumber = (double)nNumber;
892 return fNumber;
894 double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
896 double fNumber = 0.0;
897 #if OSL_DEBUG_LEVEL > 1
898 static sal_uInt32 nLevel = 0;
899 #endif
900 if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
902 if ( vNodesSharedPtr[ nIndex ].get() ) {
903 #if OSL_DEBUG_LEVEL > 1
904 nLevel ++;
905 #endif
908 if ( vEquationResults[ nIndex ].bReady )
909 fNumber = vEquationResults[ nIndex ].fValue;
910 else {
911 // cast to non const, so that we can optimize by caching
912 // equation results, without changing all the const in the stack
913 struct EquationResult &aResult = ((EnhancedCustomShape2d*)this)->vEquationResults[ nIndex ];
915 fNumber = aResult.fValue = (*vNodesSharedPtr[ nIndex ])();
916 aResult.bReady = true;
918 if ( !rtl::math::isFinite( fNumber ) )
919 fNumber = 0.0;
920 #if OSL_DEBUG_LEVEL > 1
921 OSL_TRACE("equation %d (level: %d): %s --> %f (angle: %f)", nIndex,
922 nLevel, OUStringToOString( seqEquations[ nIndex ],
923 RTL_TEXTENCODING_ASCII_US ).getStr(), fNumber, 180.0*fNumber/10800000.0);
924 #endif
927 catch ( ... )
929 OSL_TRACE("error: EnhancedCustomShape2d::GetEquationValueAsDouble failed");
931 #if OSL_DEBUG_LEVEL > 1
932 nLevel --;
933 #endif
935 OSL_TRACE(" ?%d --> %f (angle: %f)", nIndex,
936 fNumber, 180.0*fNumber/10800000.0);
939 return fNumber;
941 sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
943 sal_Int32 nNumber = nDefault;
944 if ( nIndex < seqAdjustmentValues.getLength() )
946 if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
948 double fNumber = 0;
949 seqAdjustmentValues[ nIndex ].Value >>= fNumber;
950 nNumber = (sal_Int32)fNumber;
952 else
953 seqAdjustmentValues[ nIndex ].Value >>= nNumber;
955 return nNumber;
957 bool EnhancedCustomShape2d::SetAdjustValueAsDouble( const double& rValue, const sal_Int32 nIndex )
959 bool bRetValue = false;
960 if ( nIndex < seqAdjustmentValues.getLength() )
962 // updating our local adjustment sequence
963 seqAdjustmentValues[ nIndex ].Value <<= rValue;
964 seqAdjustmentValues[ nIndex ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
965 bRetValue = true;
967 return bRetValue;
970 Point EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair& rPair,
971 const bool bScale, const bool bReplaceGeoSize ) const
973 Point aRetValue;
974 bool bExchange = ( nFlags & DFF_CUSTOMSHAPE_EXCH ) != 0; // x <-> y
975 sal_uInt32 nPass = 0;
978 sal_uInt32 nIndex = nPass;
980 if ( bExchange )
981 nIndex ^= 1;
983 double fVal;
984 const EnhancedCustomShapeParameter& rParameter = nIndex ? rPair.Second : rPair.First;
985 if ( nPass ) // height
987 GetParameter( fVal, rParameter, false, bReplaceGeoSize );
988 fVal -= nCoordTop;
989 if ( bScale )
991 fVal *= fYScale;
993 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_V )
994 fVal = aLogicRect.GetHeight() - fVal;
996 aRetValue.Y() = (sal_Int32)fVal;
998 else // width
1000 GetParameter( fVal, rParameter, bReplaceGeoSize, false );
1001 fVal -= nCoordLeft;
1002 if ( bScale )
1004 fVal *= fXScale;
1006 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_H )
1007 fVal = aLogicRect.GetWidth() - fVal;
1009 aRetValue.X() = (sal_Int32)fVal;
1012 while ( ++nPass < 2 );
1013 return aRetValue;
1016 bool EnhancedCustomShape2d::GetParameter( double& rRetValue, const EnhancedCustomShapeParameter& rParameter,
1017 const bool bReplaceGeoWidth, const bool bReplaceGeoHeight ) const
1019 rRetValue = 0.0;
1020 bool bRetValue = false;
1021 switch ( rParameter.Type )
1023 case EnhancedCustomShapeParameterType::ADJUSTMENT :
1025 sal_Int32 nAdjustmentIndex = 0;
1026 if ( rParameter.Value >>= nAdjustmentIndex )
1028 rRetValue = GetAdjustValueAsDouble( nAdjustmentIndex );
1029 bRetValue = true;
1032 break;
1033 case EnhancedCustomShapeParameterType::EQUATION :
1035 sal_Int32 nEquationIndex = 0;
1036 if ( rParameter.Value >>= nEquationIndex )
1038 rRetValue = GetEquationValueAsDouble( nEquationIndex );
1039 bRetValue = true;
1042 break;
1043 case EnhancedCustomShapeParameterType::NORMAL :
1045 if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE )
1047 double fValue(0.0);
1048 if ( rParameter.Value >>= fValue )
1050 rRetValue = fValue;
1051 bRetValue = true;
1054 else
1056 sal_Int32 nValue = 0;
1057 if ( rParameter.Value >>= nValue )
1059 rRetValue = nValue;
1060 bRetValue = true;
1061 if ( bReplaceGeoWidth && ( nValue == nCoordWidth ) )
1062 rRetValue *= fXRatio;
1063 else if ( bReplaceGeoHeight && ( nValue == nCoordHeight ) )
1064 rRetValue *= fYRatio;
1068 break;
1069 case EnhancedCustomShapeParameterType::LEFT :
1071 rRetValue = 0.0;
1072 bRetValue = true;
1074 break;
1075 case EnhancedCustomShapeParameterType::TOP :
1077 rRetValue = 0.0;
1078 bRetValue = true;
1080 break;
1081 case EnhancedCustomShapeParameterType::RIGHT :
1083 rRetValue = nCoordWidth;
1084 bRetValue = true;
1086 break;
1087 case EnhancedCustomShapeParameterType::BOTTOM :
1089 rRetValue = nCoordHeight;
1090 bRetValue = true;
1092 break;
1094 return bRetValue;
1097 // nLumDat 28-31 = number of luminance entries in nLumDat
1098 // nLumDat 27-24 = nLumDatEntry 0
1099 // nLumDat 23-20 = nLumDatEntry 1 ...
1100 // each 4bit entry is to be interpreted as a 10 percent signed luminance changing
1101 sal_Int32 EnhancedCustomShape2d::GetLuminanceChange( sal_uInt32 nIndex ) const
1103 const sal_uInt32 nCount = nColorData >> 28;
1104 if ( !nCount )
1105 return 0;
1107 if ( nIndex >= nCount )
1108 nIndex = nCount - 1;
1110 const sal_Int32 nLumDat = nColorData << ( ( 1 + nIndex ) << 2 );
1111 return ( nLumDat >> 28 ) * 10;
1114 Color EnhancedCustomShape2d::GetColorData( const Color& rFillColor, sal_uInt32 nIndex, double dBrightness ) const
1116 const sal_Int32 nLuminance = GetLuminanceChange(nIndex);
1117 if( !nLuminance && dBrightness == 1.0 )
1118 return rFillColor;
1120 basegfx::BColor aHSVColor=
1121 basegfx::tools::rgb2hsv(
1122 basegfx::BColor(rFillColor.GetRed()/255.0,
1123 rFillColor.GetGreen()/255.0,
1124 rFillColor.GetBlue()/255.0));
1125 if (nLuminance ) {
1126 if( nLuminance > 0 )
1128 aHSVColor.setGreen(
1129 aHSVColor.getGreen() * (1.0-nLuminance/100.0));
1130 aHSVColor.setBlue(
1131 nLuminance/100.0 +
1132 (1.0-nLuminance/100.0)*aHSVColor.getBlue());
1134 else if( nLuminance < 0 )
1136 aHSVColor.setBlue(
1137 (1.0+nLuminance/100.0)*aHSVColor.getBlue());
1141 aHSVColor = basegfx::tools::hsv2rgb(aHSVColor);
1142 return Color( (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getRed(),0.0,1.0) * 255.0 + 0.5 ),
1143 (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getGreen(),0.0,1.0) * 255.0 + 0.5 ),
1144 (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getBlue(),0.0,1.0) * 255.0 + 0.5 ) );
1147 Rectangle EnhancedCustomShape2d::GetTextRect() const
1149 sal_Int32 nIndex, nSize = seqTextFrames.getLength();
1150 if ( !nSize )
1151 return aLogicRect;
1152 nIndex = 0;
1153 if ( bTextFlow && ( nSize > 1 ) )
1154 nIndex++;
1155 Point aTopLeft( GetPoint( seqTextFrames[ nIndex ].TopLeft, !bOOXMLShape, true ) );
1156 Point aBottomRight( GetPoint( seqTextFrames[ nIndex ].BottomRight, !bOOXMLShape, true ) );
1157 if ( bFlipH )
1159 aTopLeft.X() = aLogicRect.GetWidth() - aTopLeft.X();
1160 aBottomRight.X() = aLogicRect.GetWidth() - aBottomRight.X();
1162 if ( bFlipV )
1164 aTopLeft.Y() = aLogicRect.GetHeight() - aTopLeft.Y();
1165 aBottomRight.Y() = aLogicRect.GetHeight() - aBottomRight.Y();
1167 Rectangle aRect( aTopLeft, aBottomRight );
1168 OSL_TRACE("EnhancedCustomShape2d::GetTextRect: %d x %d", aRect.GetWidth(), aRect.GetHeight());
1169 if( aRect.GetWidth() <= 1 || aRect.GetHeight() <= 1 )
1170 return aLogicRect;
1171 aRect.Move( aLogicRect.Left(), aLogicRect.Top() );
1172 aRect.Justify();
1173 return aRect;
1176 sal_uInt32 EnhancedCustomShape2d::GetHdlCount() const
1178 return seqHandles.getLength();
1181 bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex, Point& rReturnPosition ) const
1183 bool bRetValue = false;
1184 if ( nIndex < GetHdlCount() )
1186 Handle aHandle;
1187 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1189 if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1191 Point aReferencePoint( GetPoint( aHandle.aPolar, true, false ) );
1193 double fAngle;
1194 double fRadius;
1195 GetParameter( fRadius, aHandle.aPosition.First, false, false );
1196 GetParameter( fAngle, aHandle.aPosition.Second, false, false );
1198 double a = ( 360.0 - fAngle ) * F_PI180;
1199 double dx = fRadius * fXScale;
1200 double fX = dx * cos( a );
1201 double fY =-dx * sin( a );
1202 rReturnPosition =
1203 Point(
1204 Round( fX + aReferencePoint.X() ),
1205 basegfx::fTools::equalZero(fXScale) ? aReferencePoint.Y() :
1206 Round( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) );
1208 else
1210 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1212 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1214 com::sun::star::drawing::EnhancedCustomShapeParameter aFirst = aHandle.aPosition.First;
1215 com::sun::star::drawing::EnhancedCustomShapeParameter aSecond = aHandle.aPosition.Second;
1216 aHandle.aPosition.First = aSecond;
1217 aHandle.aPosition.Second = aFirst;
1220 rReturnPosition = GetPoint( aHandle.aPosition, true, false );
1222 const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1223 if ( aGeoStat.nShearWink )
1225 double nTan = aGeoStat.nTan;
1226 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1227 nTan = -nTan;
1228 ShearPoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1230 if ( nRotateAngle )
1232 double a = nRotateAngle * F_PI18000;
1233 RotatePoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1235 if ( bFlipH )
1236 rReturnPosition.X() = aLogicRect.GetWidth() - rReturnPosition.X();
1237 if ( bFlipV )
1238 rReturnPosition.Y() = aLogicRect.GetHeight() - rReturnPosition.Y();
1239 rReturnPosition.Move( aLogicRect.Left(), aLogicRect.Top() );
1240 bRetValue = true;
1243 return bRetValue;
1246 bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex, const com::sun::star::awt::Point& rPosition )
1248 bool bRetValue = false;
1249 if ( nIndex < GetHdlCount() )
1251 Handle aHandle;
1252 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1254 Point aP( rPosition.X, rPosition.Y );
1255 // apply the negative object rotation to the controller position
1257 aP.Move( -aLogicRect.Left(), -aLogicRect.Top() );
1258 if ( bFlipH )
1259 aP.X() = aLogicRect.GetWidth() - aP.X();
1260 if ( bFlipV )
1261 aP.Y() = aLogicRect.GetHeight() - aP.Y();
1262 if ( nRotateAngle )
1264 double a = -nRotateAngle * F_PI18000;
1265 RotatePoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1267 const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1268 if ( aGeoStat.nShearWink )
1270 double nTan = -aGeoStat.nTan;
1271 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1272 nTan = -nTan;
1273 ShearPoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1276 double fPos1 = aP.X(); //( bFlipH ) ? aLogicRect.GetWidth() - aP.X() : aP.X();
1277 double fPos2 = aP.Y(); //( bFlipV ) ? aLogicRect.GetHeight() -aP.Y() : aP.Y();
1278 fPos1 /= fXScale;
1279 fPos2 /= fYScale;
1281 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1283 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1285 double fX = fPos1;
1286 double fY = fPos2;
1287 fPos1 = fY;
1288 fPos2 = fX;
1292 sal_Int32 nFirstAdjustmentValue = -1, nSecondAdjustmentValue = -1;
1294 if ( aHandle.aPosition.First.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1295 aHandle.aPosition.First.Value >>= nFirstAdjustmentValue;
1296 if ( aHandle.aPosition.Second.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1297 aHandle.aPosition.Second.Value>>= nSecondAdjustmentValue;
1299 if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1301 double fXRef, fYRef, fAngle;
1302 GetParameter( fXRef, aHandle.aPolar.First, false, false );
1303 GetParameter( fYRef, aHandle.aPolar.Second, false, false );
1304 const double fDX = fPos1 - fXRef;
1305 fAngle = -( atan2( -fPos2 + fYRef, ( ( fDX == 0.0L ) ? 0.000000001 : fDX ) ) / F_PI180 );
1306 double fX = ( fPos1 - fXRef );
1307 double fY = ( fPos2 - fYRef );
1308 double fRadius = sqrt( fX * fX + fY * fY );
1309 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MINIMUM )
1311 double fMin;
1312 GetParameter( fMin, aHandle.aRadiusRangeMinimum, false, false );
1313 if ( fRadius < fMin )
1314 fRadius = fMin;
1316 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM )
1318 double fMax;
1319 GetParameter( fMax, aHandle.aRadiusRangeMaximum, false, false );
1320 if ( fRadius > fMax )
1321 fRadius = fMax;
1323 if ( nFirstAdjustmentValue >= 0 )
1324 SetAdjustValueAsDouble( fRadius, nFirstAdjustmentValue );
1325 if ( nSecondAdjustmentValue >= 0 )
1326 SetAdjustValueAsDouble( fAngle, nSecondAdjustmentValue );
1328 else
1330 if ( aHandle.nFlags & HANDLE_FLAGS_REFX )
1332 nFirstAdjustmentValue = aHandle.nRefX;
1333 fPos1 *= 100000.0;
1334 fPos1 /= nCoordWidth;
1336 if ( aHandle.nFlags & HANDLE_FLAGS_REFY )
1338 nSecondAdjustmentValue = aHandle.nRefY;
1339 fPos2 *= 100000.0;
1340 fPos2 /= nCoordHeight;
1342 if ( nFirstAdjustmentValue >= 0 )
1344 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MINIMUM ) // check if horizontal handle needs to be within a range
1346 double fXMin;
1347 GetParameter( fXMin, aHandle.aXRangeMinimum, false, false );
1348 if ( fPos1 < fXMin )
1349 fPos1 = fXMin;
1351 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MAXIMUM ) // check if horizontal handle needs to be within a range
1353 double fXMax;
1354 GetParameter( fXMax, aHandle.aXRangeMaximum, false, false );
1355 if ( fPos1 > fXMax )
1356 fPos1 = fXMax;
1358 SetAdjustValueAsDouble( fPos1, nFirstAdjustmentValue );
1360 if ( nSecondAdjustmentValue >= 0 )
1362 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MINIMUM ) // check if vertical handle needs to be within a range
1364 double fYMin;
1365 GetParameter( fYMin, aHandle.aYRangeMinimum, false, false );
1366 if ( fPos2 < fYMin )
1367 fPos2 = fYMin;
1369 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MAXIMUM ) // check if vertical handle needs to be within a range
1371 double fYMax;
1372 GetParameter( fYMax, aHandle.aYRangeMaximum, false, false );
1373 if ( fPos2 > fYMax )
1374 fPos2 = fYMax;
1376 SetAdjustValueAsDouble( fPos2, nSecondAdjustmentValue );
1379 // and writing them back into the GeometryItem
1380 SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)
1381 (const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1382 const OUString sAdjustmentValues( "AdjustmentValues" );
1383 com::sun::star::beans::PropertyValue aPropVal;
1384 aPropVal.Name = sAdjustmentValues;
1385 aPropVal.Value <<= seqAdjustmentValues;
1386 aGeometryItem.SetPropertyValue( aPropVal );
1387 pCustomShapeObj->SetMergedItem( aGeometryItem );
1388 bRetValue = true;
1391 return bRetValue;
1394 void EnhancedCustomShape2d::SwapStartAndEndArrow( SdrObject* pObj ) //#108274
1396 XLineStartItem aLineStart;
1397 aLineStart.SetLineStartValue(((XLineStartItem&)pObj->GetMergedItem( XATTR_LINEEND )).GetLineStartValue());
1398 XLineStartWidthItem aLineStartWidth(((XLineStartWidthItem&)pObj->GetMergedItem( XATTR_LINEENDWIDTH )).GetValue());
1399 XLineStartCenterItem aLineStartCenter(((XLineStartCenterItem&)pObj->GetMergedItem( XATTR_LINEENDCENTER )).GetValue());
1401 XLineEndItem aLineEnd;
1402 aLineEnd.SetLineEndValue(((XLineEndItem&)pObj->GetMergedItem( XATTR_LINESTART )).GetLineEndValue());
1403 XLineEndWidthItem aLineEndWidth(((XLineEndWidthItem&)pObj->GetMergedItem( XATTR_LINESTARTWIDTH )).GetValue());
1404 XLineEndCenterItem aLineEndCenter(((XLineEndCenterItem&)pObj->GetMergedItem( XATTR_LINESTARTCENTER )).GetValue());
1406 pObj->SetMergedItem( aLineStart );
1407 pObj->SetMergedItem( aLineStartWidth );
1408 pObj->SetMergedItem( aLineStartCenter );
1409 pObj->SetMergedItem( aLineEnd );
1410 pObj->SetMergedItem( aLineEndWidth );
1411 pObj->SetMergedItem( aLineEndCenter );
1414 static basegfx::B2DPolygon CreateArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, const sal_Bool bClockwise, sal_Bool bFullCircle = sal_False )
1416 Rectangle aRect( rRect );
1417 Point aStart( rStart );
1418 Point aEnd( rEnd );
1420 sal_Int32 bSwapStartEndAngle = 0;
1422 if ( aRect.Left() > aRect.Right() )
1423 bSwapStartEndAngle ^= 0x01;
1424 if ( aRect.Top() > aRect.Bottom() )
1425 bSwapStartEndAngle ^= 0x11;
1426 if ( bSwapStartEndAngle )
1428 aRect.Justify();
1429 if ( bSwapStartEndAngle & 1 )
1431 Point aTmp( aStart );
1432 aStart = aEnd;
1433 aEnd = aTmp;
1437 Polygon aTempPoly( aRect, aStart, aEnd, POLY_ARC, bFullCircle );
1438 basegfx::B2DPolygon aRetval;
1440 if ( bClockwise )
1442 for ( sal_uInt16 j = aTempPoly.GetSize(); j--; )
1444 aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1447 else
1449 for ( sal_uInt16 j = 0; j < aTempPoly.GetSize(); j++ )
1451 aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1455 return aRetval;
1458 void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegmentInd, std::vector< SdrPathObj* >& rObjectList,
1459 const sal_Bool bLineGeometryNeededOnly,
1460 const sal_Bool bSortFilledObjectsToBack,
1461 sal_Int32 nIndex )
1463 bool bNoFill = false;
1464 bool bNoStroke = false;
1465 double dBrightness = 1.0;
1467 basegfx::B2DPolyPolygon aNewB2DPolyPolygon;
1468 basegfx::B2DPolygon aNewB2DPolygon;
1470 SetPathSize( nIndex );
1472 sal_Int32 nCoordSize = seqCoordinates.getLength();
1473 sal_Int32 nSegInfoSize = seqSegments.getLength();
1474 if ( !nSegInfoSize )
1476 const EnhancedCustomShapeParameterPair* pTmp = seqCoordinates.getArray();
1478 for ( sal_Int32 nPtNum(0L); nPtNum < nCoordSize; nPtNum++ )
1480 const Point aTempPoint(GetPoint( *pTmp++, true, true ));
1481 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1484 aNewB2DPolygon.setClosed(true);
1486 else
1488 for ( ;rSegmentInd < nSegInfoSize; )
1490 sal_Int16 nCommand = seqSegments[ rSegmentInd ].Command;
1491 sal_Int16 nPntCount= seqSegments[ rSegmentInd++ ].Count;
1493 switch ( nCommand )
1495 case NOFILL :
1496 bNoFill = true;
1497 break;
1498 case NOSTROKE :
1499 bNoStroke = true;
1500 break;
1501 case DARKEN :
1502 dBrightness = 0.66666666;
1503 break;
1504 case DARKENLESS :
1505 dBrightness = 0.83333333;
1506 break;
1507 case LIGHTEN :
1508 dBrightness = 1.16666666;
1509 break;
1510 case LIGHTENLESS :
1511 dBrightness = 1.33333333;
1512 break;
1513 case MOVETO :
1515 if(aNewB2DPolygon.count() > 1L)
1517 // #i76201# Add conversion to closed polygon when first and last points are equal
1518 basegfx::tools::checkClosed(aNewB2DPolygon);
1519 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1522 aNewB2DPolygon.clear();
1524 if ( rSrcPt < nCoordSize )
1526 const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1527 OSL_TRACE("moveTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
1528 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1531 break;
1532 case ENDSUBPATH :
1533 break;
1534 case CLOSESUBPATH :
1536 if(aNewB2DPolygon.count())
1538 if(aNewB2DPolygon.count() > 1L)
1540 aNewB2DPolygon.setClosed(true);
1541 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1544 aNewB2DPolygon.clear();
1547 break;
1548 case CURVETO :
1550 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1552 const Point aControlA(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1553 const Point aControlB(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1554 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1556 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding control point (!)");
1557 aNewB2DPolygon.appendBezierSegment(
1558 basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1559 basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1560 basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1563 break;
1565 case ANGLEELLIPSE :
1567 if ( nPntCount )
1569 if(aNewB2DPolygon.count() > 1L)
1571 // #i76201# Add conversion to closed polygon when first and last points are equal
1572 basegfx::tools::checkClosed(aNewB2DPolygon);
1573 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1575 aNewB2DPolygon.clear();
1578 case ANGLEELLIPSETO :
1580 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1582 // create a circle
1583 Point _aCenter;
1584 double fWidth, fHeight;
1585 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( mso_sptEllipse );
1586 bool bIsDefaultViewBox = false;
1587 bool bIsDefaultPath = false;
1588 bool bIsMSEllipse = false;
1590 if( ( nCoordWidth == pDefCustomShape->nCoordWidth )
1591 && ( nCoordHeight == pDefCustomShape->nCoordHeight ) )
1592 bIsDefaultViewBox = true;
1593 sal_Int32 j, nCount = pDefCustomShape->nVertices;//==3
1594 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1596 seqCoordinates1.realloc( nCount );
1597 for ( j = 0; j < nCount; j++ )
1599 seqCoordinates1[j] = seqCoordinates[ rSrcPt + j];
1602 seqCoordinates2.realloc( nCount );
1603 for ( j = 0; j < nCount; j++ )
1605 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].First, pDefCustomShape->pVertices[ j ].nValA );
1606 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].Second, pDefCustomShape->pVertices[ j ].nValB );
1608 if(seqCoordinates1 == seqCoordinates2)
1609 bIsDefaultPath = true;
1611 const rtl::OUString sType( "Type" );
1612 rtl::OUString sShpType;
1613 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
1614 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
1615 if ( pAny )
1616 *pAny >>= sShpType;
1617 if( sShpType.getLength() > 3 &&
1618 sShpType.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "mso" ))){
1619 bIsMSEllipse = true;
1621 if( (! bIsDefaultPath && ! bIsDefaultViewBox) || (bIsDefaultViewBox && bIsMSEllipse) /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1623 _aCenter = GetPoint( seqCoordinates[ rSrcPt ], true, true );
1624 GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, true, false );
1625 GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, false, true );
1626 fWidth /= 2;
1627 fHeight /= 2;
1628 }else if( bIsDefaultPath && !bIsDefaultViewBox /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1630 _aCenter.X() = nCoordWidth/2 * fXScale;
1631 _aCenter.Y() = nCoordHeight/2 * fYScale;
1632 fWidth = nCoordWidth/2;
1633 fHeight = nCoordHeight/2;
1635 const rtl::OUString sViewBox( "ViewBox" );
1636 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
1637 com::sun::star::awt::Rectangle aViewBox;
1638 if ( pViewBox && (*pViewBox >>= aViewBox ) )
1640 aViewBox.Width = pDefCustomShape->nCoordWidth;
1641 aViewBox.Height = pDefCustomShape->nCoordHeight;
1643 com::sun::star::beans::PropertyValue aPropVal;
1644 aPropVal.Name = sViewBox;
1645 aPropVal.Value <<= aViewBox;
1646 rGeometryItem.SetPropertyValue( aPropVal );
1647 pCustomShapeObj->SetMergedItem( rGeometryItem );
1648 }else{
1649 _aCenter = GetPoint( seqCoordinates[ rSrcPt ], true, true );
1650 GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, true, false);
1651 GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, false, true );
1654 fWidth *= fXScale;
1655 fHeight*= fYScale;
1656 Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1657 Size aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1658 Rectangle aRect( aP, aS );
1659 if ( aRect.GetWidth() && aRect.GetHeight() )
1661 double fStartAngle, fEndAngle;
1662 GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First, false, false );
1663 GetParameter( fEndAngle , seqCoordinates[ rSrcPt + 2 ].Second, false, false );
1665 if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1667 if ( (sal_Int32)fStartAngle & 0x7fff0000 ) // SJ: if the angle was imported from our escher import, then the
1668 fStartAngle /= 65536.0; // value is shifted by 16. TODO: already change the fixed float to a
1669 if ( (sal_Int32)fEndAngle & 0x7fff0000 ) // double in the import filter
1671 fEndAngle /= 65536.0;
1672 fEndAngle = fEndAngle + fStartAngle;
1673 if ( fEndAngle < 0 )
1674 { // in the binary filter the endangle is the amount
1675 double fTemp = fStartAngle;
1676 fStartAngle = fEndAngle;
1677 fEndAngle = fTemp;
1680 double fCenterX = aRect.Center().X();
1681 double fCenterY = aRect.Center().Y();
1682 double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1683 double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1684 double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1685 double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1686 aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), sal_False));
1688 else
1689 { /* SJ: TODO: this block should be replaced sometimes, because the current point
1690 is not set correct, it also does not use the correct moveto
1691 point if ANGLEELLIPSETO was used, but the method CreateArc
1692 is at the moment not able to draw full circles (if startangle is 0
1693 and endangle 360 nothing is painted :-( */
1694 sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1695 sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1696 Point aCenter( aRect.Center() );
1698 // append start point
1699 aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1701 // append four bezier segments
1702 aNewB2DPolygon.appendBezierSegment(
1703 basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1704 basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1705 basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1707 aNewB2DPolygon.appendBezierSegment(
1708 basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1709 basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1710 basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1712 aNewB2DPolygon.appendBezierSegment(
1713 basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1714 basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1715 basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1717 aNewB2DPolygon.appendBezierSegment(
1718 basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1719 basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1720 basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1722 // close, rescue last controlpoint, remove double last point
1723 basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1726 rSrcPt += 3;
1729 break;
1731 case QUADRATICCURVETO :
1733 for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
1735 if ( rSrcPt )
1737 const Point aPreviousEndPoint(GetPoint( seqCoordinates[ rSrcPt - 1 ], true, true));
1738 const Point aControlQ(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1739 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1740 const Point aControlA((aPreviousEndPoint + (aControlQ * 2.0)) / 3.0);
1741 const Point aControlB(((aControlQ * 2.0) + aEnd) / 3.0);
1743 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1744 aNewB2DPolygon.appendBezierSegment(
1745 basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1746 basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1747 basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1749 else // no previous point , do a moveto
1751 rSrcPt++; // skip control point
1752 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1754 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1755 aNewB2DPolygon.append(basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1759 break;
1761 case LINETO :
1763 for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1765 const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1766 OSL_TRACE("lineTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
1767 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1770 break;
1772 case ARC :
1773 case CLOCKWISEARC :
1775 if(aNewB2DPolygon.count() > 1L)
1777 // #i76201# Add conversion to closed polygon when first and last points are equal
1778 basegfx::tools::checkClosed(aNewB2DPolygon);
1779 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1782 aNewB2DPolygon.clear();
1784 case ARCTO :
1785 case CLOCKWISEARCTO :
1787 sal_Bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1788 sal_uInt32 nXor = bClockwise ? 3 : 2;
1789 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1791 Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], true, true ), GetPoint( seqCoordinates[ rSrcPt + 1 ], true, true ) );
1792 if ( aRect.GetWidth() && aRect.GetHeight() )
1794 Point aCenter( aRect.Center() );
1795 Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], true, true ) );
1796 Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], true, true ) );
1797 aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) ) + aCenter.X();
1798 aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1799 aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) ) + aCenter.X();
1800 aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1801 aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1803 rSrcPt += 4;
1806 break;
1808 case ARCANGLETO :
1810 double fWR, fHR, fStartAngle, fSwingAngle;
1812 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
1814 GetParameter ( fWR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].First, true, false );
1815 GetParameter ( fHR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].Second, false, true );
1817 GetParameter ( fStartAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1) ].First, false, false );
1818 GetParameter ( fSwingAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1 ) ].Second, false, false );
1820 fWR *= fXScale;
1821 fHR *= fYScale;
1823 fStartAngle *= F_PI180;
1824 fSwingAngle *= F_PI180;
1826 OSL_TRACE("ARCANGLETO scale: %f x %f angles: %f, %f", fWR, fHR, fStartAngle, fSwingAngle);
1828 sal_Bool bClockwise = fSwingAngle >= 0.0;
1830 if (aNewB2DPolygon.count() > 0)
1832 basegfx::B2DPoint aStartPointB2D( aNewB2DPolygon.getB2DPoint(aNewB2DPolygon.count() - 1 ) );
1833 Point aStartPoint( aStartPointB2D.getX(), aStartPointB2D.getY() );
1835 double fT = atan2((fWR*sin(fStartAngle)), (fHR*cos(fStartAngle)));
1836 double fTE = atan2((fWR*sin(fStartAngle + fSwingAngle)), fHR*cos(fStartAngle + fSwingAngle));
1838 OSL_TRACE("ARCANGLETO angles: %f, %f --> parameters: %f, %f", fStartAngle, fSwingAngle, fT, fTE );
1840 Rectangle aRect ( Point ( aStartPoint.getX() - fWR*cos(fT) - fWR, aStartPoint.getY() - fHR*sin(fT) - fHR ),
1841 Point ( aStartPoint.getX() - fWR*cos(fT) + fWR, aStartPoint.getY() - fHR*sin(fT) + fHR) );
1843 Point aEndPoint ( aStartPoint.getX() - fWR*(cos(fT) - cos(fTE)), aStartPoint.getY() - fHR*(sin(fT) - sin(fTE)) );
1845 OSL_TRACE("ARCANGLETO rect: %d, %d x %d, %d start: %d, %d end: %d, %d clockwise: %d",
1846 aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom(),
1847 aStartPoint.X(), aStartPoint.Y(), aEndPoint.X(), aEndPoint.Y(), bClockwise);
1848 aNewB2DPolygon.append(CreateArc( aRect, bClockwise ? aEndPoint : aStartPoint, bClockwise ? aStartPoint : aEndPoint, bClockwise, aStartPoint == aEndPoint && fSwingAngle > F_PI));
1851 rSrcPt += 2;
1854 break;
1856 case ELLIPTICALQUADRANTX :
1857 case ELLIPTICALQUADRANTY :
1859 bool bFirstDirection(true);
1860 basegfx::B2DPoint aControlPointA;
1861 basegfx::B2DPoint aControlPointB;
1863 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1865 sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1866 Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], true, true ) );
1868 if ( rSrcPt ) // we need a previous point
1870 Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], true, true ) );
1871 sal_Int32 nX, nY;
1872 nX = aCurrent.X() - aPrev.X();
1873 nY = aCurrent.Y() - aPrev.Y();
1874 if ( ( nY ^ nX ) & 0x80000000 )
1876 if ( !i )
1877 bFirstDirection = true;
1878 else if ( !bFirstDirection )
1879 nModT ^= 1;
1881 else
1883 if ( !i )
1884 bFirstDirection = false;
1885 else if ( bFirstDirection )
1886 nModT ^= 1;
1888 if ( nModT ) // get the right corner
1890 nX = aCurrent.X();
1891 nY = aPrev.Y();
1893 else
1895 nX = aPrev.X();
1896 nY = aCurrent.Y();
1898 sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1899 sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1900 Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1902 aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1904 nXVec = ( nX - aCurrent.X() ) >> 1;
1905 nYVec = ( nY - aCurrent.Y() ) >> 1;
1906 Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1908 aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1910 aNewB2DPolygon.appendBezierSegment(
1911 aControlPointA,
1912 aControlPointB,
1913 basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1915 else
1917 aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1920 rSrcPt++;
1923 break;
1925 #ifdef DBG_CUSTOMSHAPE
1926 case UNKNOWN :
1927 default :
1929 OStringBuffer aString("CustomShapes::unknown PolyFlagValue :");
1930 aString.append(static_cast<sal_Int32>(nCommand));
1931 OSL_FAIL(aString.getStr());
1933 break;
1934 #endif
1936 if ( nCommand == ENDSUBPATH )
1937 break;
1940 if ( rSegmentInd == nSegInfoSize )
1941 rSegmentInd++;
1943 if(aNewB2DPolygon.count() > 1L)
1945 // #i76201# Add conversion to closed polygon when first and last points are equal
1946 basegfx::tools::checkClosed(aNewB2DPolygon);
1947 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1950 if(aNewB2DPolyPolygon.count())
1952 if( !bLineGeometryNeededOnly )
1954 // hack aNewB2DPolyPolygon to fill logic rect - this is
1955 // needed to produce gradient fills that look like mso
1956 aNewB2DPolygon.clear();
1957 aNewB2DPolygon.append(basegfx::B2DPoint(0,0));
1958 aNewB2DPolygon.setClosed(true);
1959 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1961 aNewB2DPolygon.clear();
1962 aNewB2DPolygon.append(basegfx::B2DPoint(aLogicRect.GetWidth(),
1963 aLogicRect.GetHeight()));
1964 aNewB2DPolygon.setClosed(true);
1965 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1968 // #i37011#
1969 bool bForceCreateTwoObjects(false);
1971 if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1973 bForceCreateTwoObjects = true;
1976 if(bLineGeometryNeededOnly)
1978 bForceCreateTwoObjects = true;
1979 bNoFill = true;
1980 bNoStroke = false;
1983 if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1985 if(bFilled && !bNoFill)
1987 basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1988 aClosedPolyPolygon.setClosed(true);
1989 SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon, dBrightness);
1990 SfxItemSet aTempSet(*this);
1991 aTempSet.Put(SdrShadowItem(sal_False));
1992 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1993 pFill->SetMergedItemSet(aTempSet);
1994 rObjectList.push_back(pFill);
1997 if(!bNoStroke)
1999 // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
2000 // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
2001 // to correct the polygon (here: open it) using the type, the last edge may get lost.
2002 // Thus, use a type that fits the polygon
2003 SdrPathObj* pStroke = new SdrPathObj(
2004 aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
2005 aNewB2DPolyPolygon, dBrightness);
2006 SfxItemSet aTempSet(*this);
2007 aTempSet.Put(SdrShadowItem(sal_False));
2008 aTempSet.Put(XFillStyleItem(XFILL_NONE));
2009 pStroke->SetMergedItemSet(aTempSet);
2010 rObjectList.push_back(pStroke);
2013 else
2015 SdrPathObj* pObj = 0;
2016 SfxItemSet aTempSet(*this);
2017 aTempSet.Put(SdrShadowItem(sal_False));
2019 if(bNoFill)
2021 // see comment above about OBJ_PLIN
2022 pObj = new SdrPathObj(
2023 aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
2024 aNewB2DPolyPolygon, dBrightness);
2025 aTempSet.Put(XFillStyleItem(XFILL_NONE));
2027 else
2029 aNewB2DPolyPolygon.setClosed(true);
2030 pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon, dBrightness);
2033 if(bNoStroke)
2035 aTempSet.Put(XLineStyleItem(XLINE_NONE));
2038 if(pObj)
2040 pObj->SetMergedItemSet(aTempSet);
2041 rObjectList.push_back(pObj);
2047 void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
2049 bool bAccent = false;
2050 switch( eSpType )
2052 case mso_sptCallout1 :
2053 case mso_sptBorderCallout1 :
2054 case mso_sptCallout90 :
2055 case mso_sptBorderCallout90 :
2056 default:
2057 break;
2059 case mso_sptAccentCallout1 :
2060 case mso_sptAccentBorderCallout1 :
2061 case mso_sptAccentCallout90 :
2062 case mso_sptAccentBorderCallout90 :
2064 sal_uInt32 i, nLine = 0;
2065 for ( i = 0; i < vObjectList.size(); i++ )
2067 SdrPathObj* pObj( vObjectList[ i ] );
2068 if(pObj->IsLine())
2070 nLine++;
2071 if ( nLine == nLineObjectCount )
2073 pObj->ClearMergedItem( XATTR_LINESTART );
2074 pObj->ClearMergedItem( XATTR_LINEEND );
2079 break;
2081 // switch start & end
2082 case mso_sptAccentCallout2 :
2083 case mso_sptAccentBorderCallout2 :
2084 bAccent = true;
2085 case mso_sptCallout2 :
2086 case mso_sptBorderCallout2 :
2088 sal_uInt32 i, nLine = 0;
2089 for ( i = 0; i < vObjectList.size(); i++ )
2091 SdrPathObj* pObj( vObjectList[ i ] );
2092 if(pObj->IsLine())
2094 nLine++;
2095 if ( nLine == 1 )
2096 pObj->ClearMergedItem( XATTR_LINEEND );
2097 else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
2098 pObj->ClearMergedItem( XATTR_LINESTART );
2099 else
2101 pObj->ClearMergedItem( XATTR_LINESTART );
2102 pObj->ClearMergedItem( XATTR_LINEEND );
2107 break;
2109 case mso_sptAccentCallout3 :
2110 case mso_sptAccentBorderCallout3 :
2111 bAccent = false;
2112 case mso_sptCallout3 :
2113 case mso_sptBorderCallout3 :
2115 sal_uInt32 i, nLine = 0;
2116 for ( i = 0; i < vObjectList.size(); i++ )
2118 SdrPathObj* pObj( vObjectList[ i ] );
2119 if(pObj->IsLine())
2121 if ( nLine )
2123 pObj->ClearMergedItem( XATTR_LINESTART );
2124 pObj->ClearMergedItem( XATTR_LINEEND );
2126 else
2127 EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
2129 nLine++;
2133 break;
2137 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
2138 sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
2140 if ( !rObj.IsLine() )
2142 const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2143 switch( eFillStyle )
2145 default:
2146 case XFILL_SOLID:
2148 Color aFillColor;
2149 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2151 aFillColor = GetColorData(
2152 ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
2153 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() );
2154 rObj.SetMergedItem( XFillColorItem( String(), aFillColor ) );
2156 break;
2158 case XFILL_GRADIENT:
2160 XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
2161 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2163 aXGradient.SetStartColor(
2164 GetColorData(
2165 aXGradient.GetStartColor(),
2166 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2167 aXGradient.SetEndColor(
2168 GetColorData(
2169 aXGradient.GetEndColor(),
2170 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2173 rObj.SetMergedItem( XFillGradientItem( String(), aXGradient ) );
2174 break;
2176 case XFILL_HATCH:
2178 XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
2179 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2181 aXHatch.SetColor(
2182 GetColorData(
2183 aXHatch.GetColor(),
2184 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2187 rObj.SetMergedItem( XFillHatchItem( String(), aXHatch ) );
2188 break;
2190 case XFILL_BITMAP:
2192 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2194 Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2196 aBitmap.Adjust(
2197 static_cast< short > ( GetLuminanceChange(
2198 std::min(nColorIndex, nColorCount-1))));
2200 rObj.SetMergedItem(XFillBitmapItem(String(), Graphic(aBitmap)));
2203 break;
2207 if ( nColorIndex < nColorCount )
2208 nColorIndex++;
2212 SdrObject* EnhancedCustomShape2d::CreatePathObj( sal_Bool bLineGeometryNeededOnly )
2214 sal_Int32 nCoordSize = seqCoordinates.getLength();
2215 if ( !nCoordSize )
2216 return NULL;
2218 sal_uInt16 nSrcPt = 0;
2219 sal_uInt16 nSegmentInd = 0;
2221 std::vector< SdrPathObj* > vObjectList;
2222 sal_Bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
2224 sal_Int32 nSubPathIndex = 0;
2226 while( nSegmentInd <= seqSegments.getLength() )
2228 CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack, nSubPathIndex );
2229 nSubPathIndex ++;
2232 SdrObject* pRet = NULL;
2233 sal_uInt32 i;
2235 if ( !vObjectList.empty() )
2237 const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
2238 sal_uInt32 nColorCount = nColorData >> 28;
2239 sal_uInt32 nColorIndex = 0;
2241 // #i37011# remove invisible objects
2242 if(!vObjectList.empty())
2244 std::vector< SdrPathObj* > vTempList;
2246 for(i = 0L; i < vObjectList.size(); i++)
2248 SdrPathObj* pObj(vObjectList[i]);
2249 const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
2250 const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2252 //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2253 if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
2254 delete pObj;
2255 else
2256 vTempList.push_back(pObj);
2259 vObjectList = vTempList;
2262 if(1L == vObjectList.size())
2264 // a single object, correct some values
2265 AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2267 else
2269 sal_Int32 nLineObjectCount = 0;
2270 sal_Int32 nAreaObjectCount = 0;
2272 // correct some values and collect content data
2273 for ( i = 0; i < vObjectList.size(); i++ )
2275 SdrPathObj* pObj( vObjectList[ i ] );
2277 if(pObj->IsLine())
2279 nLineObjectCount++;
2281 else
2283 nAreaObjectCount++;
2284 AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2288 // #i88870# correct line arrows for callouts
2289 if ( nLineObjectCount )
2290 CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2292 // sort objects so that filled ones are in front. Necessary
2293 // for some strange objects
2294 if ( bSortFilledObjectsToBack )
2296 std::vector< SdrPathObj* > vTempList;
2298 for ( i = 0; i < vObjectList.size(); i++ )
2300 SdrPathObj* pObj( vObjectList[ i ] );
2302 if ( !pObj->IsLine() )
2304 vTempList.push_back(pObj);
2308 for ( i = 0; i < vObjectList.size(); i++ )
2310 SdrPathObj* pObj( vObjectList[ i ] );
2312 if ( pObj->IsLine() )
2314 vTempList.push_back(pObj);
2318 vObjectList = vTempList;
2323 // #i37011#
2324 if(!vObjectList.empty())
2326 // copy remaining objects to pRet
2327 if(vObjectList.size() > 1L)
2329 pRet = new SdrObjGroup;
2331 for (i = 0L; i < vObjectList.size(); i++)
2333 SdrObject* pObj(vObjectList[i]);
2334 pRet->GetSubList()->NbcInsertObject(pObj);
2337 else if(1L == vObjectList.size())
2339 pRet = vObjectList[0L];
2342 if(pRet)
2344 // move to target position
2345 Rectangle aCurRect(pRet->GetSnapRect());
2346 aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2347 pRet->NbcSetSnapRect(aCurRect);
2351 return pRet;
2354 SdrObject* EnhancedCustomShape2d::CreateObject( sal_Bool bLineGeometryNeededOnly )
2356 SdrObject* pRet = NULL;
2358 if ( eSpType == mso_sptRectangle )
2360 pRet = new SdrRectObj( aLogicRect );
2361 pRet->SetMergedItemSet( *this );
2363 if ( !pRet )
2364 pRet = CreatePathObj( bLineGeometryNeededOnly );
2366 return pRet;
2369 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2371 if ( pObj && seqGluePoints.getLength() )
2373 sal_uInt32 i, nCount = seqGluePoints.getLength();
2374 for ( i = 0; i < nCount; i++ )
2376 SdrGluePoint aGluePoint;
2378 aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], true, true ) );
2379 aGluePoint.SetPercent( sal_False );
2380 aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2381 aGluePoint.SetEscDir( SDRESC_SMART );
2382 SdrGluePointList* pList = pObj->ForceGluePointList();
2383 if( pList )
2384 /* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2389 bool EnhancedCustomShape2d::IsPostRotate() const
2391 return pCustomShapeObj->ISA( SdrObjCustomShape ) ? ((SdrObjCustomShape*)pCustomShapeObj)->IsPostRotate() : false;
2394 SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2396 return CreateObject( true );
2400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */