1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
56 #include <basegfx/polygon/b2dpolygontools.hxx>
57 #include <rtl/strbuf.hxx>
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
;
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
)
83 bool b1Special
= ( nFlags
& 0x2000 ) != 0;
84 bool b2Special
= ( nFlags
& 0x4000 ) != 0;
85 bool b3Special
= ( nFlags
& 0x8000 ) != 0;
86 switch( nFlags
& 0xff )
91 sal_Int32 nOptimize
= 0;
107 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
112 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
116 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
117 aEquation
+= OUString( (sal_Unicode
)'+' );
118 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
122 if ( b3Special
|| nP3
)
124 aEquation
+= OUString( (sal_Unicode
)'-' );
125 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
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
);
147 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
149 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
156 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
163 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
165 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
172 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
174 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
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
)')' );
191 aEquation
+= "sqrt(";
192 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
194 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
196 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
198 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
200 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
202 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
203 aEquation
+= OUString( (sal_Unicode
)')' );
208 aEquation
+= "atan2(";
209 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
211 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
212 aEquation
+= ")/(pi/180)";
217 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
218 aEquation
+= "*sin(";
219 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
220 aEquation
+= "*(pi/180))";
225 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
226 aEquation
+= "*cos(";
227 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
228 aEquation
+= "*(pi/180))";
233 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
234 aEquation
+= "*cos(atan2(";
235 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
237 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
243 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
244 aEquation
+= "*sin(atan2(";
245 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
247 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
253 aEquation
+= "sqrt(";
254 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
260 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
261 aEquation
+= "*sqrt(1-(";
262 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
264 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
267 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
269 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
275 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
276 aEquation
+= "*tan(";
277 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP2
, b2Special
);
283 aEquation
+= "sqrt(";
284 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
286 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP3
, b3Special
);
288 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
290 EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( aEquation
, nP1
, b1Special
);
291 aEquation
+= OUString( (sal_Unicode
)')' );
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";
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";
324 void EnhancedCustomShape2d::AppendEnhancedCustomShapeEquationParameter( OUString
& rParameter
, const sal_Int32 nPara
, const bool bIsSpecialValue
)
326 if ( bIsSpecialValue
)
331 rParameter
+= OUString::valueOf( (sal_Int32
)( nPara
& 0xff ) );
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
:
350 rParameter
+= OUString::valueOf( (sal_Int32
)( nPara
- DFF_Prop_adjustValue
) );
354 case DFF_Prop_geoLeft
:
356 rParameter
+= "left";
359 case DFF_Prop_geoTop
:
364 case DFF_Prop_geoRight
:
366 rParameter
+= "right";
369 case DFF_Prop_geoBottom
:
371 rParameter
+= "bottom";
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 ) )
396 rParameter
.Type
= EnhancedCustomShapeParameterType::EQUATION
;
398 else if ( nPara
== 0 )
402 rParameter
.Type
= EnhancedCustomShapeParameterType::LEFT
;
404 rParameter
.Type
= EnhancedCustomShapeParameterType::TOP
;
406 else if ( nPara
== 1 )
410 rParameter
.Type
= EnhancedCustomShapeParameterType::RIGHT
;
412 rParameter
.Type
= EnhancedCustomShapeParameterType::BOTTOM
;
414 else if ( nPara
== 2 ) // means to be centered, but should not be
415 { // used in our implementation
417 rParameter
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
422 rParameter
.Type
= EnhancedCustomShapeParameterType::NORMAL
;
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();
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
)
467 else if ( rPropVal
.Name
== sMirroredX
)
469 sal_Bool bMirroredX
= sal_Bool();
470 if ( rPropVal
.Value
>>= 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
)
482 rDestinationHandle
.nFlags
|= HANDLE_FLAGS_MIRRORED_Y
;
485 else if ( rPropVal
.Name
== sSwitched
)
487 sal_Bool bSwitched
= sal_Bool();
488 if ( rPropVal
.Value
>>= 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
;
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
);
567 *pAny
>>= seqAdjustmentValues
;
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
);
590 *pAny
>>= seqCoordinates
;
592 /////////////////////
593 // Path/GluePoints //
594 /////////////////////
595 const OUString
sGluePoints( "GluePoints" );
596 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, sGluePoints
);
598 *pAny
>>= seqGluePoints
;
603 const OUString
sSegments( "Segments" );
604 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, sSegments
);
606 *pAny
>>= seqSegments
;
608 //////////////////////
609 // Path/SubViewSize //
610 //////////////////////
611 const OUString
sSubViewSize( "SubViewSize" );
612 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, sSubViewSize
);
614 *pAny
>>= seqSubViewSize
;
619 const OUString
sStretchX( "StretchX" );
620 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, sStretchX
);
623 sal_Int32 nStretchX
= 0;
624 if ( *pAny
>>= nStretchX
)
631 const OUString
sStretchY( "StretchY" );
632 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, sStretchY
);
635 sal_Int32 nStretchY
= 0;
636 if ( *pAny
>>= nStretchY
)
640 /////////////////////
641 // Path/TextFrames //
642 /////////////////////
643 const OUString
sTextFrames( "TextFrames" );
644 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, sTextFrames
);
646 *pAny
>>= seqTextFrames
;
651 const OUString
sEquations( "Equations" );
652 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sEquations
);
654 *pAny
>>= seqEquations
;
659 const OUString
sHandles( "Handles" );
660 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sHandles
);
662 *pAny
>>= seqHandles
;
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
;
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
;
694 OSL_TRACE("ooxml shape, path width: %d height: %d", nCoordWidth
, nCoordHeight
);
695 if ( nCoordWidth
== 0 )
697 if ( nCoordHeight
== 0 )
700 if ( (sal_uInt32
)nXRef
!= 0x80000000 && aLogicRect
.GetHeight() )
702 fXRatio
= (double)aLogicRect
.GetWidth() / (double)aLogicRect
.GetHeight();
710 if ( (sal_uInt32
)nYRef
!= 0x80000000 && aLogicRect
.GetWidth() )
712 fYRatio
= (double)aLogicRect
.GetHeight() / (double)aLogicRect
.GetWidth();
722 EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject
* pAObj
) :
723 SfxItemSet ( pAObj
->GetMergedItemSet() ),
724 pCustomShapeObj ( pAObj
),
725 eSpType ( mso_sptNil
),
728 nCoordWidthG ( 21600 ),
729 nCoordHeightG ( 21600 ),
730 bOOXMLShape ( sal_False
),
731 nXRef ( 0x80000000 ),
732 nYRef ( 0x80000000 ),
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
),
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
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" );
768 SdrCustomShapeGeometryItem
& rGeometryItem
= (SdrCustomShapeGeometryItem
&)(const SdrCustomShapeGeometryItem
&)pCustomShapeObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
);
769 Any
* pAny
= rGeometryItem
.GetPropertyValueByName( sType
);
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
);
780 pAny
= rGeometryItem
.GetPropertyValueByName( sMirroredY
);
784 if ( pCustomShapeObj
->ISA( SdrObjCustomShape
) ) // should always be a SdrObjCustomShape, but you don't know
785 nRotateAngle
= (sal_Int32
)(((SdrObjCustomShape
*)pCustomShapeObj
)->GetObjectRotation() * 100.0);
787 nRotateAngle
= pCustomShapeObj
->GetRotateAngle();
789 /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem
);
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;
813 if( sShapeType
.getLength() > 4 &&
814 sShapeType
.match( "col-" ))
816 nColorData
= sShapeType
.copy( 4 ).toInt32( 16 );
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;
836 sal_Int32 i
, nLength
= seqEquations
.getLength();
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
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;
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
;
887 sal_Int32 nNumber
= 0;
888 seqAdjustmentValues
[ nIndex
].Value
>>= nNumber
;
889 fNumber
= (double)nNumber
;
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;
900 if ( nIndex
< (sal_Int32
)vNodesSharedPtr
.size() )
902 if ( vNodesSharedPtr
[ nIndex
].get() ) {
903 #if OSL_DEBUG_LEVEL > 1
908 if ( vEquationResults
[ nIndex
].bReady
)
909 fNumber
= vEquationResults
[ nIndex
].fValue
;
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
) )
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);
929 OSL_TRACE("error: EnhancedCustomShape2d::GetEquationValueAsDouble failed");
931 #if OSL_DEBUG_LEVEL > 1
935 OSL_TRACE(" ?%d --> %f (angle: %f)", nIndex
,
936 fNumber
, 180.0*fNumber
/10800000.0);
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
)
949 seqAdjustmentValues
[ nIndex
].Value
>>= fNumber
;
950 nNumber
= (sal_Int32
)fNumber
;
953 seqAdjustmentValues
[ nIndex
].Value
>>= 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
;
970 Point
EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair
& rPair
,
971 const bool bScale
, const bool bReplaceGeoSize
) const
974 bool bExchange
= ( nFlags
& DFF_CUSTOMSHAPE_EXCH
) != 0; // x <-> y
975 sal_uInt32 nPass
= 0;
978 sal_uInt32 nIndex
= nPass
;
984 const EnhancedCustomShapeParameter
& rParameter
= nIndex
? rPair
.Second
: rPair
.First
;
985 if ( nPass
) // height
987 GetParameter( fVal
, rParameter
, false, bReplaceGeoSize
);
993 if ( nFlags
& DFF_CUSTOMSHAPE_FLIP_V
)
994 fVal
= aLogicRect
.GetHeight() - fVal
;
996 aRetValue
.Y() = (sal_Int32
)fVal
;
1000 GetParameter( fVal
, rParameter
, bReplaceGeoSize
, false );
1006 if ( nFlags
& DFF_CUSTOMSHAPE_FLIP_H
)
1007 fVal
= aLogicRect
.GetWidth() - fVal
;
1009 aRetValue
.X() = (sal_Int32
)fVal
;
1012 while ( ++nPass
< 2 );
1016 bool EnhancedCustomShape2d::GetParameter( double& rRetValue
, const EnhancedCustomShapeParameter
& rParameter
,
1017 const bool bReplaceGeoWidth
, const bool bReplaceGeoHeight
) const
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
);
1033 case EnhancedCustomShapeParameterType::EQUATION
:
1035 sal_Int32 nEquationIndex
= 0;
1036 if ( rParameter
.Value
>>= nEquationIndex
)
1038 rRetValue
= GetEquationValueAsDouble( nEquationIndex
);
1043 case EnhancedCustomShapeParameterType::NORMAL
:
1045 if ( rParameter
.Value
.getValueTypeClass() == TypeClass_DOUBLE
)
1048 if ( rParameter
.Value
>>= fValue
)
1056 sal_Int32 nValue
= 0;
1057 if ( rParameter
.Value
>>= nValue
)
1061 if ( bReplaceGeoWidth
&& ( nValue
== nCoordWidth
) )
1062 rRetValue
*= fXRatio
;
1063 else if ( bReplaceGeoHeight
&& ( nValue
== nCoordHeight
) )
1064 rRetValue
*= fYRatio
;
1069 case EnhancedCustomShapeParameterType::LEFT
:
1075 case EnhancedCustomShapeParameterType::TOP
:
1081 case EnhancedCustomShapeParameterType::RIGHT
:
1083 rRetValue
= nCoordWidth
;
1087 case EnhancedCustomShapeParameterType::BOTTOM
:
1089 rRetValue
= nCoordHeight
;
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;
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 )
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));
1126 if( nLuminance
> 0 )
1129 aHSVColor
.getGreen() * (1.0-nLuminance
/100.0));
1132 (1.0-nLuminance
/100.0)*aHSVColor
.getBlue());
1134 else if( nLuminance
< 0 )
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();
1153 if ( bTextFlow
&& ( nSize
> 1 ) )
1155 Point
aTopLeft( GetPoint( seqTextFrames
[ nIndex
].TopLeft
, !bOOXMLShape
, true ) );
1156 Point
aBottomRight( GetPoint( seqTextFrames
[ nIndex
].BottomRight
, !bOOXMLShape
, true ) );
1159 aTopLeft
.X() = aLogicRect
.GetWidth() - aTopLeft
.X();
1160 aBottomRight
.X() = aLogicRect
.GetWidth() - aBottomRight
.X();
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 )
1171 aRect
.Move( aLogicRect
.Left(), aLogicRect
.Top() );
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() )
1187 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles
[ nIndex
], aHandle
) )
1189 if ( aHandle
.nFlags
& HANDLE_FLAGS_POLAR
)
1191 Point
aReferencePoint( GetPoint( aHandle
.aPolar
, true, false ) );
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
);
1204 Round( fX
+ aReferencePoint
.X() ),
1205 basegfx::fTools::equalZero(fXScale
) ? aReferencePoint
.Y() :
1206 Round( ( fY
* fYScale
) / fXScale
+ aReferencePoint
.Y() ) );
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
))
1228 ShearPoint( rReturnPosition
, Point( aLogicRect
.GetWidth() / 2, aLogicRect
.GetHeight() / 2 ), nTan
);
1232 double a
= nRotateAngle
* F_PI18000
;
1233 RotatePoint( rReturnPosition
, Point( aLogicRect
.GetWidth() / 2, aLogicRect
.GetHeight() / 2 ), sin( a
), cos( a
) );
1236 rReturnPosition
.X() = aLogicRect
.GetWidth() - rReturnPosition
.X();
1238 rReturnPosition
.Y() = aLogicRect
.GetHeight() - rReturnPosition
.Y();
1239 rReturnPosition
.Move( aLogicRect
.Left(), aLogicRect
.Top() );
1246 bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex
, const com::sun::star::awt::Point
& rPosition
)
1248 bool bRetValue
= false;
1249 if ( nIndex
< GetHdlCount() )
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() );
1259 aP
.X() = aLogicRect
.GetWidth() - aP
.X();
1261 aP
.Y() = aLogicRect
.GetHeight() - aP
.Y();
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
))
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();
1281 if ( aHandle
.nFlags
& HANDLE_FLAGS_SWITCHED
)
1283 if ( aLogicRect
.GetHeight() > aLogicRect
.GetWidth() )
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
)
1312 GetParameter( fMin
, aHandle
.aRadiusRangeMinimum
, false, false );
1313 if ( fRadius
< fMin
)
1316 if ( aHandle
.nFlags
& HANDLE_FLAGS_RADIUS_RANGE_MAXIMUM
)
1319 GetParameter( fMax
, aHandle
.aRadiusRangeMaximum
, false, false );
1320 if ( fRadius
> fMax
)
1323 if ( nFirstAdjustmentValue
>= 0 )
1324 SetAdjustValueAsDouble( fRadius
, nFirstAdjustmentValue
);
1325 if ( nSecondAdjustmentValue
>= 0 )
1326 SetAdjustValueAsDouble( fAngle
, nSecondAdjustmentValue
);
1330 if ( aHandle
.nFlags
& HANDLE_FLAGS_REFX
)
1332 nFirstAdjustmentValue
= aHandle
.nRefX
;
1334 fPos1
/= nCoordWidth
;
1336 if ( aHandle
.nFlags
& HANDLE_FLAGS_REFY
)
1338 nSecondAdjustmentValue
= aHandle
.nRefY
;
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
1347 GetParameter( fXMin
, aHandle
.aXRangeMinimum
, false, false );
1348 if ( fPos1
< fXMin
)
1351 if ( aHandle
.nFlags
& HANDLE_FLAGS_RANGE_X_MAXIMUM
) // check if horizontal handle needs to be within a range
1354 GetParameter( fXMax
, aHandle
.aXRangeMaximum
, false, false );
1355 if ( 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
1365 GetParameter( fYMin
, aHandle
.aYRangeMinimum
, false, false );
1366 if ( fPos2
< fYMin
)
1369 if ( aHandle
.nFlags
& HANDLE_FLAGS_RANGE_Y_MAXIMUM
) // check if vertical handle needs to be within a range
1372 GetParameter( fYMax
, aHandle
.aYRangeMaximum
, false, false );
1373 if ( 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
);
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
);
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
)
1429 if ( bSwapStartEndAngle
& 1 )
1431 Point
aTmp( aStart
);
1437 Polygon
aTempPoly( aRect
, aStart
, aEnd
, POLY_ARC
, bFullCircle
);
1438 basegfx::B2DPolygon aRetval
;
1442 for ( sal_uInt16 j
= aTempPoly
.GetSize(); j
--; )
1444 aRetval
.append(basegfx::B2DPoint(aTempPoly
[ j
].X(), aTempPoly
[ j
].Y()));
1449 for ( sal_uInt16 j
= 0; j
< aTempPoly
.GetSize(); j
++ )
1451 aRetval
.append(basegfx::B2DPoint(aTempPoly
[ j
].X(), aTempPoly
[ j
].Y()));
1458 void EnhancedCustomShape2d::CreateSubPath( sal_uInt16
& rSrcPt
, sal_uInt16
& rSegmentInd
, std::vector
< SdrPathObj
* >& rObjectList
,
1459 const sal_Bool bLineGeometryNeededOnly
,
1460 const sal_Bool bSortFilledObjectsToBack
,
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);
1488 for ( ;rSegmentInd
< nSegInfoSize
; )
1490 sal_Int16 nCommand
= seqSegments
[ rSegmentInd
].Command
;
1491 sal_Int16 nPntCount
= seqSegments
[ rSegmentInd
++ ].Count
;
1502 dBrightness
= 0.66666666;
1505 dBrightness
= 0.83333333;
1508 dBrightness
= 1.16666666;
1511 dBrightness
= 1.33333333;
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()));
1536 if(aNewB2DPolygon
.count())
1538 if(aNewB2DPolygon
.count() > 1L)
1540 aNewB2DPolygon
.setClosed(true);
1541 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1544 aNewB2DPolygon
.clear();
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()));
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
++ )
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
);
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 );
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
);
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 );
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
;
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
));
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
);
1731 case QUADRATICCURVETO
:
1733 for ( sal_Int32
i(0L); ( i
< nPntCount
) && ( rSrcPt
+ 1 < nCoordSize
); i
++ )
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()));
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()));
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();
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
));
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 );
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
));
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 ) );
1872 nX
= aCurrent
.X() - aPrev
.X();
1873 nY
= aCurrent
.Y() - aPrev
.Y();
1874 if ( ( nY
^ nX
) & 0x80000000 )
1877 bFirstDirection
= true;
1878 else if ( !bFirstDirection
)
1884 bFirstDirection
= false;
1885 else if ( bFirstDirection
)
1888 if ( nModT
) // get the right corner
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(
1913 basegfx::B2DPoint(aCurrent
.X(), aCurrent
.Y()));
1917 aNewB2DPolygon
.append(basegfx::B2DPoint(aCurrent
.X(), aCurrent
.Y()));
1925 #ifdef DBG_CUSTOMSHAPE
1929 OStringBuffer
aString("CustomShapes::unknown PolyFlagValue :");
1930 aString
.append(static_cast<sal_Int32
>(nCommand
));
1931 OSL_FAIL(aString
.getStr());
1936 if ( nCommand
== ENDSUBPATH
)
1940 if ( rSegmentInd
== nSegInfoSize
)
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
);
1969 bool bForceCreateTwoObjects(false);
1971 if(!bSortFilledObjectsToBack
&& !aNewB2DPolyPolygon
.isClosed() && !bNoStroke
)
1973 bForceCreateTwoObjects
= true;
1976 if(bLineGeometryNeededOnly
)
1978 bForceCreateTwoObjects
= true;
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
);
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
);
2015 SdrPathObj
* pObj
= 0;
2016 SfxItemSet
aTempSet(*this);
2017 aTempSet
.Put(SdrShadowItem(sal_False
));
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
));
2029 aNewB2DPolyPolygon
.setClosed(true);
2030 pObj
= new SdrPathObj(OBJ_POLY
, aNewB2DPolyPolygon
, dBrightness
);
2035 aTempSet
.Put(XLineStyleItem(XLINE_NONE
));
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;
2052 case mso_sptCallout1
:
2053 case mso_sptBorderCallout1
:
2054 case mso_sptCallout90
:
2055 case mso_sptBorderCallout90
:
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
] );
2071 if ( nLine
== nLineObjectCount
)
2073 pObj
->ClearMergedItem( XATTR_LINESTART
);
2074 pObj
->ClearMergedItem( XATTR_LINEEND
);
2081 // switch start & end
2082 case mso_sptAccentCallout2
:
2083 case mso_sptAccentBorderCallout2
:
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
] );
2096 pObj
->ClearMergedItem( XATTR_LINEEND
);
2097 else if ( ( bAccent
&& ( nLine
== nLineObjectCount
- 1 ) ) || ( !bAccent
&& ( nLine
== nLineObjectCount
) ) )
2098 pObj
->ClearMergedItem( XATTR_LINESTART
);
2101 pObj
->ClearMergedItem( XATTR_LINESTART
);
2102 pObj
->ClearMergedItem( XATTR_LINEEND
);
2109 case mso_sptAccentCallout3
:
2110 case mso_sptAccentBorderCallout3
:
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
] );
2123 pObj
->ClearMergedItem( XATTR_LINESTART
);
2124 pObj
->ClearMergedItem( XATTR_LINEEND
);
2127 EnhancedCustomShape2d::SwapStartAndEndArrow( pObj
);
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
)
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
) );
2158 case XFILL_GRADIENT
:
2160 XGradient
aXGradient(((const XFillGradientItem
&)rObj
.GetMergedItem(XATTR_FILLGRADIENT
)).GetGradientValue());
2161 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2163 aXGradient
.SetStartColor(
2165 aXGradient
.GetStartColor(),
2166 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() ));
2167 aXGradient
.SetEndColor(
2169 aXGradient
.GetEndColor(),
2170 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() ));
2173 rObj
.SetMergedItem( XFillGradientItem( String(), aXGradient
) );
2178 XHatch
aXHatch(((const XFillHatchItem
&)rObj
.GetMergedItem(XATTR_FILLHATCH
)).GetHatchValue());
2179 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2184 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() ));
2187 rObj
.SetMergedItem( XFillHatchItem( String(), aXHatch
) );
2192 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2194 Bitmap
aBitmap(((const XFillBitmapItem
&)rObj
.GetMergedItem(XATTR_FILLBITMAP
)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2197 static_cast< short > ( GetLuminanceChange(
2198 std::min(nColorIndex
, nColorCount
-1))));
2200 rObj
.SetMergedItem(XFillBitmapItem(String(), Graphic(aBitmap
)));
2207 if ( nColorIndex
< nColorCount
)
2212 SdrObject
* EnhancedCustomShape2d::CreatePathObj( sal_Bool bLineGeometryNeededOnly
)
2214 sal_Int32 nCoordSize
= seqCoordinates
.getLength();
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
);
2232 SdrObject
* pRet
= NULL
;
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
) )
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
);
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
] );
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
;
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];
2344 // move to target position
2345 Rectangle
aCurRect(pRet
->GetSnapRect());
2346 aCurRect
.Move(aLogicRect
.Left(), aLogicRect
.Top());
2347 pRet
->NbcSetSnapRect(aCurRect
);
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 );
2364 pRet
= CreatePathObj( bLineGeometryNeededOnly
);
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();
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: */