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>
54 #include <basegfx/polygon/b2dpolygontools.hxx>
55 #include <basegfx/matrix/b2dhommatrixtools.hxx>
56 #include <rtl/strbuf.hxx>
59 using namespace ::com::sun::star
;
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::number( ( 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::number( ( 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::number( ( 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
= HandleFlags::NONE
;
442 for ( i
= 0; i
< nProperties
; i
++ )
444 const com::sun::star::beans::PropertyValue
& rPropVal
= rHandleProperties
[ i
];
446 if ( rPropVal
.Name
== "Position" )
448 if ( rPropVal
.Value
>>= rDestinationHandle
.aPosition
)
451 else if ( rPropVal
.Name
== "MirroredX" )
454 if ( rPropVal
.Value
>>= bMirroredX
)
457 rDestinationHandle
.nFlags
|= HandleFlags::MIRRORED_X
;
460 else if ( rPropVal
.Name
== "MirroredY" )
463 if ( rPropVal
.Value
>>= bMirroredY
)
466 rDestinationHandle
.nFlags
|= HandleFlags::MIRRORED_Y
;
469 else if ( rPropVal
.Name
== "Switched" )
472 if ( rPropVal
.Value
>>= bSwitched
)
475 rDestinationHandle
.nFlags
|= HandleFlags::SWITCHED
;
478 else if ( rPropVal
.Name
== "Polar" )
480 if ( rPropVal
.Value
>>= rDestinationHandle
.aPolar
)
481 rDestinationHandle
.nFlags
|= HandleFlags::POLAR
;
483 else if ( rPropVal
.Name
== "RefX" )
485 if ( rPropVal
.Value
>>= rDestinationHandle
.nRefX
)
486 rDestinationHandle
.nFlags
|= HandleFlags::REFX
;
488 else if ( rPropVal
.Name
== "RefY" )
490 if ( rPropVal
.Value
>>= rDestinationHandle
.nRefY
)
491 rDestinationHandle
.nFlags
|= HandleFlags::REFY
;
493 else if ( rPropVal
.Name
== "RefAngle" )
495 if ( rPropVal
.Value
>>= rDestinationHandle
.nRefAngle
)
496 rDestinationHandle
.nFlags
|= HandleFlags::REFANGLE
;
498 else if ( rPropVal
.Name
== "RefR" )
500 if ( rPropVal
.Value
>>= rDestinationHandle
.nRefR
)
501 rDestinationHandle
.nFlags
|= HandleFlags::REFR
;
503 else if ( rPropVal
.Name
== "RadiusRangeMinimum" )
505 if ( rPropVal
.Value
>>= rDestinationHandle
.aRadiusRangeMinimum
)
506 rDestinationHandle
.nFlags
|= HandleFlags::RADIUS_RANGE_MINIMUM
;
508 else if ( rPropVal
.Name
== "RadiusRangeMaximum" )
510 if ( rPropVal
.Value
>>= rDestinationHandle
.aRadiusRangeMaximum
)
511 rDestinationHandle
.nFlags
|= HandleFlags::RADIUS_RANGE_MAXIMUM
;
513 else if ( rPropVal
.Name
== "RangeXMinimum" )
515 if ( rPropVal
.Value
>>= rDestinationHandle
.aXRangeMinimum
)
516 rDestinationHandle
.nFlags
|= HandleFlags::RANGE_X_MINIMUM
;
518 else if ( rPropVal
.Name
== "RangeXMaximum" )
520 if ( rPropVal
.Value
>>= rDestinationHandle
.aXRangeMaximum
)
521 rDestinationHandle
.nFlags
|= HandleFlags::RANGE_X_MAXIMUM
;
523 else if ( rPropVal
.Name
== "RangeYMinimum" )
525 if ( rPropVal
.Value
>>= rDestinationHandle
.aYRangeMinimum
)
526 rDestinationHandle
.nFlags
|= HandleFlags::RANGE_Y_MINIMUM
;
528 else if ( rPropVal
.Name
== "RangeYMaximum" )
530 if ( rPropVal
.Value
>>= rDestinationHandle
.aYRangeMaximum
)
531 rDestinationHandle
.nFlags
|= HandleFlags::RANGE_Y_MAXIMUM
;
538 const sal_Int32
* EnhancedCustomShape2d::ApplyShapeAttributes( const SdrCustomShapeGeometryItem
& rGeometryItem
)
540 const sal_Int32
* pDefData
= NULL
;
541 const mso_CustomShape
* pDefCustomShape
= GetCustomShapeContent( eSpType
);
542 if ( pDefCustomShape
)
543 pDefData
= pDefCustomShape
->pDefData
;
547 const Any
* pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( "AdjustmentValues" );
549 *pAny
>>= seqAdjustmentValues
;
553 const Any
* pViewBox
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( "ViewBox" );
554 com::sun::star::awt::Rectangle aViewBox
;
555 if ( pViewBox
&& (*pViewBox
>>= aViewBox
) )
557 nCoordLeft
= aViewBox
.X
;
558 nCoordTop
= aViewBox
.Y
;
559 nCoordWidthG
= labs( aViewBox
.Width
);
560 nCoordHeightG
= labs( aViewBox
.Height
);
562 const OUString
sPath( "Path" );
566 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "Coordinates" );
568 *pAny
>>= seqCoordinates
;
572 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "GluePoints" );
574 *pAny
>>= seqGluePoints
;
578 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "Segments" );
580 *pAny
>>= seqSegments
;
584 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "SubViewSize" );
586 *pAny
>>= seqSubViewSize
;
590 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "StretchX" );
593 sal_Int32 nStretchX
= 0;
594 if ( *pAny
>>= nStretchX
)
600 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "StretchY" );
603 sal_Int32 nStretchY
= 0;
604 if ( *pAny
>>= nStretchY
)
610 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( sPath
, "TextFrames" );
612 *pAny
>>= seqTextFrames
;
616 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( "Equations" );
618 *pAny
>>= seqEquations
;
622 pAny
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( "Handles" );
624 *pAny
>>= seqHandles
;
629 EnhancedCustomShape2d::~EnhancedCustomShape2d()
633 void EnhancedCustomShape2d::SetPathSize( sal_Int32 nIndex
)
635 sal_Int32 nWidth
= 0;
636 sal_Int32 nHeight
= 0;
638 if ( seqSubViewSize
.getLength() && nIndex
< seqSubViewSize
.getLength() ) {
639 nWidth
= seqSubViewSize
[ nIndex
].Width
;
640 nHeight
= seqSubViewSize
[ nIndex
].Height
;
643 "set subpath " << nIndex
<< " size: " << nWidth
<< " x "
647 if ( nWidth
&& nHeight
) {
648 nCoordWidth
= nWidth
;
649 nCoordHeight
= nHeight
;
651 nCoordWidth
= nCoordWidthG
;
652 nCoordHeight
= nCoordHeightG
;
655 fXScale
= nCoordWidth
== 0 ? 0.0 : (double)aLogicRect
.GetWidth() / (double)nCoordWidth
;
656 fYScale
= nCoordHeight
== 0 ? 0.0 : (double)aLogicRect
.GetHeight() / (double)nCoordHeight
;
661 "ooxml shape, path width: " << nCoordWidth
<< " height: "
663 if ( nCoordWidth
== 0 )
665 if ( nCoordHeight
== 0 )
668 if ( (sal_uInt32
)nXRef
!= 0x80000000 && aLogicRect
.GetHeight() )
670 fXRatio
= (double)aLogicRect
.GetWidth() / (double)aLogicRect
.GetHeight();
678 if ( (sal_uInt32
)nYRef
!= 0x80000000 && aLogicRect
.GetWidth() )
680 fYRatio
= (double)aLogicRect
.GetHeight() / (double)aLogicRect
.GetWidth();
690 EnhancedCustomShape2d::EnhancedCustomShape2d( SdrObject
* pAObj
) :
691 SfxItemSet ( pAObj
->GetMergedItemSet() ),
692 pCustomShapeObj ( pAObj
),
693 eSpType ( mso_sptNil
),
696 nCoordWidthG ( 21600 ),
697 nCoordHeightG ( 21600 ),
698 bOOXMLShape ( false ),
699 nXRef ( 0x80000000 ),
700 nYRef ( 0x80000000 ),
703 bFilled ( static_cast<const XFillStyleItem
&>(pAObj
->GetMergedItem( XATTR_FILLSTYLE
)).GetValue() != drawing::FillStyle_NONE
),
704 bStroked ( static_cast<const XLineStyleItem
&>(pAObj
->GetMergedItem( XATTR_LINESTYLE
)).GetValue() != drawing::LineStyle_NONE
),
708 // bTextFlow needs to be set before clearing the TextDirection Item
710 ClearItem( SDRATTR_TEXTDIRECTION
); //SJ: vertical writing is not required, by removing this item no outliner is created
712 // #i105323# For 2D AtoShapes, the shadow attirbute does not need to be applied to any
713 // of the constucted helper SdrObjects. This would lead to problems since the shadow
714 // of one helper object would fall on one helper object behind it (e.g. with the
715 // eyes of the smiley shape). This is not wanted; instead a single shadow 'behind'
716 // the AutoShape visualisation is wanted. This is done with primitive functionailty
717 // now in SdrCustomShapePrimitive2D::create2DDecomposition, but only for 2D objects
718 // (see there and in EnhancedCustomShape3d::Create3DObject to read more).
719 // This exception may be removed later when AutoShapes will create primitives directly.
720 // So, currently remove the ShadowAttribute from the ItemSet to not apply it to any
722 ClearItem(SDRATTR_SHADOW
);
724 Point
aP( pCustomShapeObj
->GetSnapRect().Center() );
725 Size
aS( pCustomShapeObj
->GetLogicRect().GetSize() );
726 aP
.X() -= aS
.Width() / 2;
727 aP
.Y() -= aS
.Height() / 2;
728 aLogicRect
= Rectangle( aP
, aS
);
731 const SdrCustomShapeGeometryItem
& rGeometryItem
= static_cast<const SdrCustomShapeGeometryItem
&>(pCustomShapeObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
));
732 const Any
* pAny
= rGeometryItem
.GetPropertyValueByName( "Type" );
734 *pAny
>>= sShapeType
;
735 bOOXMLShape
= ( sShapeType
.startsWith("ooxml-") );
736 OSL_TRACE("shape type: %s %d", OUStringToOString( sShapeType
, RTL_TEXTENCODING_ASCII_US
).getStr(), bOOXMLShape
);
738 eSpType
= EnhancedCustomShapeTypeNames::Get( sShapeType
);
740 pAny
= rGeometryItem
.GetPropertyValueByName( "MirroredX" );
743 pAny
= rGeometryItem
.GetPropertyValueByName( "MirroredY" );
747 if ( pCustomShapeObj
->ISA( SdrObjCustomShape
) ) // should always be a SdrObjCustomShape, but you don't know
748 nRotateAngle
= (sal_Int32
)(static_cast<SdrObjCustomShape
*>(pCustomShapeObj
)->GetObjectRotation() * 100.0);
750 nRotateAngle
= pCustomShapeObj
->GetRotateAngle();
752 /*const sal_Int32* pDefData =*/ ApplyShapeAttributes( rGeometryItem
);
757 case mso_sptCan
: nColorData
= 0x20400000; break;
758 case mso_sptCube
: nColorData
= 0x302e0000; break;
759 case mso_sptActionButtonBlank
: nColorData
= 0x502ce400; break;
760 case mso_sptActionButtonHome
: nColorData
= 0x702ce4ce; break;
761 case mso_sptActionButtonHelp
: nColorData
= 0x602ce4c0; break;
762 case mso_sptActionButtonInformation
: nColorData
= 0x702ce4c5; break;
763 case mso_sptActionButtonBackPrevious
: nColorData
= 0x602ce4c0; break;
764 case mso_sptActionButtonForwardNext
: nColorData
= 0x602ce4c0; break;
765 case mso_sptActionButtonBeginning
: nColorData
= 0x602ce4c0; break;
766 case mso_sptActionButtonEnd
: nColorData
= 0x602ce4c0; break;
767 case mso_sptActionButtonReturn
: nColorData
= 0x602ce4c0; break;
768 case mso_sptActionButtonDocument
: nColorData
= 0x702ce4ec; break;
769 case mso_sptActionButtonSound
: nColorData
= 0x602ce4c0; break;
770 case mso_sptActionButtonMovie
: nColorData
= 0x602ce4c0; break;
771 case mso_sptBevel
: nColorData
= 0x502ce400; break;
772 case mso_sptFoldedCorner
: nColorData
= 0x20e00000; break;
773 case mso_sptSmileyFace
: nColorData
= 0x20e00000; break;
776 if( sShapeType
.getLength() > 4 &&
777 sShapeType
.match( "col-" ))
779 nColorData
= sShapeType
.copy( 4 ).toUInt32( 16 );
783 case mso_sptCurvedLeftArrow
:
784 case mso_sptCurvedRightArrow
:
785 case mso_sptCurvedUpArrow
:
786 case mso_sptCurvedDownArrow
: nColorData
= 0x20d00000; break;
787 case mso_sptRibbon2
: nColorData
= 0x30ee0000; break;
788 case mso_sptRibbon
: nColorData
= 0x30ee0000; break;
790 case mso_sptEllipseRibbon2
: nColorData
= 0x30ee0000; break;
791 case mso_sptEllipseRibbon
: nColorData
= 0x30ee0000; break;
793 case mso_sptVerticalScroll
: nColorData
= 0x30ee0000; break;
794 case mso_sptHorizontalScroll
: nColorData
= 0x30ee0000; break;
799 sal_Int32 i
, nLength
= seqEquations
.getLength();
803 vNodesSharedPtr
.resize( nLength
);
804 vEquationResults
.resize( nLength
);
805 for ( i
= 0; i
< seqEquations
.getLength(); i
++ )
807 vEquationResults
[ i
].bReady
= false;
810 vNodesSharedPtr
[ i
] = EnhancedCustomShape::FunctionParser::parseFunction( seqEquations
[ i
], *this );
812 catch ( EnhancedCustomShape::ParseError
& )
816 "error: equation number: " << i
<< ", parser failed ("
817 << seqEquations
[i
] << ")");
822 double EnhancedCustomShape2d::GetEnumFunc( const EnumFunc eFunc
) const
827 case ENUM_FUNC_PI
: fRet
= F_PI
; break;
828 case ENUM_FUNC_LEFT
: fRet
= 0.0; break;
829 case ENUM_FUNC_TOP
: fRet
= 0.0; break;
830 case ENUM_FUNC_RIGHT
: fRet
= (double)nCoordWidth
* fXRatio
; break;
831 case ENUM_FUNC_BOTTOM
: fRet
= (double)nCoordHeight
* fYRatio
; break;
832 case ENUM_FUNC_XSTRETCH
: fRet
= nXRef
; break;
833 case ENUM_FUNC_YSTRETCH
: fRet
= nYRef
; break;
834 case ENUM_FUNC_HASSTROKE
: fRet
= bStroked
? 1.0 : 0.0; break;
835 case ENUM_FUNC_HASFILL
: fRet
= bFilled
? 1.0 : 0.0; break;
836 case ENUM_FUNC_WIDTH
: fRet
= nCoordWidth
; break;
837 case ENUM_FUNC_HEIGHT
: fRet
= nCoordHeight
; break;
838 case ENUM_FUNC_LOGWIDTH
: fRet
= aLogicRect
.GetWidth(); break;
839 case ENUM_FUNC_LOGHEIGHT
: fRet
= aLogicRect
.GetHeight(); break;
843 double EnhancedCustomShape2d::GetAdjustValueAsDouble( const sal_Int32 nIndex
) const
845 double fNumber
= 0.0;
846 if ( nIndex
< seqAdjustmentValues
.getLength() )
848 if ( seqAdjustmentValues
[ nIndex
].Value
.getValueTypeClass() == TypeClass_DOUBLE
)
849 seqAdjustmentValues
[ nIndex
].Value
>>= fNumber
;
852 sal_Int32 nNumber
= 0;
853 seqAdjustmentValues
[ nIndex
].Value
>>= nNumber
;
854 fNumber
= (double)nNumber
;
859 double EnhancedCustomShape2d::GetEquationValueAsDouble( const sal_Int32 nIndex
) const
861 double fNumber
= 0.0;
862 #if OSL_DEBUG_LEVEL > 1
863 static sal_uInt32 nLevel
= 0;
865 if ( nIndex
< (sal_Int32
)vNodesSharedPtr
.size() )
867 if ( vNodesSharedPtr
[ nIndex
].get() ) {
868 #if OSL_DEBUG_LEVEL > 1
873 if ( vEquationResults
[ nIndex
].bReady
)
874 fNumber
= vEquationResults
[ nIndex
].fValue
;
876 // cast to non const, so that we can optimize by caching
877 // equation results, without changing all the const in the stack
878 struct EquationResult
&aResult
= const_cast<EnhancedCustomShape2d
*>(this)->vEquationResults
[ nIndex
];
880 fNumber
= aResult
.fValue
= (*vNodesSharedPtr
[ nIndex
])();
881 aResult
.bReady
= true;
883 if ( !rtl::math::isFinite( fNumber
) )
885 #if OSL_DEBUG_LEVEL > 1
886 OSL_TRACE("equation %d (level: %d): %s --> %f (angle: %f)", nIndex
,
887 nLevel
, OUStringToOString( seqEquations
[ nIndex
],
888 RTL_TEXTENCODING_ASCII_US
).getStr(), fNumber
, 180.0*fNumber
/10800000.0);
894 OSL_TRACE("error: EnhancedCustomShape2d::GetEquationValueAsDouble failed");
896 #if OSL_DEBUG_LEVEL > 1
902 "?" << nIndex
<< " --> " << fNumber
<< " (angle: "
903 << 180.0*fNumber
/10800000.0 << ")");
908 sal_Int32
EnhancedCustomShape2d::GetAdjustValueAsInteger( const sal_Int32 nIndex
, const sal_Int32 nDefault
) const
910 sal_Int32 nNumber
= nDefault
;
911 if ( nIndex
< seqAdjustmentValues
.getLength() )
913 if ( seqAdjustmentValues
[ nIndex
].Value
.getValueTypeClass() == TypeClass_DOUBLE
)
916 seqAdjustmentValues
[ nIndex
].Value
>>= fNumber
;
917 nNumber
= (sal_Int32
)fNumber
;
920 seqAdjustmentValues
[ nIndex
].Value
>>= nNumber
;
924 bool EnhancedCustomShape2d::SetAdjustValueAsDouble( const double& rValue
, const sal_Int32 nIndex
)
926 bool bRetValue
= false;
927 if ( nIndex
< seqAdjustmentValues
.getLength() )
929 // updating our local adjustment sequence
930 seqAdjustmentValues
[ nIndex
].Value
<<= rValue
;
931 seqAdjustmentValues
[ nIndex
].State
= com::sun::star::beans::PropertyState_DIRECT_VALUE
;
937 Point
EnhancedCustomShape2d::GetPoint( const com::sun::star::drawing::EnhancedCustomShapeParameterPair
& rPair
,
938 const bool bScale
, const bool bReplaceGeoSize
) const
941 sal_uInt32 nPass
= 0;
944 sal_uInt32 nIndex
= nPass
;
947 const EnhancedCustomShapeParameter
& rParameter
= nIndex
? rPair
.Second
: rPair
.First
;
948 if ( nPass
) // height
950 GetParameter( fVal
, rParameter
, false, bReplaceGeoSize
);
956 aRetValue
.Y() = (sal_Int32
)fVal
;
960 GetParameter( fVal
, rParameter
, bReplaceGeoSize
, false );
966 aRetValue
.X() = static_cast<long>(fVal
);
969 while ( ++nPass
< 2 );
973 bool EnhancedCustomShape2d::GetParameter( double& rRetValue
, const EnhancedCustomShapeParameter
& rParameter
,
974 const bool bReplaceGeoWidth
, const bool bReplaceGeoHeight
) const
977 bool bRetValue
= false;
978 switch ( rParameter
.Type
)
980 case EnhancedCustomShapeParameterType::ADJUSTMENT
:
982 sal_Int32 nAdjustmentIndex
= 0;
983 if ( rParameter
.Value
>>= nAdjustmentIndex
)
985 rRetValue
= GetAdjustValueAsDouble( nAdjustmentIndex
);
990 case EnhancedCustomShapeParameterType::EQUATION
:
992 sal_Int32 nEquationIndex
= 0;
993 if ( rParameter
.Value
>>= nEquationIndex
)
995 rRetValue
= GetEquationValueAsDouble( nEquationIndex
);
1000 case EnhancedCustomShapeParameterType::NORMAL
:
1002 if ( rParameter
.Value
.getValueTypeClass() == TypeClass_DOUBLE
)
1005 if ( rParameter
.Value
>>= fValue
)
1013 sal_Int32 nValue
= 0;
1014 if ( rParameter
.Value
>>= nValue
)
1018 if ( bReplaceGeoWidth
&& ( nValue
== nCoordWidth
) )
1019 rRetValue
*= fXRatio
;
1020 else if ( bReplaceGeoHeight
&& ( nValue
== nCoordHeight
) )
1021 rRetValue
*= fYRatio
;
1026 case EnhancedCustomShapeParameterType::LEFT
:
1032 case EnhancedCustomShapeParameterType::TOP
:
1038 case EnhancedCustomShapeParameterType::RIGHT
:
1040 rRetValue
= nCoordWidth
;
1044 case EnhancedCustomShapeParameterType::BOTTOM
:
1046 rRetValue
= nCoordHeight
;
1054 // nLumDat 28-31 = number of luminance entries in nLumDat
1055 // nLumDat 27-24 = nLumDatEntry 0
1056 // nLumDat 23-20 = nLumDatEntry 1 ...
1057 // each 4bit entry is to be interpreted as a 10 percent signed luminance changing
1058 sal_Int32
EnhancedCustomShape2d::GetLuminanceChange( sal_uInt32 nIndex
) const
1060 const sal_uInt32 nCount
= nColorData
>> 28;
1064 if ( nIndex
>= nCount
)
1065 nIndex
= nCount
- 1;
1067 const sal_Int32 nLumDat
= nColorData
<< ( ( 1 + nIndex
) << 2 );
1068 return ( nLumDat
>> 28 ) * 10;
1071 Color
EnhancedCustomShape2d::GetColorData( const Color
& rFillColor
, sal_uInt32 nIndex
, double dBrightness
) const
1073 const sal_Int32 nLuminance
= GetLuminanceChange(nIndex
);
1074 if( !nLuminance
&& dBrightness
== 1.0 )
1077 basegfx::BColor aHSVColor
=
1078 basegfx::tools::rgb2hsv(
1079 basegfx::BColor(rFillColor
.GetRed()/255.0,
1080 rFillColor
.GetGreen()/255.0,
1081 rFillColor
.GetBlue()/255.0));
1083 if( nLuminance
> 0 )
1086 aHSVColor
.getGreen() * (1.0-nLuminance
/100.0));
1089 (1.0-nLuminance
/100.0)*aHSVColor
.getBlue());
1091 else if( nLuminance
< 0 )
1094 (1.0+nLuminance
/100.0)*aHSVColor
.getBlue());
1098 aHSVColor
= basegfx::tools::hsv2rgb(aHSVColor
);
1099 return Color( (sal_uInt8
)static_cast< sal_Int32
>( basegfx::clamp(dBrightness
*aHSVColor
.getRed(),0.0,1.0) * 255.0 + 0.5 ),
1100 (sal_uInt8
)static_cast< sal_Int32
>( basegfx::clamp(dBrightness
*aHSVColor
.getGreen(),0.0,1.0) * 255.0 + 0.5 ),
1101 (sal_uInt8
)static_cast< sal_Int32
>( basegfx::clamp(dBrightness
*aHSVColor
.getBlue(),0.0,1.0) * 255.0 + 0.5 ) );
1104 Rectangle
EnhancedCustomShape2d::GetTextRect() const
1106 sal_Int32 nIndex
, nSize
= seqTextFrames
.getLength();
1110 if ( bTextFlow
&& ( nSize
> 1 ) )
1112 Point
aTopLeft( GetPoint( seqTextFrames
[ nIndex
].TopLeft
, !bOOXMLShape
, true ) );
1113 Point
aBottomRight( GetPoint( seqTextFrames
[ nIndex
].BottomRight
, !bOOXMLShape
, true ) );
1116 aTopLeft
.X() = aLogicRect
.GetWidth() - aTopLeft
.X();
1117 aBottomRight
.X() = aLogicRect
.GetWidth() - aBottomRight
.X();
1121 aTopLeft
.Y() = aLogicRect
.GetHeight() - aTopLeft
.Y();
1122 aBottomRight
.Y() = aLogicRect
.GetHeight() - aBottomRight
.Y();
1124 Rectangle
aRect( aTopLeft
, aBottomRight
);
1125 SAL_INFO("svx", aRect
.GetWidth() << " x " << aRect
.GetHeight());
1126 if( aRect
.GetWidth() <= 1 || aRect
.GetHeight() <= 1 )
1128 aRect
.Move( aLogicRect
.Left(), aLogicRect
.Top() );
1133 sal_uInt32
EnhancedCustomShape2d::GetHdlCount() const
1135 return seqHandles
.getLength();
1138 bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex
, Point
& rReturnPosition
) const
1140 bool bRetValue
= false;
1141 if ( nIndex
< GetHdlCount() )
1144 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles
[ nIndex
], aHandle
) )
1146 if ( aHandle
.nFlags
& HandleFlags::POLAR
)
1148 Point
aReferencePoint( GetPoint( aHandle
.aPolar
, true, false ) );
1152 GetParameter( fRadius
, aHandle
.aPosition
.First
, false, false );
1153 GetParameter( fAngle
, aHandle
.aPosition
.Second
, false, false );
1155 double a
= ( 360.0 - fAngle
) * F_PI180
;
1156 double dx
= fRadius
* fXScale
;
1157 double fX
= dx
* cos( a
);
1158 double fY
=-dx
* sin( a
);
1161 Round( fX
+ aReferencePoint
.X() ),
1162 basegfx::fTools::equalZero(fXScale
) ? aReferencePoint
.Y() :
1163 Round( ( fY
* fYScale
) / fXScale
+ aReferencePoint
.Y() ) );
1167 if ( aHandle
.nFlags
& HandleFlags::SWITCHED
)
1169 if ( aLogicRect
.GetHeight() > aLogicRect
.GetWidth() )
1171 com::sun::star::drawing::EnhancedCustomShapeParameter aFirst
= aHandle
.aPosition
.First
;
1172 com::sun::star::drawing::EnhancedCustomShapeParameter aSecond
= aHandle
.aPosition
.Second
;
1173 aHandle
.aPosition
.First
= aSecond
;
1174 aHandle
.aPosition
.Second
= aFirst
;
1177 rReturnPosition
= GetPoint( aHandle
.aPosition
, true, false );
1179 const GeoStat
aGeoStat( static_cast<SdrObjCustomShape
*>(pCustomShapeObj
)->GetGeoStat() );
1180 if ( aGeoStat
.nShearAngle
)
1182 double nTan
= aGeoStat
.nTan
;
1183 if ((bFlipV
&&!bFlipH
)||(bFlipH
&&!bFlipV
))
1185 ShearPoint( rReturnPosition
, Point( aLogicRect
.GetWidth() / 2, aLogicRect
.GetHeight() / 2 ), nTan
);
1189 double a
= nRotateAngle
* F_PI18000
;
1190 RotatePoint( rReturnPosition
, Point( aLogicRect
.GetWidth() / 2, aLogicRect
.GetHeight() / 2 ), sin( a
), cos( a
) );
1193 rReturnPosition
.X() = aLogicRect
.GetWidth() - rReturnPosition
.X();
1195 rReturnPosition
.Y() = aLogicRect
.GetHeight() - rReturnPosition
.Y();
1196 rReturnPosition
.Move( aLogicRect
.Left(), aLogicRect
.Top() );
1203 bool EnhancedCustomShape2d::SetHandleControllerPosition( const sal_uInt32 nIndex
, const com::sun::star::awt::Point
& rPosition
)
1205 bool bRetValue
= false;
1206 if ( nIndex
< GetHdlCount() )
1209 if ( ConvertSequenceToEnhancedCustomShape2dHandle( seqHandles
[ nIndex
], aHandle
) )
1211 Point
aP( rPosition
.X
, rPosition
.Y
);
1212 // apply the negative object rotation to the controller position
1214 aP
.Move( -aLogicRect
.Left(), -aLogicRect
.Top() );
1216 aP
.X() = aLogicRect
.GetWidth() - aP
.X();
1218 aP
.Y() = aLogicRect
.GetHeight() - aP
.Y();
1221 double a
= -nRotateAngle
* F_PI18000
;
1222 RotatePoint( aP
, Point( aLogicRect
.GetWidth() / 2, aLogicRect
.GetHeight() / 2 ), sin( a
), cos( a
) );
1224 const GeoStat
aGeoStat( static_cast<SdrObjCustomShape
*>(pCustomShapeObj
)->GetGeoStat() );
1225 if ( aGeoStat
.nShearAngle
)
1227 double nTan
= -aGeoStat
.nTan
;
1228 if ((bFlipV
&&!bFlipH
)||(bFlipH
&&!bFlipV
))
1230 ShearPoint( aP
, Point( aLogicRect
.GetWidth() / 2, aLogicRect
.GetHeight() / 2 ), nTan
);
1233 double fPos1
= aP
.X(); //( bFlipH ) ? aLogicRect.GetWidth() - aP.X() : aP.X();
1234 double fPos2
= aP
.Y(); //( bFlipV ) ? aLogicRect.GetHeight() -aP.Y() : aP.Y();
1238 if ( aHandle
.nFlags
& HandleFlags::SWITCHED
)
1240 if ( aLogicRect
.GetHeight() > aLogicRect
.GetWidth() )
1249 sal_Int32 nFirstAdjustmentValue
= -1, nSecondAdjustmentValue
= -1;
1251 if ( aHandle
.aPosition
.First
.Type
== EnhancedCustomShapeParameterType::ADJUSTMENT
)
1252 aHandle
.aPosition
.First
.Value
>>= nFirstAdjustmentValue
;
1253 if ( aHandle
.aPosition
.Second
.Type
== EnhancedCustomShapeParameterType::ADJUSTMENT
)
1254 aHandle
.aPosition
.Second
.Value
>>= nSecondAdjustmentValue
;
1256 if ( aHandle
.nFlags
& HandleFlags::POLAR
)
1258 double fXRef
, fYRef
, fAngle
;
1259 GetParameter( fXRef
, aHandle
.aPolar
.First
, false, false );
1260 GetParameter( fYRef
, aHandle
.aPolar
.Second
, false, false );
1261 const double fDX
= fPos1
- fXRef
;
1262 fAngle
= -( atan2( -fPos2
+ fYRef
, ( ( fDX
== 0.0L ) ? 0.000000001 : fDX
) ) / F_PI180
);
1263 double fX
= ( fPos1
- fXRef
);
1264 double fY
= ( fPos2
- fYRef
);
1265 double fRadius
= sqrt( fX
* fX
+ fY
* fY
);
1266 if ( aHandle
.nFlags
& HandleFlags::RADIUS_RANGE_MINIMUM
)
1269 GetParameter( fMin
, aHandle
.aRadiusRangeMinimum
, false, false );
1270 if ( fRadius
< fMin
)
1273 if ( aHandle
.nFlags
& HandleFlags::RADIUS_RANGE_MAXIMUM
)
1276 GetParameter( fMax
, aHandle
.aRadiusRangeMaximum
, false, false );
1277 if ( fRadius
> fMax
)
1280 if ( nFirstAdjustmentValue
>= 0 )
1281 SetAdjustValueAsDouble( fRadius
, nFirstAdjustmentValue
);
1282 if ( nSecondAdjustmentValue
>= 0 )
1283 SetAdjustValueAsDouble( fAngle
, nSecondAdjustmentValue
);
1287 if ( aHandle
.nFlags
& HandleFlags::REFX
)
1289 nFirstAdjustmentValue
= aHandle
.nRefX
;
1291 fPos1
/= nCoordWidth
;
1293 if ( aHandle
.nFlags
& HandleFlags::REFY
)
1295 nSecondAdjustmentValue
= aHandle
.nRefY
;
1297 fPos2
/= nCoordHeight
;
1299 if ( nFirstAdjustmentValue
>= 0 )
1301 if ( aHandle
.nFlags
& HandleFlags::RANGE_X_MINIMUM
) // check if horizontal handle needs to be within a range
1304 GetParameter( fXMin
, aHandle
.aXRangeMinimum
, false, false );
1305 if ( fPos1
< fXMin
)
1308 if ( aHandle
.nFlags
& HandleFlags::RANGE_X_MAXIMUM
) // check if horizontal handle needs to be within a range
1311 GetParameter( fXMax
, aHandle
.aXRangeMaximum
, false, false );
1312 if ( fPos1
> fXMax
)
1315 SetAdjustValueAsDouble( fPos1
, nFirstAdjustmentValue
);
1317 if ( nSecondAdjustmentValue
>= 0 )
1319 if ( aHandle
.nFlags
& HandleFlags::RANGE_Y_MINIMUM
) // check if vertical handle needs to be within a range
1322 GetParameter( fYMin
, aHandle
.aYRangeMinimum
, false, false );
1323 if ( fPos2
< fYMin
)
1326 if ( aHandle
.nFlags
& HandleFlags::RANGE_Y_MAXIMUM
) // check if vertical handle needs to be within a range
1329 GetParameter( fYMax
, aHandle
.aYRangeMaximum
, false, false );
1330 if ( fPos2
> fYMax
)
1333 SetAdjustValueAsDouble( fPos2
, nSecondAdjustmentValue
);
1336 // and writing them back into the GeometryItem
1337 SdrCustomShapeGeometryItem
aGeometryItem(
1338 static_cast<const SdrCustomShapeGeometryItem
&>(pCustomShapeObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
)));
1339 com::sun::star::beans::PropertyValue aPropVal
;
1340 aPropVal
.Name
= "AdjustmentValues";
1341 aPropVal
.Value
<<= seqAdjustmentValues
;
1342 aGeometryItem
.SetPropertyValue( aPropVal
);
1343 pCustomShapeObj
->SetMergedItem( aGeometryItem
);
1350 void EnhancedCustomShape2d::SwapStartAndEndArrow( SdrObject
* pObj
) //#108274
1352 XLineStartItem aLineStart
;
1353 aLineStart
.SetLineStartValue(static_cast<const XLineStartItem
&>(pObj
->GetMergedItem( XATTR_LINEEND
)).GetLineStartValue());
1354 XLineStartWidthItem
aLineStartWidth(static_cast<const XLineStartWidthItem
&>(pObj
->GetMergedItem( XATTR_LINEENDWIDTH
)).GetValue());
1355 XLineStartCenterItem
aLineStartCenter(static_cast<const XLineStartCenterItem
&>(pObj
->GetMergedItem( XATTR_LINEENDCENTER
)).GetValue());
1357 XLineEndItem aLineEnd
;
1358 aLineEnd
.SetLineEndValue(static_cast<const XLineEndItem
&>(pObj
->GetMergedItem( XATTR_LINESTART
)).GetLineEndValue());
1359 XLineEndWidthItem
aLineEndWidth(static_cast<const XLineEndWidthItem
&>(pObj
->GetMergedItem( XATTR_LINESTARTWIDTH
)).GetValue());
1360 XLineEndCenterItem
aLineEndCenter(static_cast<const XLineEndCenterItem
&>(pObj
->GetMergedItem( XATTR_LINESTARTCENTER
)).GetValue());
1362 pObj
->SetMergedItem( aLineStart
);
1363 pObj
->SetMergedItem( aLineStartWidth
);
1364 pObj
->SetMergedItem( aLineStartCenter
);
1365 pObj
->SetMergedItem( aLineEnd
);
1366 pObj
->SetMergedItem( aLineEndWidth
);
1367 pObj
->SetMergedItem( aLineEndCenter
);
1370 static basegfx::B2DPolygon
CreateArc( const Rectangle
& rRect
, const Point
& rStart
, const Point
& rEnd
, const bool bClockwise
, bool bFullCircle
= false )
1372 Rectangle
aRect( rRect
);
1373 Point
aStart( rStart
);
1376 sal_Int32 bSwapStartEndAngle
= 0;
1378 if ( aRect
.Left() > aRect
.Right() )
1379 bSwapStartEndAngle
^= 0x01;
1380 if ( aRect
.Top() > aRect
.Bottom() )
1381 bSwapStartEndAngle
^= 0x11;
1382 if ( bSwapStartEndAngle
)
1385 if ( bSwapStartEndAngle
& 1 )
1387 Point
aTmp( aStart
);
1393 Polygon
aTempPoly( aRect
, aStart
, aEnd
, POLY_ARC
, bFullCircle
);
1394 basegfx::B2DPolygon aRetval
;
1398 for ( sal_uInt16 j
= aTempPoly
.GetSize(); j
--; )
1400 aRetval
.append(basegfx::B2DPoint(aTempPoly
[ j
].X(), aTempPoly
[ j
].Y()));
1405 for ( sal_uInt16 j
= 0; j
< aTempPoly
.GetSize(); j
++ )
1407 aRetval
.append(basegfx::B2DPoint(aTempPoly
[ j
].X(), aTempPoly
[ j
].Y()));
1414 void EnhancedCustomShape2d::CreateSubPath( sal_uInt16
& rSrcPt
, sal_uInt16
& rSegmentInd
, std::vector
< SdrPathObj
* >& rObjectList
,
1415 const bool bLineGeometryNeededOnly
,
1416 const bool bSortFilledObjectsToBack
,
1419 bool bNoFill
= false;
1420 bool bNoStroke
= false;
1421 double dBrightness
= 1.0;
1423 basegfx::B2DPolyPolygon aNewB2DPolyPolygon
;
1424 basegfx::B2DPolygon aNewB2DPolygon
;
1426 SetPathSize( nIndex
);
1428 sal_Int32 nCoordSize
= seqCoordinates
.getLength();
1429 sal_Int32 nSegInfoSize
= seqSegments
.getLength();
1430 if ( !nSegInfoSize
)
1432 const EnhancedCustomShapeParameterPair
* pTmp
= seqCoordinates
.getArray();
1434 for ( sal_Int32
nPtNum(0L); nPtNum
< nCoordSize
; nPtNum
++ )
1436 const Point
aTempPoint(GetPoint( *pTmp
++, true, true ));
1437 aNewB2DPolygon
.append(basegfx::B2DPoint(aTempPoint
.X(), aTempPoint
.Y()));
1440 aNewB2DPolygon
.setClosed(true);
1444 for ( ;rSegmentInd
< nSegInfoSize
; )
1446 sal_Int16 nCommand
= seqSegments
[ rSegmentInd
].Command
;
1447 sal_Int16 nPntCount
= seqSegments
[ rSegmentInd
++ ].Count
;
1458 dBrightness
= 0.66666666;
1461 dBrightness
= 0.83333333;
1464 dBrightness
= 1.16666666;
1467 dBrightness
= 1.33333333;
1471 if(aNewB2DPolygon
.count() > 1L)
1473 // #i76201# Add conversion to closed polygon when first and last points are equal
1474 basegfx::tools::checkClosed(aNewB2DPolygon
);
1475 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1478 aNewB2DPolygon
.clear();
1480 if ( rSrcPt
< nCoordSize
)
1482 const Point
aTempPoint(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1485 "moveTo: " << aTempPoint
.X() << ","
1487 aNewB2DPolygon
.append(basegfx::B2DPoint(aTempPoint
.X(), aTempPoint
.Y()));
1495 if(aNewB2DPolygon
.count())
1497 if(aNewB2DPolygon
.count() > 1L)
1499 aNewB2DPolygon
.setClosed(true);
1500 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1503 aNewB2DPolygon
.clear();
1509 for ( sal_uInt16 i
= 0; ( i
< nPntCount
) && ( ( rSrcPt
+ 2 ) < nCoordSize
); i
++ )
1511 const Point
aControlA(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1512 const Point
aControlB(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1513 const Point
aEnd(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1515 DBG_ASSERT(aNewB2DPolygon
.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding control point (!)");
1516 aNewB2DPolygon
.appendBezierSegment(
1517 basegfx::B2DPoint(aControlA
.X(), aControlA
.Y()),
1518 basegfx::B2DPoint(aControlB
.X(), aControlB
.Y()),
1519 basegfx::B2DPoint(aEnd
.X(), aEnd
.Y()));
1528 if(aNewB2DPolygon
.count() > 1L)
1530 // #i76201# Add conversion to closed polygon when first and last points are equal
1531 basegfx::tools::checkClosed(aNewB2DPolygon
);
1532 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1534 aNewB2DPolygon
.clear();
1537 case ANGLEELLIPSETO
:
1539 for ( sal_uInt16 i
= 0; ( i
< nPntCount
) && ( ( rSrcPt
+ 2 ) < nCoordSize
); i
++ )
1543 double fWidth
, fHeight
;
1544 const mso_CustomShape
* pDefCustomShape
= GetCustomShapeContent( mso_sptEllipse
);
1545 bool bIsDefaultViewBox
= false;
1546 bool bIsDefaultPath
= false;
1547 bool bIsMSEllipse
= false;
1549 if( ( nCoordWidth
== pDefCustomShape
->nCoordWidth
)
1550 && ( nCoordHeight
== pDefCustomShape
->nCoordHeight
) )
1551 bIsDefaultViewBox
= true;
1552 sal_Int32 j
, nCount
= pDefCustomShape
->nVertices
;//==3
1553 com::sun::star::uno::Sequence
< com::sun::star::drawing::EnhancedCustomShapeParameterPair
> seqCoordinates1
, seqCoordinates2
;
1555 seqCoordinates1
.realloc( nCount
);
1556 for ( j
= 0; j
< nCount
; j
++ )
1558 seqCoordinates1
[j
] = seqCoordinates
[ rSrcPt
+ j
];
1561 seqCoordinates2
.realloc( nCount
);
1562 for ( j
= 0; j
< nCount
; j
++ )
1564 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2
[ j
].First
, pDefCustomShape
->pVertices
[ j
].nValA
);
1565 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( seqCoordinates2
[ j
].Second
, pDefCustomShape
->pVertices
[ j
].nValB
);
1567 if(seqCoordinates1
== seqCoordinates2
)
1568 bIsDefaultPath
= true;
1571 SdrCustomShapeGeometryItem
& rGeometryItem
= const_cast<SdrCustomShapeGeometryItem
&>(static_cast<const SdrCustomShapeGeometryItem
&>(pCustomShapeObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
)));
1572 Any
* pAny
= rGeometryItem
.GetPropertyValueByName( "Type" );
1575 if( sShpType
.getLength() > 3 &&
1576 sShpType
.startsWith( "mso" )){
1577 bIsMSEllipse
= true;
1579 if( (! bIsDefaultPath
&& ! bIsDefaultViewBox
) || (bIsDefaultViewBox
&& bIsMSEllipse
) /*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1581 _aCenter
= GetPoint( seqCoordinates
[ rSrcPt
], true, true );
1582 GetParameter( fWidth
, seqCoordinates
[ rSrcPt
+ 1 ].First
, true, false );
1583 GetParameter( fHeight
, seqCoordinates
[ rSrcPt
+ 1 ].Second
, false, true );
1586 }else if( bIsDefaultPath
&& !bIsDefaultViewBox
/*&& (nGeneratorVersion == SfxObjectShell::Sym_L2)*/ )
1588 _aCenter
.X() = nCoordWidth
/2 * fXScale
;
1589 _aCenter
.Y() = nCoordHeight
/2 * fYScale
;
1590 fWidth
= nCoordWidth
/2;
1591 fHeight
= nCoordHeight
/2;
1592 const Any
* pViewBox
= ((SdrCustomShapeGeometryItem
&)rGeometryItem
).GetPropertyValueByName( "ViewBox" );
1593 com::sun::star::awt::Rectangle aViewBox
;
1594 if ( pViewBox
&& (*pViewBox
>>= aViewBox
) )
1596 aViewBox
.Width
= pDefCustomShape
->nCoordWidth
;
1597 aViewBox
.Height
= pDefCustomShape
->nCoordHeight
;
1599 com::sun::star::beans::PropertyValue aPropVal
;
1600 aPropVal
.Name
= "ViewBox";
1601 aPropVal
.Value
<<= aViewBox
;
1602 rGeometryItem
.SetPropertyValue( aPropVal
);
1603 pCustomShapeObj
->SetMergedItem( rGeometryItem
);
1605 _aCenter
= GetPoint( seqCoordinates
[ rSrcPt
], true, true );
1606 GetParameter( fWidth
, seqCoordinates
[ rSrcPt
+ 1 ].First
, true, false);
1607 GetParameter( fHeight
, seqCoordinates
[ rSrcPt
+ 1 ].Second
, false, true );
1612 Point
aP( (sal_Int32
)( _aCenter
.X() - fWidth
), (sal_Int32
)( _aCenter
.Y() - fHeight
) );
1613 Size
aS( (sal_Int32
)( fWidth
* 2.0 ), (sal_Int32
)( fHeight
* 2.0 ) );
1614 Rectangle
aRect( aP
, aS
);
1615 if ( aRect
.GetWidth() && aRect
.GetHeight() )
1617 double fStartAngle
, fEndAngle
;
1618 GetParameter( fStartAngle
, seqCoordinates
[ rSrcPt
+ 2 ].First
, false, false );
1619 GetParameter( fEndAngle
, seqCoordinates
[ rSrcPt
+ 2 ].Second
, false, false );
1621 if ( ((sal_Int32
)fStartAngle
% 360) != ((sal_Int32
)fEndAngle
% 360) )
1623 if ( (sal_Int32
)fStartAngle
& 0x7fff0000 ) // SJ: if the angle was imported from our escher import, then the
1624 fStartAngle
/= 65536.0; // value is shifted by 16. TODO: already change the fixed float to a
1625 if ( (sal_Int32
)fEndAngle
& 0x7fff0000 ) // double in the import filter
1627 fEndAngle
/= 65536.0;
1628 fEndAngle
= fEndAngle
+ fStartAngle
;
1629 if ( fEndAngle
< 0 )
1630 { // in the binary filter the endangle is the amount
1631 double fTemp
= fStartAngle
;
1632 fStartAngle
= fEndAngle
;
1636 double fCenterX
= aRect
.Center().X();
1637 double fCenterY
= aRect
.Center().Y();
1638 double fx1
= ( cos( fStartAngle
* F_PI180
) * 65536.0 * fXScale
) + fCenterX
;
1639 double fy1
= ( -sin( fStartAngle
* F_PI180
) * 65536.0 * fYScale
) + fCenterY
;
1640 double fx2
= ( cos( fEndAngle
* F_PI180
) * 65536.0 * fXScale
) + fCenterX
;
1641 double fy2
= ( -sin( fEndAngle
* F_PI180
) * 65536.0 * fYScale
) + fCenterY
;
1642 aNewB2DPolygon
.append(CreateArc( aRect
, Point( (sal_Int32
)fx1
, (sal_Int32
)fy1
), Point( (sal_Int32
)fx2
, (sal_Int32
)fy2
), false));
1645 { /* SJ: TODO: this block should be replaced sometimes, because the current point
1646 is not set correct, it also does not use the correct moveto
1647 point if ANGLEELLIPSETO was used, but the method CreateArc
1648 is at the moment not able to draw full circles (if startangle is 0
1649 and endangle 360 nothing is painted :-( */
1650 sal_Int32 nXControl
= (sal_Int32
)((double)aRect
.GetWidth() * 0.2835 );
1651 sal_Int32 nYControl
= (sal_Int32
)((double)aRect
.GetHeight() * 0.2835 );
1652 Point
aCenter( aRect
.Center() );
1654 // append start point
1655 aNewB2DPolygon
.append(basegfx::B2DPoint(aCenter
.X(), aRect
.Top()));
1657 // append four bezier segments
1658 aNewB2DPolygon
.appendBezierSegment(
1659 basegfx::B2DPoint(aCenter
.X() + nXControl
, aRect
.Top()),
1660 basegfx::B2DPoint(aRect
.Right(), aCenter
.Y() - nYControl
),
1661 basegfx::B2DPoint(aRect
.Right(), aCenter
.Y()));
1663 aNewB2DPolygon
.appendBezierSegment(
1664 basegfx::B2DPoint(aRect
.Right(), aCenter
.Y() + nYControl
),
1665 basegfx::B2DPoint(aCenter
.X() + nXControl
, aRect
.Bottom()),
1666 basegfx::B2DPoint(aCenter
.X(), aRect
.Bottom()));
1668 aNewB2DPolygon
.appendBezierSegment(
1669 basegfx::B2DPoint(aCenter
.X() - nXControl
, aRect
.Bottom()),
1670 basegfx::B2DPoint(aRect
.Left(), aCenter
.Y() + nYControl
),
1671 basegfx::B2DPoint(aRect
.Left(), aCenter
.Y()));
1673 aNewB2DPolygon
.appendBezierSegment(
1674 basegfx::B2DPoint(aRect
.Left(), aCenter
.Y() - nYControl
),
1675 basegfx::B2DPoint(aCenter
.X() - nXControl
, aRect
.Top()),
1676 basegfx::B2DPoint(aCenter
.X(), aRect
.Top()));
1678 // close, rescue last controlpoint, remove double last point
1679 basegfx::tools::closeWithGeometryChange(aNewB2DPolygon
);
1687 case QUADRATICCURVETO
:
1689 for ( sal_Int32
i(0L); ( i
< nPntCount
) && ( rSrcPt
+ 1 < nCoordSize
); i
++ )
1693 const Point
aPreviousEndPoint(GetPoint( seqCoordinates
[ rSrcPt
- 1 ], true, true));
1694 const Point
aControlQ(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1695 const Point
aEnd(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1696 const Point
aControlA((aPreviousEndPoint
+ (aControlQ
* 2)) / 3);
1697 const Point
aControlB(((aControlQ
* 2) + aEnd
) / 3);
1699 DBG_ASSERT(aNewB2DPolygon
.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1700 aNewB2DPolygon
.appendBezierSegment(
1701 basegfx::B2DPoint(aControlA
.X(), aControlA
.Y()),
1702 basegfx::B2DPoint(aControlB
.X(), aControlB
.Y()),
1703 basegfx::B2DPoint(aEnd
.X(), aEnd
.Y()));
1705 else // no previous point , do a moveto
1707 rSrcPt
++; // skip control point
1708 const Point
aEnd(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1710 DBG_ASSERT(aNewB2DPolygon
.count(), "EnhancedCustomShape2d::CreateSubPath: Error in adding Q control point (!)");
1711 aNewB2DPolygon
.append(basegfx::B2DPoint(aEnd
.X(), aEnd
.Y()));
1719 for ( sal_Int32
i(0L); ( i
< nPntCount
) && ( rSrcPt
< nCoordSize
); i
++ )
1721 const Point
aTempPoint(GetPoint( seqCoordinates
[ rSrcPt
++ ], true, true ));
1724 "lineTo: " << aTempPoint
.X() << ","
1726 aNewB2DPolygon
.append(basegfx::B2DPoint(aTempPoint
.X(), aTempPoint
.Y()));
1734 if(aNewB2DPolygon
.count() > 1L)
1736 // #i76201# Add conversion to closed polygon when first and last points are equal
1737 basegfx::tools::checkClosed(aNewB2DPolygon
);
1738 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1741 aNewB2DPolygon
.clear();
1744 case CLOCKWISEARCTO
:
1746 bool bClockwise
= ( nCommand
== CLOCKWISEARC
) || ( nCommand
== CLOCKWISEARCTO
);
1747 sal_uInt32 nXor
= bClockwise
? 3 : 2;
1748 for ( sal_uInt16 i
= 0; ( i
< nPntCount
) && ( ( rSrcPt
+ 3 ) < nCoordSize
); i
++ )
1750 Rectangle
aRect( GetPoint( seqCoordinates
[ rSrcPt
], true, true ), GetPoint( seqCoordinates
[ rSrcPt
+ 1 ], true, true ) );
1751 if ( aRect
.GetWidth() && aRect
.GetHeight() )
1753 Point
aCenter( aRect
.Center() );
1754 Point
aStart( GetPoint( seqCoordinates
[ (sal_uInt16
)( rSrcPt
+ nXor
) ], true, true ) );
1755 Point
aEnd( GetPoint( seqCoordinates
[ (sal_uInt16
)( rSrcPt
+ ( nXor
^ 1 ) ) ], true, true ) );
1756 aStart
.X() = (sal_Int32
)( ( (double)( aStart
.X() - aCenter
.X() ) ) ) + aCenter
.X();
1757 aStart
.Y() = (sal_Int32
)( ( (double)( aStart
.Y() - aCenter
.Y() ) ) ) + aCenter
.Y();
1758 aEnd
.X() = (sal_Int32
)( ( (double)( aEnd
.X() - aCenter
.X() ) ) ) + aCenter
.X();
1759 aEnd
.Y() = (sal_Int32
)( ( (double)( aEnd
.Y() - aCenter
.Y() ) ) ) + aCenter
.Y();
1760 aNewB2DPolygon
.append(CreateArc( aRect
, aStart
, aEnd
, bClockwise
));
1769 double fWR
, fHR
, fStartAngle
, fSwingAngle
;
1771 for ( sal_uInt16 i
= 0; ( i
< nPntCount
) && ( rSrcPt
+ 1 < nCoordSize
); i
++ )
1773 GetParameter ( fWR
, seqCoordinates
[ (sal_uInt16
)( rSrcPt
) ].First
, true, false );
1774 GetParameter ( fHR
, seqCoordinates
[ (sal_uInt16
)( rSrcPt
) ].Second
, false, true );
1776 GetParameter ( fStartAngle
, seqCoordinates
[ (sal_uInt16
)( rSrcPt
+ 1) ].First
, false, false );
1777 GetParameter ( fSwingAngle
, seqCoordinates
[ (sal_uInt16
)( rSrcPt
+ 1 ) ].Second
, false, false );
1779 // Convert angles to radians, but don't do any scaling / translation yet.
1781 fStartAngle
*= F_PI180
;
1782 fSwingAngle
*= F_PI180
;
1784 OSL_TRACE("ARCANGLETO scale: %f x %f angles: %f, %f", fWR
, fHR
, fStartAngle
, fSwingAngle
);
1786 bool bClockwise
= fSwingAngle
>= 0.0;
1788 if (aNewB2DPolygon
.count() > 0)
1790 basegfx::B2DPoint
aStartPointB2D( aNewB2DPolygon
.getB2DPoint(aNewB2DPolygon
.count() - 1 ) );
1791 Point
aStartPoint( 0, 0 );
1793 double fT
= atan2((fWR
*sin(fStartAngle
)), (fHR
*cos(fStartAngle
)));
1794 double fTE
= atan2((fWR
*sin(fStartAngle
+ fSwingAngle
)), fHR
*cos(fStartAngle
+ fSwingAngle
));
1796 OSL_TRACE("ARCANGLETO angles: %f, %f --> parameters: %f, %f", fStartAngle
, fSwingAngle
, fT
, fTE
);
1801 Rectangle
aRect ( Point ( aStartPoint
.getX() - fWR
*cos(fT
) - fWR
, aStartPoint
.getY() - fHR
*sin(fT
) - fHR
),
1802 Point ( aStartPoint
.getX() - fWR
*cos(fT
) + fWR
, aStartPoint
.getY() - fHR
*sin(fT
) + fHR
) );
1804 Point
aEndPoint ( aStartPoint
.getX() - fWR
*(cos(fT
) - cos(fTE
)), aStartPoint
.getY() - fHR
*(sin(fT
) - sin(fTE
)) );
1808 "ARCANGLETO rect: " << aRect
.Left() << ", "
1809 << aRect
.Top() << " x " << aRect
.Right()
1810 << ", " << aRect
.Bottom() << " start: "
1811 << aStartPoint
.X() << ", "
1812 << aStartPoint
.Y() << " end: "
1813 << aEndPoint
.X() << ", " << aEndPoint
.Y()
1814 << " clockwise: " << int(bClockwise
));
1815 basegfx::B2DPolygon aArc
= CreateArc( aRect
, bClockwise
? aEndPoint
: aStartPoint
, bClockwise
? aStartPoint
: aEndPoint
, bClockwise
, aStartPoint
== aEndPoint
&& fSwingAngle
> F_PI
);
1816 // Now that we have the arc, move it to aStartPointB2D.
1817 basegfx::B2DHomMatrix aMatrix
= basegfx::tools::createTranslateB2DHomMatrix(aStartPointB2D
.getX(), aStartPointB2D
.getY());
1818 aArc
.transform(aMatrix
);
1819 aNewB2DPolygon
.append(aArc
);
1827 case ELLIPTICALQUADRANTX
:
1828 case ELLIPTICALQUADRANTY
:
1830 bool bFirstDirection(true);
1831 basegfx::B2DPoint aControlPointA
;
1832 basegfx::B2DPoint aControlPointB
;
1834 for ( sal_uInt16 i
= 0; ( i
< nPntCount
) && ( rSrcPt
< nCoordSize
); i
++ )
1836 sal_uInt32 nModT
= ( nCommand
== ELLIPTICALQUADRANTX
) ? 1 : 0;
1837 Point
aCurrent( GetPoint( seqCoordinates
[ rSrcPt
], true, true ) );
1839 if ( rSrcPt
) // we need a previous point
1841 Point
aPrev( GetPoint( seqCoordinates
[ rSrcPt
- 1 ], true, true ) );
1843 nX
= aCurrent
.X() - aPrev
.X();
1844 nY
= aCurrent
.Y() - aPrev
.Y();
1845 if ( ( nY
^ nX
) & 0x80000000 )
1848 bFirstDirection
= true;
1849 else if ( !bFirstDirection
)
1855 bFirstDirection
= false;
1856 else if ( bFirstDirection
)
1859 if ( nModT
) // get the right corner
1869 sal_Int32 nXVec
= ( nX
- aPrev
.X() ) >> 1;
1870 sal_Int32 nYVec
= ( nY
- aPrev
.Y() ) >> 1;
1871 Point
aControl1( aPrev
.X() + nXVec
, aPrev
.Y() + nYVec
);
1873 aControlPointA
= basegfx::B2DPoint(aControl1
.X(), aControl1
.Y());
1875 nXVec
= ( nX
- aCurrent
.X() ) >> 1;
1876 nYVec
= ( nY
- aCurrent
.Y() ) >> 1;
1877 Point
aControl2( aCurrent
.X() + nXVec
, aCurrent
.Y() + nYVec
);
1879 aControlPointB
= basegfx::B2DPoint(aControl2
.X(), aControl2
.Y());
1881 aNewB2DPolygon
.appendBezierSegment(
1884 basegfx::B2DPoint(aCurrent
.X(), aCurrent
.Y()));
1888 aNewB2DPolygon
.append(basegfx::B2DPoint(aCurrent
.X(), aCurrent
.Y()));
1896 #ifdef DBG_CUSTOMSHAPE
1900 OStringBuffer
aString("CustomShapes::unknown PolyFlagValue :");
1901 aString
.append(static_cast<sal_Int32
>(nCommand
));
1902 OSL_FAIL(aString
.getStr());
1907 if ( nCommand
== ENDSUBPATH
)
1911 if ( rSegmentInd
== nSegInfoSize
)
1914 if(aNewB2DPolygon
.count() > 1L)
1916 // #i76201# Add conversion to closed polygon when first and last points are equal
1917 basegfx::tools::checkClosed(aNewB2DPolygon
);
1918 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1921 if(aNewB2DPolyPolygon
.count())
1923 if( !bLineGeometryNeededOnly
)
1925 // hack aNewB2DPolyPolygon to fill logic rect - this is
1926 // needed to produce gradient fills that look like mso
1927 aNewB2DPolygon
.clear();
1928 aNewB2DPolygon
.append(basegfx::B2DPoint(0,0));
1929 aNewB2DPolygon
.setClosed(true);
1930 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1932 aNewB2DPolygon
.clear();
1933 aNewB2DPolygon
.append(basegfx::B2DPoint(aLogicRect
.GetWidth(),
1934 aLogicRect
.GetHeight()));
1935 aNewB2DPolygon
.setClosed(true);
1936 aNewB2DPolyPolygon
.append(aNewB2DPolygon
);
1940 bool bForceCreateTwoObjects(false);
1942 if(!bSortFilledObjectsToBack
&& !aNewB2DPolyPolygon
.isClosed() && !bNoStroke
)
1944 bForceCreateTwoObjects
= true;
1947 if(bLineGeometryNeededOnly
)
1949 bForceCreateTwoObjects
= true;
1954 if(bForceCreateTwoObjects
|| bSortFilledObjectsToBack
)
1956 if(bFilled
&& !bNoFill
)
1958 basegfx::B2DPolyPolygon
aClosedPolyPolygon(aNewB2DPolyPolygon
);
1959 aClosedPolyPolygon
.setClosed(true);
1960 SdrPathObj
* pFill
= new SdrPathObj(OBJ_POLY
, aClosedPolyPolygon
, dBrightness
);
1961 SfxItemSet
aTempSet(*this);
1962 aTempSet
.Put(makeSdrShadowItem(false));
1963 aTempSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
1964 pFill
->SetMergedItemSet(aTempSet
);
1965 rObjectList
.push_back(pFill
);
1970 // there is no reason to use OBJ_PLIN here when the polygon is actually closed,
1971 // the non-fill is defined by XFILL_NONE. Since SdrPathObj::ImpForceKind() needs
1972 // to correct the polygon (here: open it) using the type, the last edge may get lost.
1973 // Thus, use a type that fits the polygon
1974 SdrPathObj
* pStroke
= new SdrPathObj(
1975 aNewB2DPolyPolygon
.isClosed() ? OBJ_POLY
: OBJ_PLIN
,
1976 aNewB2DPolyPolygon
, dBrightness
);
1977 SfxItemSet
aTempSet(*this);
1978 aTempSet
.Put(makeSdrShadowItem(false));
1979 aTempSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
1980 pStroke
->SetMergedItemSet(aTempSet
);
1981 rObjectList
.push_back(pStroke
);
1986 SdrPathObj
* pObj
= 0;
1987 SfxItemSet
aTempSet(*this);
1988 aTempSet
.Put(makeSdrShadowItem(false));
1992 // see comment above about OBJ_PLIN
1993 pObj
= new SdrPathObj(
1994 aNewB2DPolyPolygon
.isClosed() ? OBJ_POLY
: OBJ_PLIN
,
1995 aNewB2DPolyPolygon
, dBrightness
);
1996 aTempSet
.Put(XFillStyleItem(drawing::FillStyle_NONE
));
2000 aNewB2DPolyPolygon
.setClosed(true);
2001 pObj
= new SdrPathObj(OBJ_POLY
, aNewB2DPolyPolygon
, dBrightness
);
2006 aTempSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
2011 pObj
->SetMergedItemSet(aTempSet
);
2012 rObjectList
.push_back(pObj
);
2018 void CorrectCalloutArrows( MSO_SPT eSpType
, sal_uInt32 nLineObjectCount
, std::vector
< SdrPathObj
* >& vObjectList
)
2020 bool bAccent
= false;
2023 case mso_sptCallout1
:
2024 case mso_sptBorderCallout1
:
2025 case mso_sptCallout90
:
2026 case mso_sptBorderCallout90
:
2030 case mso_sptAccentCallout1
:
2031 case mso_sptAccentBorderCallout1
:
2032 case mso_sptAccentCallout90
:
2033 case mso_sptAccentBorderCallout90
:
2035 sal_uInt32 i
, nLine
= 0;
2036 for ( i
= 0; i
< vObjectList
.size(); i
++ )
2038 SdrPathObj
* pObj( vObjectList
[ i
] );
2042 if ( nLine
== nLineObjectCount
)
2044 pObj
->ClearMergedItem( XATTR_LINESTART
);
2045 pObj
->ClearMergedItem( XATTR_LINEEND
);
2052 // switch start & end
2053 case mso_sptAccentCallout2
:
2054 case mso_sptAccentBorderCallout2
:
2057 case mso_sptCallout2
:
2058 case mso_sptBorderCallout2
:
2060 sal_uInt32 i
, nLine
= 0;
2061 for ( i
= 0; i
< vObjectList
.size(); i
++ )
2063 SdrPathObj
* pObj( vObjectList
[ i
] );
2068 pObj
->ClearMergedItem( XATTR_LINEEND
);
2069 else if ( ( bAccent
&& ( nLine
== nLineObjectCount
- 1 ) ) || ( !bAccent
&& ( nLine
== nLineObjectCount
) ) )
2070 pObj
->ClearMergedItem( XATTR_LINESTART
);
2073 pObj
->ClearMergedItem( XATTR_LINESTART
);
2074 pObj
->ClearMergedItem( XATTR_LINEEND
);
2081 case mso_sptAccentCallout3
:
2082 case mso_sptAccentBorderCallout3
:
2085 case mso_sptCallout3
:
2086 case mso_sptBorderCallout3
:
2088 sal_uInt32 i
, nLine
= 0;
2089 for ( i
= 0; i
< vObjectList
.size(); i
++ )
2091 SdrPathObj
* pObj( vObjectList
[ i
] );
2096 pObj
->ClearMergedItem( XATTR_LINESTART
);
2097 pObj
->ClearMergedItem( XATTR_LINEEND
);
2100 EnhancedCustomShape2d::SwapStartAndEndArrow( pObj
);
2110 void EnhancedCustomShape2d::AdaptObjColor(SdrPathObj
& rObj
, const SfxItemSet
& rCustomShapeSet
,
2111 sal_uInt32
& nColorIndex
, sal_uInt32 nColorCount
)
2113 if ( !rObj
.IsLine() )
2115 const drawing::FillStyle eFillStyle
= static_cast<const XFillStyleItem
&>(rObj
.GetMergedItem(XATTR_FILLSTYLE
)).GetValue();
2116 switch( eFillStyle
)
2119 case drawing::FillStyle_SOLID
:
2122 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2124 aFillColor
= GetColorData(
2125 static_cast<const XFillColorItem
&>(rCustomShapeSet
.Get( XATTR_FILLCOLOR
)).GetColorValue(),
2126 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() );
2127 rObj
.SetMergedItem( XFillColorItem( "", aFillColor
) );
2131 case drawing::FillStyle_GRADIENT
:
2133 XGradient
aXGradient(static_cast<const XFillGradientItem
&>(rObj
.GetMergedItem(XATTR_FILLGRADIENT
)).GetGradientValue());
2134 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2136 aXGradient
.SetStartColor(
2138 aXGradient
.GetStartColor(),
2139 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() ));
2140 aXGradient
.SetEndColor(
2142 aXGradient
.GetEndColor(),
2143 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() ));
2146 rObj
.SetMergedItem( XFillGradientItem( "", aXGradient
) );
2149 case drawing::FillStyle_HATCH
:
2151 XHatch
aXHatch(static_cast<const XFillHatchItem
&>(rObj
.GetMergedItem(XATTR_FILLHATCH
)).GetHatchValue());
2152 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2157 std::min(nColorIndex
, nColorCount
-1), rObj
.GetBrightness() ));
2160 rObj
.SetMergedItem( XFillHatchItem( "", aXHatch
) );
2163 case drawing::FillStyle_BITMAP
:
2165 if ( nColorCount
|| rObj
.GetBrightness() != 1.0 )
2167 Bitmap
aBitmap(static_cast<const XFillBitmapItem
&>(rObj
.GetMergedItem(XATTR_FILLBITMAP
)).GetGraphicObject().GetGraphic().GetBitmapEx().GetBitmap());
2170 static_cast< short > ( GetLuminanceChange(
2171 std::min(nColorIndex
, nColorCount
-1))));
2173 rObj
.SetMergedItem(XFillBitmapItem(OUString(), Graphic(aBitmap
)));
2180 if ( nColorIndex
< nColorCount
)
2185 SdrObject
* EnhancedCustomShape2d::CreatePathObj( bool bLineGeometryNeededOnly
)
2187 sal_Int32 nCoordSize
= seqCoordinates
.getLength();
2191 sal_uInt16 nSrcPt
= 0;
2192 sal_uInt16 nSegmentInd
= 0;
2194 std::vector
< SdrPathObj
* > vObjectList
;
2195 bool bSortFilledObjectsToBack
= SortFilledObjectsToBackByDefault( eSpType
);
2197 sal_Int32 nSubPathIndex
= 0;
2199 while( nSegmentInd
<= seqSegments
.getLength() )
2201 CreateSubPath( nSrcPt
, nSegmentInd
, vObjectList
, bLineGeometryNeededOnly
, bSortFilledObjectsToBack
, nSubPathIndex
);
2205 SdrObject
* pRet
= NULL
;
2207 if ( !vObjectList
.empty() )
2209 const SfxItemSet
& rCustomShapeSet
= pCustomShapeObj
->GetMergedItemSet();
2210 sal_uInt32 nColorCount
= nColorData
>> 28;
2211 sal_uInt32 nColorIndex
= 0;
2213 // #i37011# remove invisible objects
2214 if(!vObjectList
.empty())
2216 std::vector
< SdrPathObj
* > vTempList
;
2218 for(size_t i
= 0; i
< vObjectList
.size(); ++i
)
2220 SdrPathObj
* pObj(vObjectList
[i
]);
2221 const drawing::LineStyle eLineStyle
=static_cast<const XLineStyleItem
&>(pObj
->GetMergedItem(XATTR_LINESTYLE
)).GetValue();
2222 const drawing::FillStyle eFillStyle
= static_cast<const XFillStyleItem
&>(pObj
->GetMergedItem(XATTR_FILLSTYLE
)).GetValue();
2224 //SJ: #i40600# if bLineGeometryNeededOnly is set linystyle does not matter
2225 if( !bLineGeometryNeededOnly
&& ( drawing::LineStyle_NONE
== eLineStyle
) && ( drawing::FillStyle_NONE
== eFillStyle
) )
2228 vTempList
.push_back(pObj
);
2231 vObjectList
= vTempList
;
2234 if(1L == vObjectList
.size())
2236 // a single object, correct some values
2237 AdaptObjColor(*vObjectList
[0L],rCustomShapeSet
,nColorIndex
,nColorCount
);
2241 sal_Int32 nLineObjectCount
= 0;
2242 sal_Int32 nAreaObjectCount
= 0;
2244 // correct some values and collect content data
2245 for ( size_t i
= 0; i
< vObjectList
.size(); ++i
)
2247 SdrPathObj
* pObj( vObjectList
[ i
] );
2256 AdaptObjColor(*pObj
,rCustomShapeSet
,nColorIndex
,nColorCount
);
2260 // #i88870# correct line arrows for callouts
2261 if ( nLineObjectCount
)
2262 CorrectCalloutArrows( eSpType
, nLineObjectCount
, vObjectList
);
2264 // sort objects so that filled ones are in front. Necessary
2265 // for some strange objects
2266 if ( bSortFilledObjectsToBack
)
2268 std::vector
< SdrPathObj
* > vTempList
;
2269 vTempList
.reserve(vObjectList
.size());
2271 for ( size_t i
= 0; i
< vObjectList
.size(); ++i
)
2273 SdrPathObj
* pObj( vObjectList
[ i
] );
2275 if ( !pObj
->IsLine() )
2277 vTempList
.push_back(pObj
);
2281 for ( size_t i
= 0; i
< vObjectList
.size(); ++i
)
2283 SdrPathObj
* pObj( vObjectList
[ i
] );
2285 if ( pObj
->IsLine() )
2287 vTempList
.push_back(pObj
);
2291 vObjectList
= vTempList
;
2297 if(!vObjectList
.empty())
2299 // copy remaining objects to pRet
2300 if(vObjectList
.size() > 1)
2302 pRet
= new SdrObjGroup
;
2304 for (size_t i
= 0; i
< vObjectList
.size(); ++i
)
2306 SdrObject
* pObj(vObjectList
[i
]);
2307 pRet
->GetSubList()->NbcInsertObject(pObj
);
2310 else if(1 == vObjectList
.size())
2312 pRet
= vObjectList
[0L];
2317 // move to target position
2318 Rectangle
aCurRect(pRet
->GetSnapRect());
2319 aCurRect
.Move(aLogicRect
.Left(), aLogicRect
.Top());
2320 pRet
->NbcSetSnapRect(aCurRect
);
2327 SdrObject
* EnhancedCustomShape2d::CreateObject( bool bLineGeometryNeededOnly
)
2329 SdrObject
* pRet
= NULL
;
2331 if ( eSpType
== mso_sptRectangle
)
2333 pRet
= new SdrRectObj( aLogicRect
);
2334 pRet
->SetMergedItemSet( *this );
2337 pRet
= CreatePathObj( bLineGeometryNeededOnly
);
2342 void EnhancedCustomShape2d::ApplyGluePoints( SdrObject
* pObj
)
2344 if ( pObj
&& seqGluePoints
.getLength() )
2346 sal_uInt32 i
, nCount
= seqGluePoints
.getLength();
2347 for ( i
= 0; i
< nCount
; i
++ )
2349 SdrGluePoint aGluePoint
;
2351 aGluePoint
.SetPos( GetPoint( seqGluePoints
[ i
], true, true ) );
2352 aGluePoint
.SetPercent( false );
2353 aGluePoint
.SetAlign( SdrAlign::VERT_TOP
| SdrAlign::HORZ_LEFT
);
2354 aGluePoint
.SetEscDir( SdrEscapeDirection::SMART
);
2355 SdrGluePointList
* pList
= pObj
->ForceGluePointList();
2357 /* sal_uInt16 nId = */ pList
->Insert( aGluePoint
);
2362 bool EnhancedCustomShape2d::IsPostRotate() const
2364 return pCustomShapeObj
->ISA( SdrObjCustomShape
) && static_cast<SdrObjCustomShape
*>(pCustomShapeObj
)->IsPostRotate();
2367 SdrObject
* EnhancedCustomShape2d::CreateLineGeometry()
2369 return CreateObject( true );
2373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */