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