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 "LabelPositionHelper.hxx"
21 #include "PlottingPositionHelper.hxx"
22 #include "CommonConverters.hxx"
23 #include "PropertyMapper.hxx"
24 #include "AbstractShapeFactory.hxx"
26 #include "RelativeSizeHelper.hxx"
27 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
28 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
32 using namespace ::com::sun::star
;
33 using namespace ::com::sun::star::chart2
;
35 LabelPositionHelper::LabelPositionHelper(
36 PlottingPositionHelper
* pPosHelper
37 , sal_Int32 nDimensionCount
38 , const uno::Reference
< drawing::XShapes
>& xLogicTarget
39 , AbstractShapeFactory
* pShapeFactory
)
40 : m_pPosHelper(pPosHelper
)
41 , m_nDimensionCount(nDimensionCount
)
42 , m_xLogicTarget(xLogicTarget
)
43 , m_pShapeFactory(pShapeFactory
)
47 LabelPositionHelper::~LabelPositionHelper()
51 awt::Point
LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D
& rScenePosition3D
) const
53 return PlottingPositionHelper::transformSceneToScreenPosition(
54 rScenePosition3D
, m_xLogicTarget
, m_pShapeFactory
, m_nDimensionCount
);
57 void LabelPositionHelper::changeTextAdjustment( tAnySequence
& rPropValues
, const tNameSequence
& rPropNames
, LabelAlignment eAlignment
)
59 //HorizontalAdjustment
61 drawing::TextHorizontalAdjust eHorizontalAdjust
= drawing::TextHorizontalAdjust_CENTER
;
62 if( LABEL_ALIGN_RIGHT
==eAlignment
|| LABEL_ALIGN_RIGHT_TOP
==eAlignment
|| LABEL_ALIGN_RIGHT_BOTTOM
==eAlignment
)
63 eHorizontalAdjust
= drawing::TextHorizontalAdjust_LEFT
;
64 else if( LABEL_ALIGN_LEFT
==eAlignment
|| LABEL_ALIGN_LEFT_TOP
==eAlignment
|| LABEL_ALIGN_LEFT_BOTTOM
==eAlignment
)
65 eHorizontalAdjust
= drawing::TextHorizontalAdjust_RIGHT
;
66 uno::Any
* pHorizontalAdjustAny
= PropertyMapper::getValuePointer(rPropValues
,rPropNames
,"TextHorizontalAdjust");
67 if(pHorizontalAdjustAny
)
68 *pHorizontalAdjustAny
= uno::makeAny(eHorizontalAdjust
);
73 drawing::TextVerticalAdjust eVerticalAdjust
= drawing::TextVerticalAdjust_CENTER
;
74 if( LABEL_ALIGN_TOP
==eAlignment
|| LABEL_ALIGN_RIGHT_TOP
==eAlignment
|| LABEL_ALIGN_LEFT_TOP
==eAlignment
)
75 eVerticalAdjust
= drawing::TextVerticalAdjust_BOTTOM
;
76 else if( LABEL_ALIGN_BOTTOM
==eAlignment
|| LABEL_ALIGN_RIGHT_BOTTOM
==eAlignment
|| LABEL_ALIGN_LEFT_BOTTOM
==eAlignment
)
77 eVerticalAdjust
= drawing::TextVerticalAdjust_TOP
;
78 uno::Any
* pVerticalAdjustAny
= PropertyMapper::getValuePointer(rPropValues
,rPropNames
,"TextVerticalAdjust");
79 if(pVerticalAdjustAny
)
80 *pVerticalAdjustAny
= uno::makeAny(eVerticalAdjust
);
84 void lcl_doDynamicFontResize( uno::Any
* pAOldAndNewFontHeightAny
85 , const awt::Size
& rOldReferenceSize
86 , const awt::Size
& rNewReferenceSize
)
88 double fOldFontHeight
= 0;
89 if( pAOldAndNewFontHeightAny
&& ( *pAOldAndNewFontHeightAny
>>= fOldFontHeight
) )
91 double fNewFontHeight
= RelativeSizeHelper::calculate( fOldFontHeight
, rOldReferenceSize
, rNewReferenceSize
);
92 *pAOldAndNewFontHeightAny
= uno::makeAny(fNewFontHeight
);
96 void LabelPositionHelper::doDynamicFontResize( tAnySequence
& rPropValues
97 , const tNameSequence
& rPropNames
98 , const uno::Reference
< beans::XPropertySet
>& xAxisModelProps
99 , const awt::Size
& rNewReferenceSize
102 //handle dynamic font resize:
103 awt::Size aOldReferenceSize
;
104 if( xAxisModelProps
->getPropertyValue( "ReferencePageSize") >>= aOldReferenceSize
)
106 uno::Any
* pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, "CharHeight" );
107 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
108 pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, "CharHeightAsian" );
109 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
110 pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, "CharHeightComplex" );
111 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
118 void lcl_correctRotation_Left( double& rfXCorrection
, double& rfYCorrection
119 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
121 //correct label positions for labels on a left side of something with a right centered alignment
122 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
123 if( fAnglePositiveDegree
==0.0 )
126 else if( fAnglePositiveDegree
<= 90.0 )
128 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
129 if( bRotateAroundCenter
)
130 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
132 else if( fAnglePositiveDegree
<= 180.0 )
134 double beta
= fAnglePi
-F_PI
/2.0;
135 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
)
136 -aSize
.Height
*rtl::math::cos( beta
)/2.0;
137 if( bRotateAroundCenter
)
138 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)/2.0;
140 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
);
142 else if( fAnglePositiveDegree
<= 270.0 )
144 double beta
= fAnglePi
- F_PI
;
145 rfXCorrection
= -aSize
.Width
*rtl::math::cos( beta
)
146 -aSize
.Height
*rtl::math::sin( beta
)/2.0;
147 if( bRotateAroundCenter
)
148 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
150 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
);
154 double beta
= 2*F_PI
- fAnglePi
;
155 rfXCorrection
= -aSize
.Height
*rtl::math::sin( beta
)/2.0;
156 if( bRotateAroundCenter
)
157 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
161 void lcl_correctRotation_Right( double& rfXCorrection
, double& rfYCorrection
162 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
164 //correct label positions for labels on a right side of something with a left centered alignment
165 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
166 if( fAnglePositiveDegree
== 0.0 )
169 else if( fAnglePositiveDegree
<= 90.0 )
171 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
172 if( bRotateAroundCenter
)
173 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
175 else if( fAnglePositiveDegree
<= 180.0 )
177 double beta
= F_PI
- fAnglePi
;
178 rfXCorrection
= aSize
.Width
*rtl::math::cos( beta
)
179 + aSize
.Height
*rtl::math::sin( beta
)/2.0;
180 if( bRotateAroundCenter
)
181 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
183 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
);
185 else if( fAnglePositiveDegree
<= 270.0 )
187 double beta
= 3*F_PI
/2.0 - fAnglePi
;
188 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
)
189 +aSize
.Height
*rtl::math::cos( beta
)/2.0;
190 if( bRotateAroundCenter
)
191 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)/2.0;
193 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
);
197 rfXCorrection
= aSize
.Height
*rtl::math::sin( 2*F_PI
- fAnglePi
)/2.0;
198 if( bRotateAroundCenter
)
199 rfYCorrection
= -aSize
.Width
*rtl::math::sin( 2*F_PI
- fAnglePi
)/2.0;
203 void lcl_correctRotation_Top( double& rfXCorrection
, double& rfYCorrection
204 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
206 //correct label positions for labels on top of something with a bottom centered alignment
207 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
208 if( fAnglePositiveDegree
== 0.0 )
211 else if( fAnglePositiveDegree
<= 90.0 )
213 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
214 if( !bRotateAroundCenter
)
215 rfXCorrection
+= aSize
.Width
*rtl::math::cos( fAnglePi
)/2.0;
216 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
218 else if( fAnglePositiveDegree
<= 180.0 )
220 double beta
= fAnglePi
- F_PI
/2.0;
221 rfXCorrection
= aSize
.Height
*rtl::math::cos( beta
)/2.0;
222 if( !bRotateAroundCenter
)
223 rfXCorrection
-= aSize
.Width
*rtl::math::sin( beta
)/2.0;
224 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)/2.0
225 - aSize
.Height
*rtl::math::sin( beta
);
227 else if( fAnglePositiveDegree
<= 270.0 )
229 double beta
= fAnglePi
- F_PI
;
230 rfXCorrection
= -aSize
.Height
*rtl::math::sin( beta
)/2.0;
231 if( !bRotateAroundCenter
)
232 rfXCorrection
+= aSize
.Width
*rtl::math::cos( beta
)/2.0;
233 rfYCorrection
= -aSize
.Width
*rtl::math::sin( beta
)/2.0
234 -aSize
.Height
*rtl::math::cos( beta
);
238 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
239 if( !bRotateAroundCenter
)
240 rfXCorrection
-= aSize
.Width
*rtl::math::cos( fAnglePi
)/2.0;
241 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
245 void lcl_correctRotation_Bottom( double& rfXCorrection
, double& rfYCorrection
246 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
248 //correct label positions for labels below something with a top centered alignment
249 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
250 if( fAnglePositiveDegree
==0.0 )
253 else if( fAnglePositiveDegree
<= 90.0 )
255 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
)/2.0;
256 if( !bRotateAroundCenter
)
257 rfXCorrection
-= aSize
.Width
*rtl::math::cos( fAnglePi
)/2.0;
258 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
)/2.0;
260 else if( fAnglePositiveDegree
<= 180.0 )
262 double beta
= fAnglePi
-F_PI
/2.0;
263 rfXCorrection
= -aSize
.Height
*rtl::math::cos( beta
)/2.0;
264 if( !bRotateAroundCenter
)
265 rfXCorrection
+= aSize
.Width
*rtl::math::sin( beta
)/2.0;
266 rfYCorrection
= aSize
.Width
*rtl::math::cos( beta
)/2.0
267 +aSize
.Height
*rtl::math::sin( beta
);
269 else if( fAnglePositiveDegree
<= 270.0 )
271 double beta
= 3*F_PI
/2.0 - fAnglePi
;
272 rfXCorrection
= aSize
.Height
*rtl::math::cos( beta
)/2.0;
273 if( !bRotateAroundCenter
)
274 rfXCorrection
-= aSize
.Width
*rtl::math::sin( beta
)/2.0;
275 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
)
276 +aSize
.Width
*rtl::math::cos( beta
)/2.0;
280 double beta
= 2*F_PI
- fAnglePi
;
281 rfXCorrection
= aSize
.Height
*rtl::math::sin( beta
)/2.0;
282 if( !bRotateAroundCenter
)
283 rfXCorrection
+= aSize
.Width
*rtl::math::cos( beta
)/2.0;
284 rfYCorrection
= aSize
.Width
*rtl::math::sin( beta
)/2.0;
288 void lcl_correctRotation_Left_Top( double& rfXCorrection
, double& rfYCorrection
289 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
291 //correct position for labels at the left top corner of something with a bottom right alignment
292 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
293 if( fAnglePositiveDegree
==0.0 )
296 else if( fAnglePositiveDegree
<= 90.0 )
298 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
);
300 else if( fAnglePositiveDegree
<= 180.0 )
302 double beta
= fAnglePi
-F_PI
/2.0;
303 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
);
304 rfYCorrection
= -aSize
.Height
*rtl::math::sin( beta
)
305 -aSize
.Width
*rtl::math::cos( beta
);
307 else if( fAnglePositiveDegree
<= 270.0 )
309 double beta
= 3*F_PI
/2.0 - fAnglePi
;
310 rfXCorrection
= -aSize
.Height
*rtl::math::cos( beta
)
311 -aSize
.Width
*rtl::math::sin( beta
);
312 rfYCorrection
= -aSize
.Height
*rtl::math::sin( beta
);
316 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
);
320 void lcl_correctRotation_Left_Bottom( double& rfXCorrection
, double& rfYCorrection
321 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
323 //correct position for labels at the left bottom corner of something with a top right alignment
324 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
325 if( fAnglePositiveDegree
==0.0 )
328 else if( fAnglePositiveDegree
<= 90.0 )
330 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
);
332 else if( fAnglePositiveDegree
<= 180.0 )
334 double beta
= fAnglePi
-F_PI
/2.0;
335 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
)
336 -aSize
.Height
*rtl::math::cos( beta
);
337 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
);
339 else if( fAnglePositiveDegree
<= 270.0 )
341 double beta
= 3*F_PI
/2.0 - fAnglePi
;
342 rfXCorrection
= -aSize
.Width
*rtl::math::sin( beta
);
343 rfYCorrection
= aSize
.Width
*rtl::math::cos( beta
)
344 +aSize
.Height
*rtl::math::sin( beta
);
348 rfYCorrection
= -aSize
.Width
*rtl::math::sin( fAnglePi
);
352 void lcl_correctRotation_Right_Top( double& rfXCorrection
, double& rfYCorrection
353 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
355 //correct position for labels at the right top corner of something with a bottom left alignment
356 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
357 if( fAnglePositiveDegree
==0.0 )
360 else if( fAnglePositiveDegree
<= 90.0 )
362 rfXCorrection
= aSize
.Height
*rtl::math::sin( fAnglePi
);
364 else if( fAnglePositiveDegree
<= 180.0 )
366 double beta
= fAnglePi
-F_PI
/2.0;
367 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
)
368 +aSize
.Height
*rtl::math::cos( beta
);
369 rfYCorrection
= -aSize
.Height
*rtl::math::sin( beta
);
371 else if( fAnglePositiveDegree
<= 270.0 )
373 double beta
= 3*F_PI
/2.0 - fAnglePi
;
374 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
);
375 rfYCorrection
= -aSize
.Width
*rtl::math::cos( beta
)
376 -aSize
.Height
*rtl::math::sin( beta
);
380 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
);
384 void lcl_correctRotation_Right_Bottom( double& rfXCorrection
, double& rfYCorrection
385 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
387 //correct position for labels at the right bottom corner of something with a top left alignment
388 double fAnglePi
= fAnglePositiveDegree
*F_PI
/180.0;
389 if( fAnglePositiveDegree
==0.0 )
392 else if( fAnglePositiveDegree
<= 90.0 )
394 rfYCorrection
= aSize
.Width
*rtl::math::sin( fAnglePi
);
396 else if( fAnglePositiveDegree
<= 180.0 )
398 double beta
= fAnglePi
-F_PI
/2.0;
399 rfXCorrection
= aSize
.Width
*rtl::math::sin( beta
);
400 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
)
401 +aSize
.Width
*rtl::math::cos( beta
);
403 else if( fAnglePositiveDegree
<= 270.0 )
405 double beta
= 3*F_PI
/2.0 - fAnglePi
;
406 rfXCorrection
= aSize
.Height
*rtl::math::cos( beta
)
407 +aSize
.Width
*rtl::math::sin( beta
);
408 rfYCorrection
= aSize
.Height
*rtl::math::sin( beta
);
412 rfXCorrection
= -aSize
.Height
*rtl::math::sin( fAnglePi
);
416 }//end anonymous namespace
418 void LabelPositionHelper::correctPositionForRotation( const uno::Reference
< drawing::XShape
>& xShape2DText
419 , LabelAlignment eLabelAlignment
, const double fRotationAngle
, bool bRotateAroundCenter
)
421 if( !xShape2DText
.is() )
424 awt::Point aOldPos
= xShape2DText
->getPosition();
425 awt::Size aSize
= xShape2DText
->getSize();
427 double fYCorrection
= 0.0;
428 double fXCorrection
= 0.0;
430 double fAnglePositiveDegree
= fRotationAngle
;
431 while(fAnglePositiveDegree
<0.0)
432 fAnglePositiveDegree
+=360.0;
434 switch(eLabelAlignment
)
436 case LABEL_ALIGN_LEFT
:
437 lcl_correctRotation_Left( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
439 case LABEL_ALIGN_RIGHT
:
440 lcl_correctRotation_Right( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
442 case LABEL_ALIGN_TOP
:
443 lcl_correctRotation_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
445 case LABEL_ALIGN_BOTTOM
:
446 lcl_correctRotation_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
448 case LABEL_ALIGN_LEFT_TOP
:
449 lcl_correctRotation_Left_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
451 case LABEL_ALIGN_LEFT_BOTTOM
:
452 lcl_correctRotation_Left_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
454 case LABEL_ALIGN_RIGHT_TOP
:
455 lcl_correctRotation_Right_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
457 case LABEL_ALIGN_RIGHT_BOTTOM
:
458 lcl_correctRotation_Right_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
460 default: //LABEL_ALIGN_CENTER
464 xShape2DText
->setPosition( awt::Point(
465 static_cast<sal_Int32
>(aOldPos
.X
+ fXCorrection
)
466 , static_cast<sal_Int32
>(aOldPos
.Y
+ fYCorrection
) ) );
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */