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 <PropertyMapper.hxx>
23 #include <RelativeSizeHelper.hxx>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
26 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
33 using namespace ::com::sun::star
;
35 LabelPositionHelper::LabelPositionHelper(
36 sal_Int32 nDimensionCount
37 , rtl::Reference
<SvxShapeGroupAnyD
> xLogicTarget
)
38 : m_nDimensionCount(nDimensionCount
)
39 , m_xLogicTarget(std::move(xLogicTarget
))
43 LabelPositionHelper::~LabelPositionHelper()
47 awt::Point
LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D
& rScenePosition3D
) const
49 return PlottingPositionHelper::transformSceneToScreenPosition(
50 rScenePosition3D
, m_xLogicTarget
, m_nDimensionCount
);
53 void LabelPositionHelper::changeTextAdjustment( tAnySequence
& rPropValues
, const tNameSequence
& rPropNames
, LabelAlignment eAlignment
)
55 uno::Any
* pHorizontalAdjustAny
56 = PropertyMapper::getValuePointer(rPropValues
, rPropNames
, u
"TextHorizontalAdjust");
57 if (pHorizontalAdjustAny
)
59 drawing::TextHorizontalAdjust eHorizontalAdjust
= drawing::TextHorizontalAdjust_CENTER
;
60 if( eAlignment
==LABEL_ALIGN_RIGHT
|| eAlignment
==LABEL_ALIGN_RIGHT_TOP
|| eAlignment
==LABEL_ALIGN_RIGHT_BOTTOM
)
61 eHorizontalAdjust
= drawing::TextHorizontalAdjust_LEFT
;
62 else if( eAlignment
==LABEL_ALIGN_LEFT
|| eAlignment
==LABEL_ALIGN_LEFT_TOP
|| eAlignment
==LABEL_ALIGN_LEFT_BOTTOM
)
63 eHorizontalAdjust
= drawing::TextHorizontalAdjust_RIGHT
;
64 *pHorizontalAdjustAny
<<= eHorizontalAdjust
;
67 uno::Any
* pVerticalAdjustAny
68 = PropertyMapper::getValuePointer(rPropValues
, rPropNames
, u
"TextVerticalAdjust");
69 if (pVerticalAdjustAny
)
71 drawing::TextVerticalAdjust eVerticalAdjust
= drawing::TextVerticalAdjust_CENTER
;
72 if( eAlignment
==LABEL_ALIGN_TOP
|| eAlignment
==LABEL_ALIGN_RIGHT_TOP
|| eAlignment
==LABEL_ALIGN_LEFT_TOP
)
73 eVerticalAdjust
= drawing::TextVerticalAdjust_BOTTOM
;
74 else if( eAlignment
==LABEL_ALIGN_BOTTOM
|| eAlignment
==LABEL_ALIGN_RIGHT_BOTTOM
|| eAlignment
==LABEL_ALIGN_LEFT_BOTTOM
)
75 eVerticalAdjust
= drawing::TextVerticalAdjust_TOP
;
76 *pVerticalAdjustAny
<<= eVerticalAdjust
;
80 static void lcl_doDynamicFontResize( uno::Any
* pAOldAndNewFontHeightAny
81 , const awt::Size
& rOldReferenceSize
82 , const awt::Size
& rNewReferenceSize
)
84 double fOldFontHeight
= 0;
85 if( pAOldAndNewFontHeightAny
&& ( *pAOldAndNewFontHeightAny
>>= fOldFontHeight
) )
87 double fNewFontHeight
= RelativeSizeHelper::calculate( fOldFontHeight
, rOldReferenceSize
, rNewReferenceSize
);
88 *pAOldAndNewFontHeightAny
<<= fNewFontHeight
;
92 void LabelPositionHelper::doDynamicFontResize( tAnySequence
& rPropValues
93 , const tNameSequence
& rPropNames
94 , const uno::Reference
< beans::XPropertySet
>& xAxisModelProps
95 , const awt::Size
& rNewReferenceSize
98 //handle dynamic font resize:
99 awt::Size aOldReferenceSize
;
100 if( xAxisModelProps
->getPropertyValue( u
"ReferencePageSize"_ustr
) >>= aOldReferenceSize
)
102 uno::Any
* pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, u
"CharHeight" );
103 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
104 pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, u
"CharHeightAsian" );
105 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
106 pAOldAndNewFontHeightAny
= PropertyMapper::getValuePointer( rPropValues
, rPropNames
, u
"CharHeightComplex" );
107 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny
, aOldReferenceSize
, rNewReferenceSize
);
114 void lcl_correctRotation_Left( double& rfXCorrection
, double& rfYCorrection
115 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
117 //correct label positions for labels on a left side of something with a right centered alignment
118 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
119 if( fAnglePositiveDegree
==0.0 )
122 else if( fAnglePositiveDegree
<= 90.0 )
124 rfXCorrection
= -aSize
.Height
*std::sin( fAnglePi
)/2.0;
125 if( bRotateAroundCenter
)
126 rfYCorrection
= -aSize
.Width
*std::sin( fAnglePi
)/2.0;
128 else if( fAnglePositiveDegree
<= 180.0 )
130 double beta
= fAnglePi
-M_PI_2
;
131 rfXCorrection
= -aSize
.Width
*std::sin( beta
)
132 -aSize
.Height
*std::cos( beta
)/2.0;
133 if( bRotateAroundCenter
)
134 rfYCorrection
= -aSize
.Width
*std::cos( beta
)/2.0;
136 rfYCorrection
= -aSize
.Width
*std::cos( beta
);
138 else if( fAnglePositiveDegree
<= 270.0 )
140 double beta
= fAnglePi
- M_PI
;
141 rfXCorrection
= -aSize
.Width
*std::cos( beta
)
142 -aSize
.Height
*std::sin( beta
)/2.0;
143 if( bRotateAroundCenter
)
144 rfYCorrection
= aSize
.Width
*std::sin( beta
)/2.0;
146 rfYCorrection
= aSize
.Width
*std::sin( beta
);
150 double beta
= 2*M_PI
- fAnglePi
;
151 rfXCorrection
= -aSize
.Height
*std::sin( beta
)/2.0;
152 if( bRotateAroundCenter
)
153 rfYCorrection
= aSize
.Width
*std::sin( beta
)/2.0;
157 void lcl_correctRotation_Right( double& rfXCorrection
, double& rfYCorrection
158 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
160 //correct label positions for labels on a right side of something with a left centered alignment
161 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
162 if( fAnglePositiveDegree
== 0.0 )
165 else if( fAnglePositiveDegree
<= 90.0 )
167 rfXCorrection
= aSize
.Height
*std::sin( fAnglePi
)/2.0;
168 if( bRotateAroundCenter
)
169 rfYCorrection
= aSize
.Width
*std::sin( fAnglePi
)/2.0;
171 else if( fAnglePositiveDegree
<= 180.0 )
173 double beta
= M_PI
- fAnglePi
;
174 rfXCorrection
= aSize
.Width
*std::cos( beta
)
175 + aSize
.Height
*std::sin( beta
)/2.0;
176 if( bRotateAroundCenter
)
177 rfYCorrection
= aSize
.Width
*std::sin( beta
)/2.0;
179 rfYCorrection
= aSize
.Width
*std::sin( beta
);
181 else if( fAnglePositiveDegree
<= 270.0 )
183 double beta
= 3*M_PI_2
- fAnglePi
;
184 rfXCorrection
= aSize
.Width
*std::sin( beta
)
185 +aSize
.Height
*std::cos( beta
)/2.0;
186 if( bRotateAroundCenter
)
187 rfYCorrection
= -aSize
.Width
*std::cos( beta
)/2.0;
189 rfYCorrection
= -aSize
.Width
*std::cos( beta
);
193 rfXCorrection
= aSize
.Height
*std::sin( 2*M_PI
- fAnglePi
)/2.0;
194 if( bRotateAroundCenter
)
195 rfYCorrection
= -aSize
.Width
*std::sin( 2*M_PI
- fAnglePi
)/2.0;
199 void lcl_correctRotation_Top( double& rfXCorrection
, double& rfYCorrection
200 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
202 //correct label positions for labels on top of something with a bottom centered alignment
203 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
204 if( fAnglePositiveDegree
== 0.0 )
207 else if( fAnglePositiveDegree
<= 90.0 )
209 rfXCorrection
= aSize
.Height
*std::sin( fAnglePi
)/2.0;
210 if( !bRotateAroundCenter
)
211 rfXCorrection
+= aSize
.Width
*std::cos( fAnglePi
)/2.0;
212 rfYCorrection
= -aSize
.Width
*std::sin( fAnglePi
)/2.0;
214 else if( fAnglePositiveDegree
<= 180.0 )
216 double beta
= fAnglePi
- M_PI_2
;
217 rfXCorrection
= aSize
.Height
*std::cos( beta
)/2.0;
218 if( !bRotateAroundCenter
)
219 rfXCorrection
-= aSize
.Width
*std::sin( beta
)/2.0;
220 rfYCorrection
= -aSize
.Width
*std::cos( beta
)/2.0
221 - aSize
.Height
*std::sin( beta
);
223 else if( fAnglePositiveDegree
<= 270.0 )
225 double beta
= fAnglePi
- M_PI
;
226 rfXCorrection
= -aSize
.Height
*std::sin( beta
)/2.0;
227 if( !bRotateAroundCenter
)
228 rfXCorrection
+= aSize
.Width
*std::cos( beta
)/2.0;
229 rfYCorrection
= -aSize
.Width
*std::sin( beta
)/2.0
230 -aSize
.Height
*std::cos( beta
);
234 rfXCorrection
= aSize
.Height
*std::sin( fAnglePi
)/2.0;
235 if( !bRotateAroundCenter
)
236 rfXCorrection
-= aSize
.Width
*std::cos( fAnglePi
)/2.0;
237 rfYCorrection
= aSize
.Width
*std::sin( fAnglePi
)/2.0;
241 void lcl_correctRotation_Bottom( double& rfXCorrection
, double& rfYCorrection
242 , double fAnglePositiveDegree
, const awt::Size
& aSize
, bool bRotateAroundCenter
)
244 //correct label positions for labels below something with a top centered alignment
245 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
246 if( fAnglePositiveDegree
==0.0 )
249 else if( fAnglePositiveDegree
<= 90.0 )
251 rfXCorrection
= -aSize
.Height
*std::sin( fAnglePi
)/2.0;
252 if( !bRotateAroundCenter
)
253 rfXCorrection
-= aSize
.Width
*std::cos( fAnglePi
)/2.0;
254 rfYCorrection
= aSize
.Width
*std::sin( fAnglePi
)/2.0;
256 else if( fAnglePositiveDegree
<= 180.0 )
258 double beta
= fAnglePi
-M_PI_2
;
259 rfXCorrection
= -aSize
.Height
*std::cos( beta
)/2.0;
260 if( !bRotateAroundCenter
)
261 rfXCorrection
+= aSize
.Width
*std::sin( beta
)/2.0;
262 rfYCorrection
= aSize
.Width
*std::cos( beta
)/2.0
263 +aSize
.Height
*std::sin( beta
);
265 else if( fAnglePositiveDegree
<= 270.0 )
267 double beta
= 3*M_PI_2
- fAnglePi
;
268 rfXCorrection
= aSize
.Height
*std::cos( beta
)/2.0;
269 if( !bRotateAroundCenter
)
270 rfXCorrection
-= aSize
.Width
*std::sin( beta
)/2.0;
271 rfYCorrection
= aSize
.Height
*std::sin( beta
)
272 +aSize
.Width
*std::cos( beta
)/2.0;
276 double beta
= 2*M_PI
- fAnglePi
;
277 rfXCorrection
= aSize
.Height
*std::sin( beta
)/2.0;
278 if( !bRotateAroundCenter
)
279 rfXCorrection
+= aSize
.Width
*std::cos( beta
)/2.0;
280 rfYCorrection
= aSize
.Width
*std::sin( beta
)/2.0;
284 void lcl_correctRotation_Left_Top( double& rfXCorrection
, double& rfYCorrection
285 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
287 //correct position for labels at the left top corner of something with a bottom right alignment
288 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
289 if( fAnglePositiveDegree
==0.0 )
292 else if( fAnglePositiveDegree
<= 90.0 )
294 rfYCorrection
= -aSize
.Width
*std::sin( fAnglePi
);
296 else if( fAnglePositiveDegree
<= 180.0 )
298 double beta
= fAnglePi
-M_PI_2
;
299 rfXCorrection
= -aSize
.Width
*std::sin( beta
);
300 rfYCorrection
= -aSize
.Height
*std::sin( beta
)
301 -aSize
.Width
*std::cos( beta
);
303 else if( fAnglePositiveDegree
<= 270.0 )
305 double beta
= 3*M_PI_2
- fAnglePi
;
306 rfXCorrection
= -aSize
.Height
*std::cos( beta
)
307 -aSize
.Width
*std::sin( beta
);
308 rfYCorrection
= -aSize
.Height
*std::sin( beta
);
312 rfXCorrection
= aSize
.Height
*std::sin( fAnglePi
);
316 void lcl_correctRotation_Left_Bottom( double& rfXCorrection
, double& rfYCorrection
317 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
319 //correct position for labels at the left bottom corner of something with a top right alignment
320 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
321 if( fAnglePositiveDegree
==0.0 )
324 else if( fAnglePositiveDegree
<= 90.0 )
326 rfXCorrection
= -aSize
.Height
*std::sin( fAnglePi
);
328 else if( fAnglePositiveDegree
<= 180.0 )
330 double beta
= fAnglePi
-M_PI_2
;
331 rfXCorrection
= -aSize
.Width
*std::sin( beta
)
332 -aSize
.Height
*std::cos( beta
);
333 rfYCorrection
= aSize
.Height
*std::sin( beta
);
335 else if( fAnglePositiveDegree
<= 270.0 )
337 double beta
= 3*M_PI_2
- fAnglePi
;
338 rfXCorrection
= -aSize
.Width
*std::sin( beta
);
339 rfYCorrection
= aSize
.Width
*std::cos( beta
)
340 +aSize
.Height
*std::sin( beta
);
344 rfYCorrection
= -aSize
.Width
*std::sin( fAnglePi
);
348 void lcl_correctRotation_Right_Top( double& rfXCorrection
, double& rfYCorrection
349 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
351 //correct position for labels at the right top corner of something with a bottom left alignment
352 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
353 if( fAnglePositiveDegree
==0.0 )
356 else if( fAnglePositiveDegree
<= 90.0 )
358 rfXCorrection
= aSize
.Height
*std::sin( fAnglePi
);
360 else if( fAnglePositiveDegree
<= 180.0 )
362 double beta
= fAnglePi
-M_PI_2
;
363 rfXCorrection
= aSize
.Width
*std::sin( beta
)
364 +aSize
.Height
*std::cos( beta
);
365 rfYCorrection
= -aSize
.Height
*std::sin( beta
);
367 else if( fAnglePositiveDegree
<= 270.0 )
369 double beta
= 3*M_PI_2
- fAnglePi
;
370 rfXCorrection
= aSize
.Width
*std::sin( beta
);
371 rfYCorrection
= -aSize
.Width
*std::cos( beta
)
372 -aSize
.Height
*std::sin( beta
);
376 rfYCorrection
= aSize
.Width
*std::sin( fAnglePi
);
380 void lcl_correctRotation_Right_Bottom( double& rfXCorrection
, double& rfYCorrection
381 , double fAnglePositiveDegree
, const awt::Size
& aSize
)
383 //correct position for labels at the right bottom corner of something with a top left alignment
384 double fAnglePi
= basegfx::deg2rad(fAnglePositiveDegree
);
385 if( fAnglePositiveDegree
==0.0 )
388 else if( fAnglePositiveDegree
<= 90.0 )
390 rfYCorrection
= aSize
.Width
*std::sin( fAnglePi
);
392 else if( fAnglePositiveDegree
<= 180.0 )
394 double beta
= fAnglePi
-M_PI_2
;
395 rfXCorrection
= aSize
.Width
*std::sin( beta
);
396 rfYCorrection
= aSize
.Height
*std::sin( beta
)
397 +aSize
.Width
*std::cos( beta
);
399 else if( fAnglePositiveDegree
<= 270.0 )
401 double beta
= 3*M_PI_2
- fAnglePi
;
402 rfXCorrection
= aSize
.Height
*std::cos( beta
)
403 +aSize
.Width
*std::sin( beta
);
404 rfYCorrection
= aSize
.Height
*std::sin( beta
);
408 rfXCorrection
= -aSize
.Height
*std::sin( fAnglePi
);
412 }//end anonymous namespace
414 void LabelPositionHelper::correctPositionForRotation( const rtl::Reference
<SvxShapeText
>& xShape2DText
415 , LabelAlignment eLabelAlignment
, const double fRotationAngle
, bool bRotateAroundCenter
)
417 if( !xShape2DText
.is() )
420 awt::Point aOldPos
= xShape2DText
->getPosition();
421 awt::Size aSize
= xShape2DText
->getSize();
423 double fYCorrection
= 0.0;
424 double fXCorrection
= 0.0;
426 double fAnglePositiveDegree
= fRotationAngle
;
427 while(fAnglePositiveDegree
<0.0)
428 fAnglePositiveDegree
+=360.0;
430 switch(eLabelAlignment
)
432 case LABEL_ALIGN_LEFT
:
433 lcl_correctRotation_Left( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
435 case LABEL_ALIGN_RIGHT
:
436 lcl_correctRotation_Right( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
438 case LABEL_ALIGN_TOP
:
439 lcl_correctRotation_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
441 case LABEL_ALIGN_BOTTOM
:
442 lcl_correctRotation_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
, bRotateAroundCenter
);
444 case LABEL_ALIGN_LEFT_TOP
:
445 lcl_correctRotation_Left_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
447 case LABEL_ALIGN_LEFT_BOTTOM
:
448 lcl_correctRotation_Left_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
450 case LABEL_ALIGN_RIGHT_TOP
:
451 lcl_correctRotation_Right_Top( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
453 case LABEL_ALIGN_RIGHT_BOTTOM
:
454 lcl_correctRotation_Right_Bottom( fXCorrection
, fYCorrection
, fAnglePositiveDegree
, aSize
);
456 default: //LABEL_ALIGN_CENTER
460 xShape2DText
->setPosition( awt::Point(
461 static_cast<sal_Int32
>(aOldPos
.X
+ fXCorrection
)
462 , static_cast<sal_Int32
>(aOldPos
.Y
+ fYCorrection
) ) );
467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */