Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / customshapes / EnhancedCustomShape2d.cxx
blobc39428e688f2961c9700857fddd4c7ba629f12f3
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>
54 #include <basegfx/polygon/b2dpolygontools.hxx>
55 #include <rtl/strbuf.hxx>
56 #include <math.h>
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::drawing;
60 using namespace ::com::sun::star::drawing::EnhancedCustomShapeSegmentCommand;
62 void EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nValue )
64 sal_uInt32 nDat = (sal_uInt32)nValue;
65 sal_Int32 nNewValue = nValue;
67 // check if this is a special point
68 if ( ( nDat >> 16 ) == 0x8000 )
70 nNewValue = (sal_uInt16)nDat;
71 rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
73 else
74 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
75 rParameter.Value <<= nNewValue;
78 OUString EnhancedCustomShape2d::GetEquation( const sal_uInt16 nFlags, sal_Int32 nP1, sal_Int32 nP2, sal_Int32 nP3 )
80 OUString aEquation;
81 bool b1Special = ( nFlags & 0x2000 ) != 0;
82 bool b2Special = ( nFlags & 0x4000 ) != 0;
83 bool b3Special = ( nFlags & 0x8000 ) != 0;
84 switch( nFlags & 0xff )
86 case 0 :
87 case 14 :
89 sal_Int32 nOptimize = 0;
90 if ( nP1 )
91 nOptimize |= 1;
92 if ( nP2 )
93 nOptimize |= 2;
94 if ( b1Special )
95 nOptimize |= 4;
96 if ( b2Special )
97 nOptimize |= 8;
98 switch( nOptimize )
100 case 0 :
101 break;
102 case 1 :
103 case 4 :
104 case 5 :
105 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
106 break;
107 case 2 :
108 case 8 :
109 case 10:
110 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
111 break;
112 default :
114 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
115 aEquation += OUString( (sal_Unicode)'+' );
116 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
118 break;
120 if ( b3Special || nP3 )
122 aEquation += OUString( (sal_Unicode)'-' );
123 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
126 break;
127 case 1 :
129 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
130 if ( b2Special || ( nP2 != 1 ) )
132 aEquation += OUString( (sal_Unicode)'*' );
133 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
135 if ( b3Special || ( ( nP3 != 1 ) && ( nP3 != 0 ) ) )
137 aEquation += OUString( (sal_Unicode)'/' );
138 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
141 break;
142 case 2 :
144 aEquation += "(";
145 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
146 aEquation += "+";
147 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
148 aEquation += ")/2";
150 break;
151 case 3 :
153 aEquation += "abs(";
154 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
155 aEquation += ")";
157 break;
158 case 4 :
160 aEquation += "min(";
161 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
162 aEquation += ",";
163 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
164 aEquation += ")";
166 break;
167 case 5 :
169 aEquation += "max(";
170 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
171 aEquation += ",";
172 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
173 aEquation += ")";
175 break;
176 case 6 :
178 aEquation += "if(";
179 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
180 aEquation += OUString( (sal_Unicode)',' );
181 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
182 aEquation += OUString( (sal_Unicode)',' );
183 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
184 aEquation += OUString( (sal_Unicode)')' );
186 break;
187 case 7 :
189 aEquation += "sqrt(";
190 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
191 aEquation += "*";
192 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
193 aEquation += "+";
194 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
195 aEquation += "*";
196 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
197 aEquation += "+";
198 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
199 aEquation += "*";
200 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
201 aEquation += OUString( (sal_Unicode)')' );
203 break;
204 case 8 :
206 aEquation += "atan2(";
207 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
208 aEquation += ",";
209 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
210 aEquation += ")/(pi/180)";
212 break;
213 case 9 :
215 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
216 aEquation += "*sin(";
217 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
218 aEquation += "*(pi/180))";
220 break;
221 case 10 :
223 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
224 aEquation += "*cos(";
225 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
226 aEquation += "*(pi/180))";
228 break;
229 case 11 :
231 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
232 aEquation += "*cos(atan2(";
233 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
234 aEquation += ",";
235 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
236 aEquation += "))";
238 break;
239 case 12 :
241 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
242 aEquation += "*sin(atan2(";
243 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
244 aEquation += ",";
245 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
246 aEquation += "))";
248 break;
249 case 13 :
251 aEquation += "sqrt(";
252 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
253 aEquation += ")";
255 break;
256 case 15 :
258 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
259 aEquation += "*sqrt(1-(";
260 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
261 aEquation += "/";
262 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
263 aEquation += ")";
264 aEquation += "*(";
265 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
266 aEquation += "/";
267 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
268 aEquation += "))";
270 break;
271 case 16 :
273 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
274 aEquation += "*tan(";
275 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
276 aEquation += ")";
278 break;
279 case 0x80 :
281 aEquation += "sqrt(";
282 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
283 aEquation += "*";
284 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
285 aEquation += "-";
286 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
287 aEquation += "*";
288 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
289 aEquation += OUString( (sal_Unicode)')' );
291 break;
292 case 0x81 :
294 aEquation += "(cos(";
295 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
296 aEquation += "*(pi/180))*(";
297 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
298 aEquation += "-10800)+sin(";
299 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
300 aEquation += "*(pi/180))*(";
301 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
302 aEquation += "-10800))+10800";
304 break;
305 case 0x82 :
307 aEquation += "-(sin(";
308 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
309 aEquation += "*(pi/180))*(";
310 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP1, b1Special );
311 aEquation += "-10800)-cos(";
312 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP3, b3Special );
313 aEquation += "*(pi/180))*(";
314 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation, nP2, b2Special );
315 aEquation += "-10800))+10800";
317 break;
319 return aEquation;
322 void EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( OUString& rParameter, const sal_Int32 nPara, const bool bIsSpecialValue )
324 if ( bIsSpecialValue )
326 if ( nPara & 0x400 )
328 rParameter += "?";
329 rParameter += OUString::number( ( nPara & 0xff ) );
330 rParameter += " ";
332 else
334 switch( nPara )
336 case DFF_Prop_adjustValue :
337 case DFF_Prop_adjust2Value :
338 case DFF_Prop_adjust3Value :
339 case DFF_Prop_adjust4Value :
340 case DFF_Prop_adjust5Value :
341 case DFF_Prop_adjust6Value :
342 case DFF_Prop_adjust7Value :
343 case DFF_Prop_adjust8Value :
344 case DFF_Prop_adjust9Value :
345 case DFF_Prop_adjust10Value :
347 rParameter += "$";
348 rParameter += OUString::number( ( nPara - DFF_Prop_adjustValue ) );
349 rParameter += " ";
351 break;
352 case DFF_Prop_geoLeft :
354 rParameter += "left";
356 break;
357 case DFF_Prop_geoTop :
359 rParameter += "top";
361 break;
362 case DFF_Prop_geoRight :
364 rParameter += "right";
366 break;
367 case DFF_Prop_geoBottom :
369 rParameter += "bottom";
371 break;
375 else
377 rParameter += OUString::number( ( nPara ) );
381 void EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( EnhancedCustomShapeParameter& rParameter, const sal_Int32 nPara, const bool bIsSpecialValue, bool bHorz )
383 sal_Int32 nValue = 0;
384 if ( bIsSpecialValue )
386 if ( ( nPara >= 0x100 ) && ( nPara <= 0x107 ) )
388 nValue = nPara & 0xff;
389 rParameter.Type = EnhancedCustomShapeParameterType::ADJUSTMENT;
391 else if ( ( nPara >= 3 ) && ( nPara <= 0x82 ) )
393 nValue = nPara - 3;
394 rParameter.Type = EnhancedCustomShapeParameterType::EQUATION;
396 else if ( nPara == 0 )
398 nValue = 0;
399 if ( bHorz )
400 rParameter.Type = EnhancedCustomShapeParameterType::LEFT;
401 else
402 rParameter.Type = EnhancedCustomShapeParameterType::TOP;
404 else if ( nPara == 1 )
406 nValue = 0;
407 if ( bHorz )
408 rParameter.Type = EnhancedCustomShapeParameterType::RIGHT;
409 else
410 rParameter.Type = EnhancedCustomShapeParameterType::BOTTOM;
412 else if ( nPara == 2 ) // means to be centered, but should not be
413 { // used in our implementation
414 nValue = 5600;
415 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
417 else
419 nValue = nPara;
420 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
423 else
425 nValue = nPara;
426 rParameter.Type = EnhancedCustomShapeParameterType::NORMAL;
428 rParameter.Value <<= nValue;
431 bool EnhancedCustomShape2d::ConvertSequenceToEnhancedCustomShape2dHandle(
432 const com::sun::star::beans::PropertyValues& rHandleProperties,
433 EnhancedCustomShape2d::Handle& rDestinationHandle )
435 bool bRetValue = false;
436 sal_uInt32 i, nProperties = rHandleProperties.getLength();
437 if ( nProperties )
439 rDestinationHandle.nFlags = 0;
440 for ( i = 0; i < nProperties; i++ )
442 const com::sun::star::beans::PropertyValue& rPropVal = rHandleProperties[ i ];
444 const OUString sPosition ( "Position" );
445 const OUString sMirroredX ( "MirroredX" );
446 const OUString sMirroredY ( "MirroredY" );
447 const OUString sSwitched ( "Switched" );
448 const OUString sPolar ( "Polar" );
449 const OUString sRefX ( "RefX" );
450 const OUString sRefY ( "RefY" );
451 const OUString sRefAngle ( "RefAngle" );
452 const OUString sRefR ( "RefR" );
453 const OUString sRadiusRangeMinimum ( "RadiusRangeMinimum" );
454 const OUString sRadiusRangeMaximum ( "RadiusRangeMaximum" );
455 const OUString sRangeXMinimum ( "RangeXMinimum" );
456 const OUString sRangeXMaximum ( "RangeXMaximum" );
457 const OUString sRangeYMinimum ( "RangeYMinimum" );
458 const OUString sRangeYMaximum ( "RangeYMaximum" );
460 if ( rPropVal.Name == sPosition )
462 if ( rPropVal.Value >>= rDestinationHandle.aPosition )
463 bRetValue = true;
465 else if ( rPropVal.Name == sMirroredX )
467 bool bMirroredX;
468 if ( rPropVal.Value >>= bMirroredX )
470 if ( bMirroredX )
471 rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_X;
474 else if ( rPropVal.Name == sMirroredY )
476 bool bMirroredY;
477 if ( rPropVal.Value >>= bMirroredY )
479 if ( bMirroredY )
480 rDestinationHandle.nFlags |= HANDLE_FLAGS_MIRRORED_Y;
483 else if ( rPropVal.Name == sSwitched )
485 bool bSwitched;
486 if ( rPropVal.Value >>= bSwitched )
488 if ( bSwitched )
489 rDestinationHandle.nFlags |= HANDLE_FLAGS_SWITCHED;
492 else if ( rPropVal.Name == sPolar )
494 if ( rPropVal.Value >>= rDestinationHandle.aPolar )
495 rDestinationHandle.nFlags |= HANDLE_FLAGS_POLAR;
497 else if ( rPropVal.Name == sRefX )
499 if ( rPropVal.Value >>= rDestinationHandle.nRefX )
500 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFX;
502 else if ( rPropVal.Name == sRefY )
504 if ( rPropVal.Value >>= rDestinationHandle.nRefY )
505 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFY;
507 else if ( rPropVal.Name == sRefAngle )
509 if ( rPropVal.Value >>= rDestinationHandle.nRefAngle )
510 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFANGLE;
512 else if ( rPropVal.Name == sRefR )
514 if ( rPropVal.Value >>= rDestinationHandle.nRefR )
515 rDestinationHandle.nFlags |= HANDLE_FLAGS_REFR;
517 else if ( rPropVal.Name == sRadiusRangeMinimum )
519 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMinimum )
520 rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MINIMUM;
522 else if ( rPropVal.Name == sRadiusRangeMaximum )
524 if ( rPropVal.Value >>= rDestinationHandle.aRadiusRangeMaximum )
525 rDestinationHandle.nFlags |= HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM;
527 else if ( rPropVal.Name == sRangeXMinimum )
529 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMinimum )
530 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MINIMUM;
532 else if ( rPropVal.Name == sRangeXMaximum )
534 if ( rPropVal.Value >>= rDestinationHandle.aXRangeMaximum )
535 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_X_MAXIMUM;
537 else if ( rPropVal.Name == sRangeYMinimum )
539 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMinimum )
540 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MINIMUM;
542 else if ( rPropVal.Name == sRangeYMaximum )
544 if ( rPropVal.Value >>= rDestinationHandle.aYRangeMaximum )
545 rDestinationHandle.nFlags |= HANDLE_FLAGS_RANGE_Y_MAXIMUM;
549 return bRetValue;
552 const sal_Int32* EnhancedCustomShape2d::ApplyShapeAttributes( const SdrCustomShapeGeometryItem& rGeometryItem )
554 const sal_Int32* pDefData = NULL;
555 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType );
556 if ( pDefCustomShape )
557 pDefData = pDefCustomShape->pDefData;
560 // AdjustmentValues
562 const OUString sAdjustmentValues( "AdjustmentValues" );
563 const Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sAdjustmentValues );
564 if ( pAny )
565 *pAny >>= seqAdjustmentValues;
568 // Coordsize
570 const OUString sViewBox( "ViewBox" );
571 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
572 com::sun::star::awt::Rectangle aViewBox;
573 if ( pViewBox && (*pViewBox >>= aViewBox ) )
575 nCoordLeft = aViewBox.X;
576 nCoordTop = aViewBox.Y;
577 nCoordWidthG = labs( aViewBox.Width );
578 nCoordHeightG = labs( aViewBox.Height);
580 const OUString sPath( "Path" );
583 // Path/Coordinates
585 const OUString sCoordinates( "Coordinates" );
586 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sCoordinates );
587 if ( pAny )
588 *pAny >>= seqCoordinates;
591 // Path/GluePoints
593 const OUString sGluePoints( "GluePoints" );
594 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePoints );
595 if ( pAny )
596 *pAny >>= seqGluePoints;
599 // Path/Segments
601 const OUString sSegments( "Segments" );
602 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSegments );
603 if ( pAny )
604 *pAny >>= seqSegments;
607 // Path/SubViewSize
609 const OUString sSubViewSize( "SubViewSize" );
610 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sSubViewSize );
611 if ( pAny )
612 *pAny >>= seqSubViewSize;
615 // Path/StretchX
617 const OUString sStretchX( "StretchX" );
618 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchX );
619 if ( pAny )
621 sal_Int32 nStretchX = 0;
622 if ( *pAny >>= nStretchX )
623 nXRef = nStretchX;
627 // Path/StretchY
629 const OUString sStretchY( "StretchY" );
630 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sStretchY );
631 if ( pAny )
633 sal_Int32 nStretchY = 0;
634 if ( *pAny >>= nStretchY )
635 nYRef = nStretchY;
639 // Path/TextFrames
641 const OUString sTextFrames( "TextFrames" );
642 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sTextFrames );
643 if ( pAny )
644 *pAny >>= seqTextFrames;
647 // Equations
649 const OUString sEquations( "Equations" );
650 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
651 if ( pAny )
652 *pAny >>= seqEquations;
655 // Handles
657 const OUString sHandles( "Handles" );
658 pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sHandles );
659 if ( pAny )
660 *pAny >>= seqHandles;
662 return pDefData;
665 EnhancedCustomShape2d::~EnhancedCustomShape2d()
669 void EnhancedCustomShape2d::SetPathSize( sal_Int32 nIndex )
671 sal_Int32 nWidth = 0;
672 sal_Int32 nHeight = 0;
674 if ( seqSubViewSize.getLength() && nIndex < seqSubViewSize.getLength() ) {
675 nWidth = seqSubViewSize[ nIndex ].Width;
676 nHeight = seqSubViewSize[ nIndex ].Height;
677 OSL_TRACE("set subpath %d size: %d x %d", nIndex, nWidth, nHeight);
680 if ( nWidth && nHeight ) {
681 nCoordWidth = nWidth;
682 nCoordHeight = nHeight;
683 } else {
684 nCoordWidth = nCoordWidthG;
685 nCoordHeight = nCoordHeightG;
688 fXScale = nCoordWidth == 0 ? 0.0 : (double)aLogicRect.GetWidth() / (double)nCoordWidth;
689 fYScale = nCoordHeight == 0 ? 0.0 : (double)aLogicRect.GetHeight() / (double)nCoordHeight;
690 if ( bOOXMLShape )
692 OSL_TRACE("ooxml shape, path width: %d height: %d", nCoordWidth, nCoordHeight);
693 if ( nCoordWidth == 0 )
694 fXScale = 1.0;
695 if ( nCoordHeight == 0 )
696 fYScale = 1.0;
698 if ( (sal_uInt32)nXRef != 0x80000000 && aLogicRect.GetHeight() )
700 fXRatio = (double)aLogicRect.GetWidth() / (double)aLogicRect.GetHeight();
701 if ( fXRatio > 1 )
702 fXScale /= fXRatio;
703 else
704 fXRatio = 1.0;
706 else
707 fXRatio = 1.0;
708 if ( (sal_uInt32)nYRef != 0x80000000 && aLogicRect.GetWidth() )
710 fYRatio = (double)aLogicRect.GetHeight() / (double)aLogicRect.GetWidth();
711 if ( fYRatio > 1 )
712 fYScale /= fYRatio;
713 else
714 fYRatio = 1.0;
716 else
717 fYRatio = 1.0;
720 EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject* pAObj ) :
721 SfxItemSet ( pAObj->GetMergedItemSet() ),
722 pCustomShapeObj ( pAObj ),
723 eSpType ( mso_sptNil ),
724 nCoordLeft ( 0 ),
725 nCoordTop ( 0 ),
726 nCoordWidthG ( 21600 ),
727 nCoordHeightG ( 21600 ),
728 bOOXMLShape ( false ),
729 nXRef ( 0x80000000 ),
730 nYRef ( 0x80000000 ),
731 nFlags ( 0 ),
732 nColorData ( 0 ),
733 bTextFlow ( false ),
734 bFilled ( ((const XFillStyleItem&)pAObj->GetMergedItem( XATTR_FILLSTYLE )).GetValue() != XFILL_NONE ),
735 bStroked ( ((const XLineStyleItem&)pAObj->GetMergedItem( XATTR_LINESTYLE )).GetValue() != XLINE_NONE ),
736 bFlipH ( false ),
737 bFlipV ( false )
739 // bTextFlow needs to be set before clearing the TextDirection Item
741 ClearItem( SDRATTR_TEXTDIRECTION ); //SJ: vertical writing is not required, by removing this item no outliner is created
743 // #i105323# For 2D AtoShapes, the shadow attirbute does not need to be applied to any
744 // of the constucted helper SdrObjects. This would lead to problems since the shadow
745 // of one helper object would fall on one helper object behind it (e.g. with the
746 // eyes of the smiley shape). This is not wanted; instead a single shadow 'behind'
747 // the AutoShape visualisation is wanted. This is done with primitive functionailty
748 // now in SdrCustomShapePrimitive2D::create2DDecomposition, but only for 2D objects
749 // (see there and in EnhancedCustomShape3d::Create3DObject to read more).
750 // This exception may be removed later when AutoShapes will create primitives directly.
751 // So, currently remove the ShadowAttribute from the ItemSet to not apply it to any
752 // 2D helper shape.
753 ClearItem(SDRATTR_SHADOW);
755 Point aP( pCustomShapeObj->GetSnapRect().Center() );
756 Size aS( pCustomShapeObj->GetLogicRect().GetSize() );
757 aP.X() -= aS.Width() / 2;
758 aP.Y() -= aS.Height() / 2;
759 aLogicRect = Rectangle( aP, aS );
761 const OUString sType( "Type" );
762 const OUString sMirroredX( "MirroredX" );
763 const OUString sMirroredY( "MirroredY" );
765 OUString sShapeType;
766 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
767 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
768 if ( pAny ) {
769 *pAny >>= sShapeType;
770 bOOXMLShape = ( sShapeType.startsWith("ooxml-") );
771 OSL_TRACE("shape type: %s %d", OUStringToOString( sShapeType, RTL_TEXTENCODING_ASCII_US ).getStr(), bOOXMLShape);
773 eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
775 pAny = rGeometryItem.GetPropertyValueByName( sMirroredX );
776 if ( pAny )
777 *pAny >>= bFlipH;
778 pAny = rGeometryItem.GetPropertyValueByName( sMirroredY );
779 if ( pAny )
780 *pAny >>= bFlipV;
782 if ( pCustomShapeObj->ISA( SdrObjCustomShape ) ) // should always be a SdrObjCustomShape, but you don't know
783 nRotateAngle = (sal_Int32)(((SdrObjCustomShape*)pCustomShapeObj)->GetObjectRotation() * 100.0);
784 else
785 nRotateAngle = pCustomShapeObj->GetRotateAngle();
787 /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem );
788 SetPathSize();
790 switch( eSpType )
792 case mso_sptCan : nColorData = 0x20400000; break;
793 case mso_sptCube : nColorData = 0x302e0000; break;
794 case mso_sptActionButtonBlank : nColorData = 0x502ce400; break;
795 case mso_sptActionButtonHome : nColorData = 0x702ce4ce; break;
796 case mso_sptActionButtonHelp : nColorData = 0x602ce4c0; break;
797 case mso_sptActionButtonInformation : nColorData = 0x702ce4c5; break;
798 case mso_sptActionButtonBackPrevious : nColorData = 0x602ce4c0; break;
799 case mso_sptActionButtonForwardNext : nColorData = 0x602ce4c0; break;
800 case mso_sptActionButtonBeginning : nColorData = 0x602ce4c0; break;
801 case mso_sptActionButtonEnd : nColorData = 0x602ce4c0; break;
802 case mso_sptActionButtonReturn : nColorData = 0x602ce4c0; break;
803 case mso_sptActionButtonDocument : nColorData = 0x702ce4ec; break;
804 case mso_sptActionButtonSound : nColorData = 0x602ce4c0; break;
805 case mso_sptActionButtonMovie : nColorData = 0x602ce4c0; break;
806 case mso_sptBevel : nColorData = 0x502ce400; break;
807 case mso_sptFoldedCorner : nColorData = 0x20e00000; break;
808 case mso_sptSmileyFace : nColorData = 0x20e00000; break;
809 case mso_sptNil :
811 if( sShapeType.getLength() > 4 &&
812 sShapeType.match( "col-" ))
814 nColorData = sShapeType.copy( 4 ).toUInt32( 16 );
817 break;
818 case mso_sptCurvedLeftArrow :
819 case mso_sptCurvedRightArrow :
820 case mso_sptCurvedUpArrow :
821 case mso_sptCurvedDownArrow : nColorData = 0x20d00000; break;
822 case mso_sptRibbon2 : nColorData = 0x30ee0000; break;
823 case mso_sptRibbon : nColorData = 0x30ee0000; break;
825 case mso_sptEllipseRibbon2 : nColorData = 0x30ee0000; break;
826 case mso_sptEllipseRibbon : nColorData = 0x30ee0000; break;
828 case mso_sptVerticalScroll : nColorData = 0x30ee0000; break;
829 case mso_sptHorizontalScroll : nColorData = 0x30ee0000; break;
830 default:
831 break;
834 sal_Int32 i, nLength = seqEquations.getLength();
836 if ( nLength )
838 vNodesSharedPtr.resize( nLength );
839 vEquationResults.resize( nLength );
840 for ( i = 0; i < seqEquations.getLength(); i++ )
842 vEquationResults[ i ].bReady = false;
845 vNodesSharedPtr[ i ] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations[ i ], *this );
847 catch ( EnhancedCustomShape::ParseError& )
849 OSL_TRACE("error: equation number: %d, parser failed ( %s )",
850 i, OUStringToOString( seqEquations[ i ], RTL_TEXTENCODING_ASCII_US ).getStr());
855 double EnhancedCustomShape2d::GetEnumFunc( const EnumFunc eFunc ) const
857 double fRet = 0.0;
858 switch( eFunc )
860 case ENUM_FUNC_PI : fRet = F_PI; break;
861 case ENUM_FUNC_LEFT : fRet = 0.0; break;
862 case ENUM_FUNC_TOP : fRet = 0.0; break;
863 case ENUM_FUNC_RIGHT : fRet = (double)nCoordWidth * fXRatio; break;
864 case ENUM_FUNC_BOTTOM : fRet = (double)nCoordHeight * fYRatio; break;
865 case ENUM_FUNC_XSTRETCH : fRet = nXRef; break;
866 case ENUM_FUNC_YSTRETCH : fRet = nYRef; break;
867 case ENUM_FUNC_HASSTROKE : fRet = bStroked ? 1.0 : 0.0; break;
868 case ENUM_FUNC_HASFILL : fRet = bFilled ? 1.0 : 0.0; break;
869 case ENUM_FUNC_WIDTH : fRet = nCoordWidth; break;
870 case ENUM_FUNC_HEIGHT : fRet = nCoordHeight; break;
871 case ENUM_FUNC_LOGWIDTH : fRet = aLogicRect.GetWidth(); break;
872 case ENUM_FUNC_LOGHEIGHT : fRet = aLogicRect.GetHeight(); break;
874 return fRet;
876 double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex ) const
878 double fNumber = 0.0;
879 if ( nIndex < seqAdjustmentValues.getLength() )
881 if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
882 seqAdjustmentValues[ nIndex ].Value >>= fNumber;
883 else
885 sal_Int32 nNumber = 0;
886 seqAdjustmentValues[ nIndex ].Value >>= nNumber;
887 fNumber = (double)nNumber;
890 return fNumber;
892 double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex ) const
894 double fNumber = 0.0;
895 #if OSL_DEBUG_LEVEL > 1
896 static sal_uInt32 nLevel = 0;
897 #endif
898 if ( nIndex < (sal_Int32)vNodesSharedPtr.size() )
900 if ( vNodesSharedPtr[ nIndex ].get() ) {
901 #if OSL_DEBUG_LEVEL > 1
902 nLevel ++;
903 #endif
906 if ( vEquationResults[ nIndex ].bReady )
907 fNumber = vEquationResults[ nIndex ].fValue;
908 else {
909 // cast to non const, so that we can optimize by caching
910 // equation results, without changing all the const in the stack
911 struct EquationResult &aResult = ((EnhancedCustomShape2d*)this)->vEquationResults[ nIndex ];
913 fNumber = aResult.fValue = (*vNodesSharedPtr[ nIndex ])();
914 aResult.bReady = true;
916 if ( !rtl::math::isFinite( fNumber ) )
917 fNumber = 0.0;
918 #if OSL_DEBUG_LEVEL > 1
919 OSL_TRACE("equation %d (level: %d): %s --> %f (angle: %f)", nIndex,
920 nLevel, OUStringToOString( seqEquations[ nIndex ],
921 RTL_TEXTENCODING_ASCII_US ).getStr(), fNumber, 180.0*fNumber/10800000.0);
922 #endif
925 catch ( ... )
927 OSL_TRACE("error: EnhancedCustomShape2d::GetEquationValueAsDouble failed");
929 #if OSL_DEBUG_LEVEL > 1
930 nLevel --;
931 #endif
933 OSL_TRACE(" ?%d --> %f (angle: %f)", nIndex,
934 fNumber, 180.0*fNumber/10800000.0);
937 return fNumber;
939 sal_Int32 EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex, const sal_Int32 nDefault ) const
941 sal_Int32 nNumber = nDefault;
942 if ( nIndex < seqAdjustmentValues.getLength() )
944 if ( seqAdjustmentValues[ nIndex ].Value.getValueTypeClass() == TypeClass_DOUBLE )
946 double fNumber = 0;
947 seqAdjustmentValues[ nIndex ].Value >>= fNumber;
948 nNumber = (sal_Int32)fNumber;
950 else
951 seqAdjustmentValues[ nIndex ].Value >>= nNumber;
953 return nNumber;
955 bool EnhancedCustomShape2d::SetAdjustValueAsDouble( const double& rValue, const sal_Int32 nIndex )
957 bool bRetValue = false;
958 if ( nIndex < seqAdjustmentValues.getLength() )
960 // updating our local adjustment sequence
961 seqAdjustmentValues[ nIndex ].Value <<= rValue;
962 seqAdjustmentValues[ nIndex ].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
963 bRetValue = true;
965 return bRetValue;
968 Point EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair& rPair,
969 const bool bScale, const bool bReplaceGeoSize ) const
971 Point aRetValue;
972 bool bExchange = ( nFlags & DFF_CUSTOMSHAPE_EXCH ) != 0; // x <-> y
973 sal_uInt32 nPass = 0;
976 sal_uInt32 nIndex = nPass;
978 if ( bExchange )
979 nIndex ^= 1;
981 double fVal;
982 const EnhancedCustomShapeParameter& rParameter = nIndex ? rPair.Second : rPair.First;
983 if ( nPass ) // height
985 GetParameter( fVal, rParameter, false, bReplaceGeoSize );
986 fVal -= nCoordTop;
987 if ( bScale )
989 fVal *= fYScale;
991 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_V )
992 fVal = aLogicRect.GetHeight() - fVal;
994 aRetValue.Y() = (sal_Int32)fVal;
996 else // width
998 GetParameter( fVal, rParameter, bReplaceGeoSize, false );
999 fVal -= nCoordLeft;
1000 if ( bScale )
1002 fVal *= fXScale;
1004 if ( nFlags & DFF_CUSTOMSHAPE_FLIP_H )
1005 fVal = aLogicRect.GetWidth() - fVal;
1007 aRetValue.X() = (sal_Int32)fVal;
1010 while ( ++nPass < 2 );
1011 return aRetValue;
1014 bool EnhancedCustomShape2d::GetParameter( double& rRetValue, const EnhancedCustomShapeParameter& rParameter,
1015 const bool bReplaceGeoWidth, const bool bReplaceGeoHeight ) const
1017 rRetValue = 0.0;
1018 bool bRetValue = false;
1019 switch ( rParameter.Type )
1021 case EnhancedCustomShapeParameterType::ADJUSTMENT :
1023 sal_Int32 nAdjustmentIndex = 0;
1024 if ( rParameter.Value >>= nAdjustmentIndex )
1026 rRetValue = GetAdjustValueAsDouble( nAdjustmentIndex );
1027 bRetValue = true;
1030 break;
1031 case EnhancedCustomShapeParameterType::EQUATION :
1033 sal_Int32 nEquationIndex = 0;
1034 if ( rParameter.Value >>= nEquationIndex )
1036 rRetValue = GetEquationValueAsDouble( nEquationIndex );
1037 bRetValue = true;
1040 break;
1041 case EnhancedCustomShapeParameterType::NORMAL :
1043 if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE )
1045 double fValue(0.0);
1046 if ( rParameter.Value >>= fValue )
1048 rRetValue = fValue;
1049 bRetValue = true;
1052 else
1054 sal_Int32 nValue = 0;
1055 if ( rParameter.Value >>= nValue )
1057 rRetValue = nValue;
1058 bRetValue = true;
1059 if ( bReplaceGeoWidth && ( nValue == nCoordWidth ) )
1060 rRetValue *= fXRatio;
1061 else if ( bReplaceGeoHeight && ( nValue == nCoordHeight ) )
1062 rRetValue *= fYRatio;
1066 break;
1067 case EnhancedCustomShapeParameterType::LEFT :
1069 rRetValue = 0.0;
1070 bRetValue = true;
1072 break;
1073 case EnhancedCustomShapeParameterType::TOP :
1075 rRetValue = 0.0;
1076 bRetValue = true;
1078 break;
1079 case EnhancedCustomShapeParameterType::RIGHT :
1081 rRetValue = nCoordWidth;
1082 bRetValue = true;
1084 break;
1085 case EnhancedCustomShapeParameterType::BOTTOM :
1087 rRetValue = nCoordHeight;
1088 bRetValue = true;
1090 break;
1092 return bRetValue;
1095 // nLumDat 28-31 = number of luminance entries in nLumDat
1096 // nLumDat 27-24 = nLumDatEntry 0
1097 // nLumDat 23-20 = nLumDatEntry 1 ...
1098 // each 4bit entry is to be interpreted as a 10 percent signed luminance changing
1099 sal_Int32 EnhancedCustomShape2d::GetLuminanceChange( sal_uInt32 nIndex ) const
1101 const sal_uInt32 nCount = nColorData >> 28;
1102 if ( !nCount )
1103 return 0;
1105 if ( nIndex >= nCount )
1106 nIndex = nCount - 1;
1108 const sal_Int32 nLumDat = nColorData << ( ( 1 + nIndex ) << 2 );
1109 return ( nLumDat >> 28 ) * 10;
1112 Color EnhancedCustomShape2d::GetColorData( const Color& rFillColor, sal_uInt32 nIndex, double dBrightness ) const
1114 const sal_Int32 nLuminance = GetLuminanceChange(nIndex);
1115 if( !nLuminance && dBrightness == 1.0 )
1116 return rFillColor;
1118 basegfx::BColor aHSVColor=
1119 basegfx::tools::rgb2hsv(
1120 basegfx::BColor(rFillColor.GetRed()/255.0,
1121 rFillColor.GetGreen()/255.0,
1122 rFillColor.GetBlue()/255.0));
1123 if (nLuminance ) {
1124 if( nLuminance > 0 )
1126 aHSVColor.setGreen(
1127 aHSVColor.getGreen() * (1.0-nLuminance/100.0));
1128 aHSVColor.setBlue(
1129 nLuminance/100.0 +
1130 (1.0-nLuminance/100.0)*aHSVColor.getBlue());
1132 else if( nLuminance < 0 )
1134 aHSVColor.setBlue(
1135 (1.0+nLuminance/100.0)*aHSVColor.getBlue());
1139 aHSVColor = basegfx::tools::hsv2rgb(aHSVColor);
1140 return Color( (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getRed(),0.0,1.0) * 255.0 + 0.5 ),
1141 (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getGreen(),0.0,1.0) * 255.0 + 0.5 ),
1142 (sal_uInt8)static_cast< sal_Int32 >( basegfx::clamp(dBrightness*aHSVColor.getBlue(),0.0,1.0) * 255.0 + 0.5 ) );
1145 Rectangle EnhancedCustomShape2d::GetTextRect() const
1147 sal_Int32 nIndex, nSize = seqTextFrames.getLength();
1148 if ( !nSize )
1149 return aLogicRect;
1150 nIndex = 0;
1151 if ( bTextFlow && ( nSize > 1 ) )
1152 nIndex++;
1153 Point aTopLeft( GetPoint( seqTextFrames[ nIndex ].TopLeft, !bOOXMLShape, true ) );
1154 Point aBottomRight( GetPoint( seqTextFrames[ nIndex ].BottomRight, !bOOXMLShape, true ) );
1155 if ( bFlipH )
1157 aTopLeft.X() = aLogicRect.GetWidth() - aTopLeft.X();
1158 aBottomRight.X() = aLogicRect.GetWidth() - aBottomRight.X();
1160 if ( bFlipV )
1162 aTopLeft.Y() = aLogicRect.GetHeight() - aTopLeft.Y();
1163 aBottomRight.Y() = aLogicRect.GetHeight() - aBottomRight.Y();
1165 Rectangle aRect( aTopLeft, aBottomRight );
1166 OSL_TRACE("EnhancedCustomShape2d::GetTextRect: %d x %d", aRect.GetWidth(), aRect.GetHeight());
1167 if( aRect.GetWidth() <= 1 || aRect.GetHeight() <= 1 )
1168 return aLogicRect;
1169 aRect.Move( aLogicRect.Left(), aLogicRect.Top() );
1170 aRect.Justify();
1171 return aRect;
1174 sal_uInt32 EnhancedCustomShape2d::GetHdlCount() const
1176 return seqHandles.getLength();
1179 bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex, Point& rReturnPosition ) const
1181 bool bRetValue = false;
1182 if ( nIndex < GetHdlCount() )
1184 Handle aHandle;
1185 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1187 if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1189 Point aReferencePoint( GetPoint( aHandle.aPolar, true, false ) );
1191 double fAngle;
1192 double fRadius;
1193 GetParameter( fRadius, aHandle.aPosition.First, false, false );
1194 GetParameter( fAngle, aHandle.aPosition.Second, false, false );
1196 double a = ( 360.0 - fAngle ) * F_PI180;
1197 double dx = fRadius * fXScale;
1198 double fX = dx * cos( a );
1199 double fY =-dx * sin( a );
1200 rReturnPosition =
1201 Point(
1202 Round( fX + aReferencePoint.X() ),
1203 basegfx::fTools::equalZero(fXScale) ? aReferencePoint.Y() :
1204 Round( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) );
1206 else
1208 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1210 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1212 com::sun::star::drawing::EnhancedCustomShapeParameter aFirst = aHandle.aPosition.First;
1213 com::sun::star::drawing::EnhancedCustomShapeParameter aSecond = aHandle.aPosition.Second;
1214 aHandle.aPosition.First = aSecond;
1215 aHandle.aPosition.Second = aFirst;
1218 rReturnPosition = GetPoint( aHandle.aPosition, true, false );
1220 const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1221 if ( aGeoStat.nShearWink )
1223 double nTan = aGeoStat.nTan;
1224 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1225 nTan = -nTan;
1226 ShearPoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1228 if ( nRotateAngle )
1230 double a = nRotateAngle * F_PI18000;
1231 RotatePoint( rReturnPosition, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1233 if ( bFlipH )
1234 rReturnPosition.X() = aLogicRect.GetWidth() - rReturnPosition.X();
1235 if ( bFlipV )
1236 rReturnPosition.Y() = aLogicRect.GetHeight() - rReturnPosition.Y();
1237 rReturnPosition.Move( aLogicRect.Left(), aLogicRect.Top() );
1238 bRetValue = true;
1241 return bRetValue;
1244 bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex, const com::sun::star::awt::Point& rPosition )
1246 bool bRetValue = false;
1247 if ( nIndex < GetHdlCount() )
1249 Handle aHandle;
1250 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles[ nIndex ], aHandle ) )
1252 Point aP( rPosition.X, rPosition.Y );
1253 // apply the negative object rotation to the controller position
1255 aP.Move( -aLogicRect.Left(), -aLogicRect.Top() );
1256 if ( bFlipH )
1257 aP.X() = aLogicRect.GetWidth() - aP.X();
1258 if ( bFlipV )
1259 aP.Y() = aLogicRect.GetHeight() - aP.Y();
1260 if ( nRotateAngle )
1262 double a = -nRotateAngle * F_PI18000;
1263 RotatePoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), sin( a ), cos( a ) );
1265 const GeoStat aGeoStat( ((SdrObjCustomShape*)pCustomShapeObj)->GetGeoStat() );
1266 if ( aGeoStat.nShearWink )
1268 double nTan = -aGeoStat.nTan;
1269 if ((bFlipV&&!bFlipH )||(bFlipH&&!bFlipV))
1270 nTan = -nTan;
1271 ShearPoint( aP, Point( aLogicRect.GetWidth() / 2, aLogicRect.GetHeight() / 2 ), nTan );
1274 double fPos1 = aP.X(); //( bFlipH ) ? aLogicRect.GetWidth() - aP.X() : aP.X();
1275 double fPos2 = aP.Y(); //( bFlipV ) ? aLogicRect.GetHeight() -aP.Y() : aP.Y();
1276 fPos1 /= fXScale;
1277 fPos2 /= fYScale;
1279 if ( aHandle.nFlags & HANDLE_FLAGS_SWITCHED )
1281 if ( aLogicRect.GetHeight() > aLogicRect.GetWidth() )
1283 double fX = fPos1;
1284 double fY = fPos2;
1285 fPos1 = fY;
1286 fPos2 = fX;
1290 sal_Int32 nFirstAdjustmentValue = -1, nSecondAdjustmentValue = -1;
1292 if ( aHandle.aPosition.First.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1293 aHandle.aPosition.First.Value >>= nFirstAdjustmentValue;
1294 if ( aHandle.aPosition.Second.Type == EnhancedCustomShapeParameterType::ADJUSTMENT )
1295 aHandle.aPosition.Second.Value>>= nSecondAdjustmentValue;
1297 if ( aHandle.nFlags & HANDLE_FLAGS_POLAR )
1299 double fXRef, fYRef, fAngle;
1300 GetParameter( fXRef, aHandle.aPolar.First, false, false );
1301 GetParameter( fYRef, aHandle.aPolar.Second, false, false );
1302 const double fDX = fPos1 - fXRef;
1303 fAngle = -( atan2( -fPos2 + fYRef, ( ( fDX == 0.0L ) ? 0.000000001 : fDX ) ) / F_PI180 );
1304 double fX = ( fPos1 - fXRef );
1305 double fY = ( fPos2 - fYRef );
1306 double fRadius = sqrt( fX * fX + fY * fY );
1307 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MINIMUM )
1309 double fMin;
1310 GetParameter( fMin, aHandle.aRadiusRangeMinimum, false, false );
1311 if ( fRadius < fMin )
1312 fRadius = fMin;
1314 if ( aHandle.nFlags & HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM )
1316 double fMax;
1317 GetParameter( fMax, aHandle.aRadiusRangeMaximum, false, false );
1318 if ( fRadius > fMax )
1319 fRadius = fMax;
1321 if ( nFirstAdjustmentValue >= 0 )
1322 SetAdjustValueAsDouble( fRadius, nFirstAdjustmentValue );
1323 if ( nSecondAdjustmentValue >= 0 )
1324 SetAdjustValueAsDouble( fAngle, nSecondAdjustmentValue );
1326 else
1328 if ( aHandle.nFlags & HANDLE_FLAGS_REFX )
1330 nFirstAdjustmentValue = aHandle.nRefX;
1331 fPos1 *= 100000.0;
1332 fPos1 /= nCoordWidth;
1334 if ( aHandle.nFlags & HANDLE_FLAGS_REFY )
1336 nSecondAdjustmentValue = aHandle.nRefY;
1337 fPos2 *= 100000.0;
1338 fPos2 /= nCoordHeight;
1340 if ( nFirstAdjustmentValue >= 0 )
1342 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MINIMUM ) // check if horizontal handle needs to be within a range
1344 double fXMin;
1345 GetParameter( fXMin, aHandle.aXRangeMinimum, false, false );
1346 if ( fPos1 < fXMin )
1347 fPos1 = fXMin;
1349 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_X_MAXIMUM ) // check if horizontal handle needs to be within a range
1351 double fXMax;
1352 GetParameter( fXMax, aHandle.aXRangeMaximum, false, false );
1353 if ( fPos1 > fXMax )
1354 fPos1 = fXMax;
1356 SetAdjustValueAsDouble( fPos1, nFirstAdjustmentValue );
1358 if ( nSecondAdjustmentValue >= 0 )
1360 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MINIMUM ) // check if vertical handle needs to be within a range
1362 double fYMin;
1363 GetParameter( fYMin, aHandle.aYRangeMinimum, false, false );
1364 if ( fPos2 < fYMin )
1365 fPos2 = fYMin;
1367 if ( aHandle.nFlags & HANDLE_FLAGS_RANGE_Y_MAXIMUM ) // check if vertical handle needs to be within a range
1369 double fYMax;
1370 GetParameter( fYMax, aHandle.aYRangeMaximum, false, false );
1371 if ( fPos2 > fYMax )
1372 fPos2 = fYMax;
1374 SetAdjustValueAsDouble( fPos2, nSecondAdjustmentValue );
1377 // and writing them back into the GeometryItem
1378 SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)
1379 (const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1380 const OUString sAdjustmentValues( "AdjustmentValues" );
1381 com::sun::star::beans::PropertyValue aPropVal;
1382 aPropVal.Name = sAdjustmentValues;
1383 aPropVal.Value <<= seqAdjustmentValues;
1384 aGeometryItem.SetPropertyValue( aPropVal );
1385 pCustomShapeObj->SetMergedItem( aGeometryItem );
1386 bRetValue = true;
1389 return bRetValue;
1392 void EnhancedCustomShape2d::SwapStartAndEndArrow( SdrObject* pObj ) //#108274
1394 XLineStartItem aLineStart;
1395 aLineStart.SetLineStartValue(((XLineStartItem&)pObj->GetMergedItem( XATTR_LINEEND )).GetLineStartValue());
1396 XLineStartWidthItem aLineStartWidth(((XLineStartWidthItem&)pObj->GetMergedItem( XATTR_LINEENDWIDTH )).GetValue());
1397 XLineStartCenterItem aLineStartCenter(((XLineStartCenterItem&)pObj->GetMergedItem( XATTR_LINEENDCENTER )).GetValue());
1399 XLineEndItem aLineEnd;
1400 aLineEnd.SetLineEndValue(((XLineEndItem&)pObj->GetMergedItem( XATTR_LINESTART )).GetLineEndValue());
1401 XLineEndWidthItem aLineEndWidth(((XLineEndWidthItem&)pObj->GetMergedItem( XATTR_LINESTARTWIDTH )).GetValue());
1402 XLineEndCenterItem aLineEndCenter(((XLineEndCenterItem&)pObj->GetMergedItem( XATTR_LINESTARTCENTER )).GetValue());
1404 pObj->SetMergedItem( aLineStart );
1405 pObj->SetMergedItem( aLineStartWidth );
1406 pObj->SetMergedItem( aLineStartCenter );
1407 pObj->SetMergedItem( aLineEnd );
1408 pObj->SetMergedItem( aLineEndWidth );
1409 pObj->SetMergedItem( aLineEndCenter );
1412 static basegfx::B2DPolygon CreateArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, const bool bClockwise, bool bFullCircle = false )
1414 Rectangle aRect( rRect );
1415 Point aStart( rStart );
1416 Point aEnd( rEnd );
1418 sal_Int32 bSwapStartEndAngle = 0;
1420 if ( aRect.Left() > aRect.Right() )
1421 bSwapStartEndAngle ^= 0x01;
1422 if ( aRect.Top() > aRect.Bottom() )
1423 bSwapStartEndAngle ^= 0x11;
1424 if ( bSwapStartEndAngle )
1426 aRect.Justify();
1427 if ( bSwapStartEndAngle & 1 )
1429 Point aTmp( aStart );
1430 aStart = aEnd;
1431 aEnd = aTmp;
1435 Polygon aTempPoly( aRect, aStart, aEnd, POLY_ARC, bFullCircle );
1436 basegfx::B2DPolygon aRetval;
1438 if ( bClockwise )
1440 for ( sal_uInt16 j = aTempPoly.GetSize(); j--; )
1442 aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1445 else
1447 for ( sal_uInt16 j = 0; j < aTempPoly.GetSize(); j++ )
1449 aRetval.append(basegfx::B2DPoint(aTempPoly[ j ].X(), aTempPoly[ j ].Y()));
1453 return aRetval;
1456 void EnhancedCustomShape2d::CreateSubPath( sal_uInt16& rSrcPt, sal_uInt16& rSegmentInd, std::vector< SdrPathObj* >& rObjectList,
1457 const bool bLineGeometryNeededOnly,
1458 const bool bSortFilledObjectsToBack,
1459 sal_Int32 nIndex )
1461 bool bNoFill = false;
1462 bool bNoStroke = false;
1463 double dBrightness = 1.0;
1465 basegfx::B2DPolyPolygon aNewB2DPolyPolygon;
1466 basegfx::B2DPolygon aNewB2DPolygon;
1468 SetPathSize( nIndex );
1470 sal_Int32 nCoordSize = seqCoordinates.getLength();
1471 sal_Int32 nSegInfoSize = seqSegments.getLength();
1472 if ( !nSegInfoSize )
1474 const EnhancedCustomShapeParameterPair* pTmp = seqCoordinates.getArray();
1476 for ( sal_Int32 nPtNum(0L); nPtNum < nCoordSize; nPtNum++ )
1478 const Point aTempPoint(GetPoint( *pTmp++, true, true ));
1479 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1482 aNewB2DPolygon.setClosed(true);
1484 else
1486 for ( ;rSegmentInd < nSegInfoSize; )
1488 sal_Int16 nCommand = seqSegments[ rSegmentInd ].Command;
1489 sal_Int16 nPntCount= seqSegments[ rSegmentInd++ ].Count;
1491 switch ( nCommand )
1493 case NOFILL :
1494 bNoFill = true;
1495 break;
1496 case NOSTROKE :
1497 bNoStroke = true;
1498 break;
1499 case DARKEN :
1500 dBrightness = 0.66666666;
1501 break;
1502 case DARKENLESS :
1503 dBrightness = 0.83333333;
1504 break;
1505 case LIGHTEN :
1506 dBrightness = 1.16666666;
1507 break;
1508 case LIGHTENLESS :
1509 dBrightness = 1.33333333;
1510 break;
1511 case MOVETO :
1513 if(aNewB2DPolygon.count() > 1L)
1515 // #i76201# Add conversion to closed polygon when first and last points are equal
1516 basegfx::tools::checkClosed(aNewB2DPolygon);
1517 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1520 aNewB2DPolygon.clear();
1522 if ( rSrcPt < nCoordSize )
1524 const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1525 OSL_TRACE("moveTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
1526 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1529 break;
1530 case ENDSUBPATH :
1531 break;
1532 case CLOSESUBPATH :
1534 if(aNewB2DPolygon.count())
1536 if(aNewB2DPolygon.count() > 1L)
1538 aNewB2DPolygon.setClosed(true);
1539 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1542 aNewB2DPolygon.clear();
1545 break;
1546 case CURVETO :
1548 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1550 const Point aControlA(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1551 const Point aControlB(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1552 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1554 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding control point (!)");
1555 aNewB2DPolygon.appendBezierSegment(
1556 basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1557 basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1558 basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1561 break;
1563 case ANGLEELLIPSE :
1565 if ( nPntCount )
1567 if(aNewB2DPolygon.count() > 1L)
1569 // #i76201# Add conversion to closed polygon when first and last points are equal
1570 basegfx::tools::checkClosed(aNewB2DPolygon);
1571 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1573 aNewB2DPolygon.clear();
1576 case ANGLEELLIPSETO :
1578 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 2 ) < nCoordSize ); i++ )
1580 // create a circle
1581 Point _aCenter;
1582 double fWidth, fHeight;
1583 const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( mso_sptEllipse );
1584 bool bIsDefaultViewBox = false;
1585 bool bIsDefaultPath = false;
1586 bool bIsMSEllipse = false;
1588 if( ( nCoordWidth == pDefCustomShape->nCoordWidth )
1589 && ( nCoordHeight == pDefCustomShape->nCoordHeight ) )
1590 bIsDefaultViewBox = true;
1591 sal_Int32 j, nCount = pDefCustomShape->nVertices;//==3
1592 com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> seqCoordinates1, seqCoordinates2;
1594 seqCoordinates1.realloc( nCount );
1595 for ( j = 0; j < nCount; j++ )
1597 seqCoordinates1[j] = seqCoordinates[ rSrcPt + j];
1600 seqCoordinates2.realloc( nCount );
1601 for ( j = 0; j < nCount; j++ )
1603 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].First, pDefCustomShape->pVertices[ j ].nValA );
1604 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2[ j ].Second, pDefCustomShape->pVertices[ j ].nValB );
1606 if(seqCoordinates1 == seqCoordinates2)
1607 bIsDefaultPath = true;
1609 const rtl::OUString sType( "Type" );
1610 rtl::OUString sShpType;
1611 SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)pCustomShapeObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
1612 Any* pAny = rGeometryItem.GetPropertyValueByName( sType );
1613 if ( pAny )
1614 *pAny >>= sShpType;
1615 if( sShpType.getLength() > 3 &&
1616 sShpType.startsWith( "mso" )){
1617 bIsMSEllipse = true;
1619 if( (! bIsDefaultPath && ! bIsDefaultViewBox) || (bIsDefaultViewBox && bIsMSEllipse) /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1621 _aCenter = GetPoint( seqCoordinates[ rSrcPt ], true, true );
1622 GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, true, false );
1623 GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, false, true );
1624 fWidth /= 2;
1625 fHeight /= 2;
1626 }else if( bIsDefaultPath && !bIsDefaultViewBox /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1628 _aCenter.X() = nCoordWidth/2 * fXScale;
1629 _aCenter.Y() = nCoordHeight/2 * fYScale;
1630 fWidth = nCoordWidth/2;
1631 fHeight = nCoordHeight/2;
1633 const rtl::OUString sViewBox( "ViewBox" );
1634 const Any* pViewBox = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sViewBox );
1635 com::sun::star::awt::Rectangle aViewBox;
1636 if ( pViewBox && (*pViewBox >>= aViewBox ) )
1638 aViewBox.Width = pDefCustomShape->nCoordWidth;
1639 aViewBox.Height = pDefCustomShape->nCoordHeight;
1641 com::sun::star::beans::PropertyValue aPropVal;
1642 aPropVal.Name = sViewBox;
1643 aPropVal.Value <<= aViewBox;
1644 rGeometryItem.SetPropertyValue( aPropVal );
1645 pCustomShapeObj->SetMergedItem( rGeometryItem );
1646 }else{
1647 _aCenter = GetPoint( seqCoordinates[ rSrcPt ], true, true );
1648 GetParameter( fWidth, seqCoordinates[ rSrcPt + 1 ].First, true, false);
1649 GetParameter( fHeight, seqCoordinates[ rSrcPt + 1 ].Second, false, true );
1652 fWidth *= fXScale;
1653 fHeight*= fYScale;
1654 Point aP( (sal_Int32)( _aCenter.X() - fWidth ), (sal_Int32)( _aCenter.Y() - fHeight ) );
1655 Size aS( (sal_Int32)( fWidth * 2.0 ), (sal_Int32)( fHeight * 2.0 ) );
1656 Rectangle aRect( aP, aS );
1657 if ( aRect.GetWidth() && aRect.GetHeight() )
1659 double fStartAngle, fEndAngle;
1660 GetParameter( fStartAngle, seqCoordinates[ rSrcPt + 2 ].First, false, false );
1661 GetParameter( fEndAngle , seqCoordinates[ rSrcPt + 2 ].Second, false, false );
1663 if ( ((sal_Int32)fStartAngle % 360) != ((sal_Int32)fEndAngle % 360) )
1665 if ( (sal_Int32)fStartAngle & 0x7fff0000 ) // SJ: if the angle was imported from our escher import, then the
1666 fStartAngle /= 65536.0; // value is shifted by 16. TODO: already change the fixed float to a
1667 if ( (sal_Int32)fEndAngle & 0x7fff0000 ) // double in the import filter
1669 fEndAngle /= 65536.0;
1670 fEndAngle = fEndAngle + fStartAngle;
1671 if ( fEndAngle < 0 )
1672 { // in the binary filter the endangle is the amount
1673 double fTemp = fStartAngle;
1674 fStartAngle = fEndAngle;
1675 fEndAngle = fTemp;
1678 double fCenterX = aRect.Center().X();
1679 double fCenterY = aRect.Center().Y();
1680 double fx1 = ( cos( fStartAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1681 double fy1 = ( -sin( fStartAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1682 double fx2 = ( cos( fEndAngle * F_PI180 ) * 65536.0 * fXScale ) + fCenterX;
1683 double fy2 = ( -sin( fEndAngle * F_PI180 ) * 65536.0 * fYScale ) + fCenterY;
1684 aNewB2DPolygon.append(CreateArc( aRect, Point( (sal_Int32)fx1, (sal_Int32)fy1 ), Point( (sal_Int32)fx2, (sal_Int32)fy2 ), false));
1686 else
1687 { /* SJ: TODO: this block should be replaced sometimes, because the current point
1688 is not set correct, it also does not use the correct moveto
1689 point if ANGLEELLIPSETO was used, but the method CreateArc
1690 is at the moment not able to draw full circles (if startangle is 0
1691 and endangle 360 nothing is painted :-( */
1692 sal_Int32 nXControl = (sal_Int32)((double)aRect.GetWidth() * 0.2835 );
1693 sal_Int32 nYControl = (sal_Int32)((double)aRect.GetHeight() * 0.2835 );
1694 Point aCenter( aRect.Center() );
1696 // append start point
1697 aNewB2DPolygon.append(basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1699 // append four bezier segments
1700 aNewB2DPolygon.appendBezierSegment(
1701 basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Top()),
1702 basegfx::B2DPoint(aRect.Right(), aCenter.Y() - nYControl),
1703 basegfx::B2DPoint(aRect.Right(), aCenter.Y()));
1705 aNewB2DPolygon.appendBezierSegment(
1706 basegfx::B2DPoint(aRect.Right(), aCenter.Y() + nYControl),
1707 basegfx::B2DPoint(aCenter.X() + nXControl, aRect.Bottom()),
1708 basegfx::B2DPoint(aCenter.X(), aRect.Bottom()));
1710 aNewB2DPolygon.appendBezierSegment(
1711 basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Bottom()),
1712 basegfx::B2DPoint(aRect.Left(), aCenter.Y() + nYControl),
1713 basegfx::B2DPoint(aRect.Left(), aCenter.Y()));
1715 aNewB2DPolygon.appendBezierSegment(
1716 basegfx::B2DPoint(aRect.Left(), aCenter.Y() - nYControl),
1717 basegfx::B2DPoint(aCenter.X() - nXControl, aRect.Top()),
1718 basegfx::B2DPoint(aCenter.X(), aRect.Top()));
1720 // close, rescue last controlpoint, remove double last point
1721 basegfx::tools::closeWithGeometryChange(aNewB2DPolygon);
1724 rSrcPt += 3;
1727 break;
1729 case QUADRATICCURVETO :
1731 for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
1733 if ( rSrcPt )
1735 const Point aPreviousEndPoint(GetPoint( seqCoordinates[ rSrcPt - 1 ], true, true));
1736 const Point aControlQ(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1737 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1738 const Point aControlA((aPreviousEndPoint + (aControlQ * 2)) / 3);
1739 const Point aControlB(((aControlQ * 2) + aEnd) / 3);
1741 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1742 aNewB2DPolygon.appendBezierSegment(
1743 basegfx::B2DPoint(aControlA.X(), aControlA.Y()),
1744 basegfx::B2DPoint(aControlB.X(), aControlB.Y()),
1745 basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1747 else // no previous point , do a moveto
1749 rSrcPt++; // skip control point
1750 const Point aEnd(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1752 DBG_ASSERT(aNewB2DPolygon.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1753 aNewB2DPolygon.append(basegfx::B2DPoint(aEnd.X(), aEnd.Y()));
1757 break;
1759 case LINETO :
1761 for ( sal_Int32 i(0L); ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1763 const Point aTempPoint(GetPoint( seqCoordinates[ rSrcPt++ ], true, true ));
1764 OSL_TRACE("lineTo: %d,%d", aTempPoint.X(), aTempPoint.Y());
1765 aNewB2DPolygon.append(basegfx::B2DPoint(aTempPoint.X(), aTempPoint.Y()));
1768 break;
1770 case ARC :
1771 case CLOCKWISEARC :
1773 if(aNewB2DPolygon.count() > 1L)
1775 // #i76201# Add conversion to closed polygon when first and last points are equal
1776 basegfx::tools::checkClosed(aNewB2DPolygon);
1777 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1780 aNewB2DPolygon.clear();
1782 case ARCTO :
1783 case CLOCKWISEARCTO :
1785 bool bClockwise = ( nCommand == CLOCKWISEARC ) || ( nCommand == CLOCKWISEARCTO );
1786 sal_uInt32 nXor = bClockwise ? 3 : 2;
1787 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( ( rSrcPt + 3 ) < nCoordSize ); i++ )
1789 Rectangle aRect( GetPoint( seqCoordinates[ rSrcPt ], true, true ), GetPoint( seqCoordinates[ rSrcPt + 1 ], true, true ) );
1790 if ( aRect.GetWidth() && aRect.GetHeight() )
1792 Point aCenter( aRect.Center() );
1793 Point aStart( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + nXor ) ], true, true ) );
1794 Point aEnd( GetPoint( seqCoordinates[ (sal_uInt16)( rSrcPt + ( nXor ^ 1 ) ) ], true, true ) );
1795 aStart.X() = (sal_Int32)( ( (double)( aStart.X() - aCenter.X() ) ) ) + aCenter.X();
1796 aStart.Y() = (sal_Int32)( ( (double)( aStart.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1797 aEnd.X() = (sal_Int32)( ( (double)( aEnd.X() - aCenter.X() ) ) ) + aCenter.X();
1798 aEnd.Y() = (sal_Int32)( ( (double)( aEnd.Y() - aCenter.Y() ) ) ) + aCenter.Y();
1799 aNewB2DPolygon.append(CreateArc( aRect, aStart, aEnd, bClockwise));
1801 rSrcPt += 4;
1804 break;
1806 case ARCANGLETO :
1808 double fWR, fHR, fStartAngle, fSwingAngle;
1810 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt + 1 < nCoordSize ); i++ )
1812 GetParameter ( fWR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].First, true, false );
1813 GetParameter ( fHR, seqCoordinates[ (sal_uInt16)( rSrcPt ) ].Second, false, true );
1815 GetParameter ( fStartAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1) ].First, false, false );
1816 GetParameter ( fSwingAngle, seqCoordinates[ (sal_uInt16)( rSrcPt + 1 ) ].Second, false, false );
1818 fWR *= fXScale;
1819 fHR *= fYScale;
1821 fStartAngle *= F_PI180;
1822 fSwingAngle *= F_PI180;
1824 OSL_TRACE("ARCANGLETO scale: %f x %f angles: %f, %f", fWR, fHR, fStartAngle, fSwingAngle);
1826 bool bClockwise = fSwingAngle >= 0.0;
1828 if (aNewB2DPolygon.count() > 0)
1830 basegfx::B2DPoint aStartPointB2D( aNewB2DPolygon.getB2DPoint(aNewB2DPolygon.count() - 1 ) );
1831 Point aStartPoint( aStartPointB2D.getX(), aStartPointB2D.getY() );
1833 double fT = atan2((fWR*sin(fStartAngle)), (fHR*cos(fStartAngle)));
1834 double fTE = atan2((fWR*sin(fStartAngle + fSwingAngle)), fHR*cos(fStartAngle + fSwingAngle));
1836 OSL_TRACE("ARCANGLETO angles: %f, %f --> parameters: %f, %f", fStartAngle, fSwingAngle, fT, fTE );
1838 Rectangle aRect ( Point ( aStartPoint.getX() - fWR*cos(fT) - fWR, aStartPoint.getY() - fHR*sin(fT) - fHR ),
1839 Point ( aStartPoint.getX() - fWR*cos(fT) + fWR, aStartPoint.getY() - fHR*sin(fT) + fHR) );
1841 Point aEndPoint ( aStartPoint.getX() - fWR*(cos(fT) - cos(fTE)), aStartPoint.getY() - fHR*(sin(fT) - sin(fTE)) );
1843 OSL_TRACE("ARCANGLETO rect: %d, %d x %d, %d start: %d, %d end: %d, %d clockwise: %d",
1844 aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom(),
1845 aStartPoint.X(), aStartPoint.Y(), aEndPoint.X(), aEndPoint.Y(), bClockwise);
1846 aNewB2DPolygon.append(CreateArc( aRect, bClockwise ? aEndPoint : aStartPoint, bClockwise ? aStartPoint : aEndPoint, bClockwise, aStartPoint == aEndPoint && fSwingAngle > F_PI));
1849 rSrcPt += 2;
1852 break;
1854 case ELLIPTICALQUADRANTX :
1855 case ELLIPTICALQUADRANTY :
1857 bool bFirstDirection(true);
1858 basegfx::B2DPoint aControlPointA;
1859 basegfx::B2DPoint aControlPointB;
1861 for ( sal_uInt16 i = 0; ( i < nPntCount ) && ( rSrcPt < nCoordSize ); i++ )
1863 sal_uInt32 nModT = ( nCommand == ELLIPTICALQUADRANTX ) ? 1 : 0;
1864 Point aCurrent( GetPoint( seqCoordinates[ rSrcPt ], true, true ) );
1866 if ( rSrcPt ) // we need a previous point
1868 Point aPrev( GetPoint( seqCoordinates[ rSrcPt - 1 ], true, true ) );
1869 sal_Int32 nX, nY;
1870 nX = aCurrent.X() - aPrev.X();
1871 nY = aCurrent.Y() - aPrev.Y();
1872 if ( ( nY ^ nX ) & 0x80000000 )
1874 if ( !i )
1875 bFirstDirection = true;
1876 else if ( !bFirstDirection )
1877 nModT ^= 1;
1879 else
1881 if ( !i )
1882 bFirstDirection = false;
1883 else if ( bFirstDirection )
1884 nModT ^= 1;
1886 if ( nModT ) // get the right corner
1888 nX = aCurrent.X();
1889 nY = aPrev.Y();
1891 else
1893 nX = aPrev.X();
1894 nY = aCurrent.Y();
1896 sal_Int32 nXVec = ( nX - aPrev.X() ) >> 1;
1897 sal_Int32 nYVec = ( nY - aPrev.Y() ) >> 1;
1898 Point aControl1( aPrev.X() + nXVec, aPrev.Y() + nYVec );
1900 aControlPointA = basegfx::B2DPoint(aControl1.X(), aControl1.Y());
1902 nXVec = ( nX - aCurrent.X() ) >> 1;
1903 nYVec = ( nY - aCurrent.Y() ) >> 1;
1904 Point aControl2( aCurrent.X() + nXVec, aCurrent.Y() + nYVec );
1906 aControlPointB = basegfx::B2DPoint(aControl2.X(), aControl2.Y());
1908 aNewB2DPolygon.appendBezierSegment(
1909 aControlPointA,
1910 aControlPointB,
1911 basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1913 else
1915 aNewB2DPolygon.append(basegfx::B2DPoint(aCurrent.X(), aCurrent.Y()));
1918 rSrcPt++;
1921 break;
1923 #ifdef DBG_CUSTOMSHAPE
1924 case UNKNOWN :
1925 default :
1927 OStringBuffer aString("CustomShapes::unknown PolyFlagValue :");
1928 aString.append(static_cast<sal_Int32>(nCommand));
1929 OSL_FAIL(aString.getStr());
1931 break;
1932 #endif
1934 if ( nCommand == ENDSUBPATH )
1935 break;
1938 if ( rSegmentInd == nSegInfoSize )
1939 rSegmentInd++;
1941 if(aNewB2DPolygon.count() > 1L)
1943 // #i76201# Add conversion to closed polygon when first and last points are equal
1944 basegfx::tools::checkClosed(aNewB2DPolygon);
1945 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1948 if(aNewB2DPolyPolygon.count())
1950 if( !bLineGeometryNeededOnly )
1952 // hack aNewB2DPolyPolygon to fill logic rect - this is
1953 // needed to produce gradient fills that look like mso
1954 aNewB2DPolygon.clear();
1955 aNewB2DPolygon.append(basegfx::B2DPoint(0,0));
1956 aNewB2DPolygon.setClosed(true);
1957 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1959 aNewB2DPolygon.clear();
1960 aNewB2DPolygon.append(basegfx::B2DPoint(aLogicRect.GetWidth(),
1961 aLogicRect.GetHeight()));
1962 aNewB2DPolygon.setClosed(true);
1963 aNewB2DPolyPolygon.append(aNewB2DPolygon);
1966 // #i37011#
1967 bool bForceCreateTwoObjects(false);
1969 if(!bSortFilledObjectsToBack && !aNewB2DPolyPolygon.isClosed() && !bNoStroke)
1971 bForceCreateTwoObjects = true;
1974 if(bLineGeometryNeededOnly)
1976 bForceCreateTwoObjects = true;
1977 bNoFill = true;
1978 bNoStroke = false;
1981 if(bForceCreateTwoObjects || bSortFilledObjectsToBack)
1983 if(bFilled && !bNoFill)
1985 basegfx::B2DPolyPolygon aClosedPolyPolygon(aNewB2DPolyPolygon);
1986 aClosedPolyPolygon.setClosed(true);
1987 SdrPathObj* pFill = new SdrPathObj(OBJ_POLY, aClosedPolyPolygon, dBrightness);
1988 SfxItemSet aTempSet(*this);
1989 aTempSet.Put(SdrShadowItem(false));
1990 aTempSet.Put(XLineStyleItem(XLINE_NONE));
1991 pFill->SetMergedItemSet(aTempSet);
1992 rObjectList.push_back(pFill);
1995 if(!bNoStroke)
1997 // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
1998 // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
1999 // to correct the polygon (here: open it) using the type, the last edge may get lost.
2000 // Thus, use a type that fits the polygon
2001 SdrPathObj* pStroke = new SdrPathObj(
2002 aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
2003 aNewB2DPolyPolygon, dBrightness);
2004 SfxItemSet aTempSet(*this);
2005 aTempSet.Put(SdrShadowItem(false));
2006 aTempSet.Put(XFillStyleItem(XFILL_NONE));
2007 pStroke->SetMergedItemSet(aTempSet);
2008 rObjectList.push_back(pStroke);
2011 else
2013 SdrPathObj* pObj = 0;
2014 SfxItemSet aTempSet(*this);
2015 aTempSet.Put(SdrShadowItem(false));
2017 if(bNoFill)
2019 // see comment above about OBJ_PLIN
2020 pObj = new SdrPathObj(
2021 aNewB2DPolyPolygon.isClosed() ? OBJ_POLY : OBJ_PLIN,
2022 aNewB2DPolyPolygon, dBrightness);
2023 aTempSet.Put(XFillStyleItem(XFILL_NONE));
2025 else
2027 aNewB2DPolyPolygon.setClosed(true);
2028 pObj = new SdrPathObj(OBJ_POLY, aNewB2DPolyPolygon, dBrightness);
2031 if(bNoStroke)
2033 aTempSet.Put(XLineStyleItem(XLINE_NONE));
2036 if(pObj)
2038 pObj->SetMergedItemSet(aTempSet);
2039 rObjectList.push_back(pObj);
2045 void CorrectCalloutArrows( MSO_SPT eSpType, sal_uInt32 nLineObjectCount, std::vector< SdrPathObj* >& vObjectList )
2047 bool bAccent = false;
2048 switch( eSpType )
2050 case mso_sptCallout1 :
2051 case mso_sptBorderCallout1 :
2052 case mso_sptCallout90 :
2053 case mso_sptBorderCallout90 :
2054 default:
2055 break;
2057 case mso_sptAccentCallout1 :
2058 case mso_sptAccentBorderCallout1 :
2059 case mso_sptAccentCallout90 :
2060 case mso_sptAccentBorderCallout90 :
2062 sal_uInt32 i, nLine = 0;
2063 for ( i = 0; i < vObjectList.size(); i++ )
2065 SdrPathObj* pObj( vObjectList[ i ] );
2066 if(pObj->IsLine())
2068 nLine++;
2069 if ( nLine == nLineObjectCount )
2071 pObj->ClearMergedItem( XATTR_LINESTART );
2072 pObj->ClearMergedItem( XATTR_LINEEND );
2077 break;
2079 // switch start & end
2080 case mso_sptAccentCallout2 :
2081 case mso_sptAccentBorderCallout2 :
2082 bAccent = true;
2083 case mso_sptCallout2 :
2084 case mso_sptBorderCallout2 :
2086 sal_uInt32 i, nLine = 0;
2087 for ( i = 0; i < vObjectList.size(); i++ )
2089 SdrPathObj* pObj( vObjectList[ i ] );
2090 if(pObj->IsLine())
2092 nLine++;
2093 if ( nLine == 1 )
2094 pObj->ClearMergedItem( XATTR_LINEEND );
2095 else if ( ( bAccent && ( nLine == nLineObjectCount - 1 ) ) || ( !bAccent && ( nLine == nLineObjectCount ) ) )
2096 pObj->ClearMergedItem( XATTR_LINESTART );
2097 else
2099 pObj->ClearMergedItem( XATTR_LINESTART );
2100 pObj->ClearMergedItem( XATTR_LINEEND );
2105 break;
2107 case mso_sptAccentCallout3 :
2108 case mso_sptAccentBorderCallout3 :
2109 bAccent = false;
2110 case mso_sptCallout3 :
2111 case mso_sptBorderCallout3 :
2113 sal_uInt32 i, nLine = 0;
2114 for ( i = 0; i < vObjectList.size(); i++ )
2116 SdrPathObj* pObj( vObjectList[ i ] );
2117 if(pObj->IsLine())
2119 if ( nLine )
2121 pObj->ClearMergedItem( XATTR_LINESTART );
2122 pObj->ClearMergedItem( XATTR_LINEEND );
2124 else
2125 EnhancedCustomShape2d::SwapStartAndEndArrow( pObj );
2127 nLine++;
2131 break;
2135 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj& rObj, const SfxItemSet& rCustomShapeSet,
2136 sal_uInt32& nColorIndex, sal_uInt32 nColorCount)
2138 if ( !rObj.IsLine() )
2140 const XFillStyle eFillStyle = ((const XFillStyleItem&)rObj.GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2141 switch( eFillStyle )
2143 default:
2144 case XFILL_SOLID:
2146 Color aFillColor;
2147 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2149 aFillColor = GetColorData(
2150 ((XFillColorItem&)rCustomShapeSet.Get( XATTR_FILLCOLOR )).GetColorValue(),
2151 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() );
2152 rObj.SetMergedItem( XFillColorItem( "", aFillColor ) );
2154 break;
2156 case XFILL_GRADIENT:
2158 XGradient aXGradient(((const XFillGradientItem&)rObj.GetMergedItem(XATTR_FILLGRADIENT)).GetGradientValue());
2159 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2161 aXGradient.SetStartColor(
2162 GetColorData(
2163 aXGradient.GetStartColor(),
2164 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2165 aXGradient.SetEndColor(
2166 GetColorData(
2167 aXGradient.GetEndColor(),
2168 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2171 rObj.SetMergedItem( XFillGradientItem( "", aXGradient ) );
2172 break;
2174 case XFILL_HATCH:
2176 XHatch aXHatch(((const XFillHatchItem&)rObj.GetMergedItem(XATTR_FILLHATCH)).GetHatchValue());
2177 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2179 aXHatch.SetColor(
2180 GetColorData(
2181 aXHatch.GetColor(),
2182 std::min(nColorIndex, nColorCount-1), rObj.GetBrightness() ));
2185 rObj.SetMergedItem( XFillHatchItem( "", aXHatch ) );
2186 break;
2188 case XFILL_BITMAP:
2190 if ( nColorCount || rObj.GetBrightness() != 1.0 )
2192 Bitmap aBitmap(((const XFillBitmapItem&)rObj.GetMergedItem(XATTR_FILLBITMAP)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2194 aBitmap.Adjust(
2195 static_cast< short > ( GetLuminanceChange(
2196 std::min(nColorIndex, nColorCount-1))));
2198 rObj.SetMergedItem(XFillBitmapItem(OUString(), Graphic(aBitmap)));
2201 break;
2205 if ( nColorIndex < nColorCount )
2206 nColorIndex++;
2210 SdrObject* EnhancedCustomShape2d::CreatePathObj( bool bLineGeometryNeededOnly )
2212 sal_Int32 nCoordSize = seqCoordinates.getLength();
2213 if ( !nCoordSize )
2214 return NULL;
2216 sal_uInt16 nSrcPt = 0;
2217 sal_uInt16 nSegmentInd = 0;
2219 std::vector< SdrPathObj* > vObjectList;
2220 bool bSortFilledObjectsToBack = SortFilledObjectsToBackByDefault( eSpType );
2222 sal_Int32 nSubPathIndex = 0;
2224 while( nSegmentInd <= seqSegments.getLength() )
2226 CreateSubPath( nSrcPt, nSegmentInd, vObjectList, bLineGeometryNeededOnly, bSortFilledObjectsToBack, nSubPathIndex );
2227 nSubPathIndex ++;
2230 SdrObject* pRet = NULL;
2231 sal_uInt32 i;
2233 if ( !vObjectList.empty() )
2235 const SfxItemSet& rCustomShapeSet = pCustomShapeObj->GetMergedItemSet();
2236 sal_uInt32 nColorCount = nColorData >> 28;
2237 sal_uInt32 nColorIndex = 0;
2239 // #i37011# remove invisible objects
2240 if(!vObjectList.empty())
2242 std::vector< SdrPathObj* > vTempList;
2244 for(i = 0L; i < vObjectList.size(); i++)
2246 SdrPathObj* pObj(vObjectList[i]);
2247 const XLineStyle eLineStyle = ((const XLineStyleItem&)pObj->GetMergedItem(XATTR_LINESTYLE)).GetValue();
2248 const XFillStyle eFillStyle = ((const XFillStyleItem&)pObj->GetMergedItem(XATTR_FILLSTYLE)).GetValue();
2250 //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2251 if( !bLineGeometryNeededOnly && ( XLINE_NONE == eLineStyle ) && ( XFILL_NONE == eFillStyle ) )
2252 delete pObj;
2253 else
2254 vTempList.push_back(pObj);
2257 vObjectList = vTempList;
2260 if(1L == vObjectList.size())
2262 // a single object, correct some values
2263 AdaptObjColor(*vObjectList[0L],rCustomShapeSet,nColorIndex,nColorCount);
2265 else
2267 sal_Int32 nLineObjectCount = 0;
2268 sal_Int32 nAreaObjectCount = 0;
2270 // correct some values and collect content data
2271 for ( i = 0; i < vObjectList.size(); i++ )
2273 SdrPathObj* pObj( vObjectList[ i ] );
2275 if(pObj->IsLine())
2277 nLineObjectCount++;
2279 else
2281 nAreaObjectCount++;
2282 AdaptObjColor(*pObj,rCustomShapeSet,nColorIndex,nColorCount);
2286 // #i88870# correct line arrows for callouts
2287 if ( nLineObjectCount )
2288 CorrectCalloutArrows( eSpType, nLineObjectCount, vObjectList );
2290 // sort objects so that filled ones are in front. Necessary
2291 // for some strange objects
2292 if ( bSortFilledObjectsToBack )
2294 std::vector< SdrPathObj* > vTempList;
2296 for ( i = 0; i < vObjectList.size(); i++ )
2298 SdrPathObj* pObj( vObjectList[ i ] );
2300 if ( !pObj->IsLine() )
2302 vTempList.push_back(pObj);
2306 for ( i = 0; i < vObjectList.size(); i++ )
2308 SdrPathObj* pObj( vObjectList[ i ] );
2310 if ( pObj->IsLine() )
2312 vTempList.push_back(pObj);
2316 vObjectList = vTempList;
2321 // #i37011#
2322 if(!vObjectList.empty())
2324 // copy remaining objects to pRet
2325 if(vObjectList.size() > 1L)
2327 pRet = new SdrObjGroup;
2329 for (i = 0L; i < vObjectList.size(); i++)
2331 SdrObject* pObj(vObjectList[i]);
2332 pRet->GetSubList()->NbcInsertObject(pObj);
2335 else if(1L == vObjectList.size())
2337 pRet = vObjectList[0L];
2340 if(pRet)
2342 // move to target position
2343 Rectangle aCurRect(pRet->GetSnapRect());
2344 aCurRect.Move(aLogicRect.Left(), aLogicRect.Top());
2345 pRet->NbcSetSnapRect(aCurRect);
2349 return pRet;
2352 SdrObject* EnhancedCustomShape2d::CreateObject( bool bLineGeometryNeededOnly )
2354 SdrObject* pRet = NULL;
2356 if ( eSpType == mso_sptRectangle )
2358 pRet = new SdrRectObj( aLogicRect );
2359 pRet->SetMergedItemSet( *this );
2361 if ( !pRet )
2362 pRet = CreatePathObj( bLineGeometryNeededOnly );
2364 return pRet;
2367 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject* pObj )
2369 if ( pObj && seqGluePoints.getLength() )
2371 sal_uInt32 i, nCount = seqGluePoints.getLength();
2372 for ( i = 0; i < nCount; i++ )
2374 SdrGluePoint aGluePoint;
2376 aGluePoint.SetPos( GetPoint( seqGluePoints[ i ], true, true ) );
2377 aGluePoint.SetPercent( false );
2378 aGluePoint.SetAlign( SDRVERTALIGN_TOP | SDRHORZALIGN_LEFT );
2379 aGluePoint.SetEscDir( SDRESC_SMART );
2380 SdrGluePointList* pList = pObj->ForceGluePointList();
2381 if( pList )
2382 /* sal_uInt16 nId = */ pList->Insert( aGluePoint );
2387 bool EnhancedCustomShape2d::IsPostRotate() const
2389 return pCustomShapeObj->ISA( SdrObjCustomShape ) && ((SdrObjCustomShape*)pCustomShapeObj)->IsPostRotate();
2392 SdrObject* EnhancedCustomShape2d::CreateLineGeometry()
2394 return CreateObject( true );
2398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */