LibreOffice Module chart2 (master) 1
LabelPositionHelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
22#include <PropertyMapper.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>
27
28#include <cmath>
29#include <utility>
30
31namespace chart
32{
33using namespace ::com::sun::star;
34using namespace ::com::sun::star::chart2;
35
37 sal_Int32 nDimensionCount
39 : m_nDimensionCount(nDimensionCount)
40 , m_xLogicTarget(std::move(xLogicTarget))
41{
42}
43
45{
46}
47
48awt::Point LabelPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D ) const
49{
51 rScenePosition3D, m_xLogicTarget, m_nDimensionCount );
52}
53
55{
56 //HorizontalAdjustment
57 {
58 drawing::TextHorizontalAdjust eHorizontalAdjust = drawing::TextHorizontalAdjust_CENTER;
59 if( eAlignment==LABEL_ALIGN_RIGHT || eAlignment==LABEL_ALIGN_RIGHT_TOP || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM )
60 eHorizontalAdjust = drawing::TextHorizontalAdjust_LEFT;
61 else if( eAlignment==LABEL_ALIGN_LEFT || eAlignment==LABEL_ALIGN_LEFT_TOP || eAlignment==LABEL_ALIGN_LEFT_BOTTOM )
62 eHorizontalAdjust = drawing::TextHorizontalAdjust_RIGHT;
63 uno::Any* pHorizontalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,u"TextHorizontalAdjust");
64 if(pHorizontalAdjustAny)
65 *pHorizontalAdjustAny <<= eHorizontalAdjust;
66 }
67
68 //VerticalAdjustment
69 {
70 drawing::TextVerticalAdjust eVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
71 if( eAlignment==LABEL_ALIGN_TOP || eAlignment==LABEL_ALIGN_RIGHT_TOP || eAlignment==LABEL_ALIGN_LEFT_TOP )
72 eVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM;
73 else if( eAlignment==LABEL_ALIGN_BOTTOM || eAlignment==LABEL_ALIGN_RIGHT_BOTTOM || eAlignment==LABEL_ALIGN_LEFT_BOTTOM )
74 eVerticalAdjust = drawing::TextVerticalAdjust_TOP;
75 uno::Any* pVerticalAdjustAny = PropertyMapper::getValuePointer(rPropValues,rPropNames,u"TextVerticalAdjust");
76 if(pVerticalAdjustAny)
77 *pVerticalAdjustAny <<= eVerticalAdjust;
78 }
79}
80
81static void lcl_doDynamicFontResize( uno::Any* pAOldAndNewFontHeightAny
82 , const awt::Size& rOldReferenceSize
83 , const awt::Size& rNewReferenceSize )
84{
85 double fOldFontHeight = 0;
86 if( pAOldAndNewFontHeightAny && ( *pAOldAndNewFontHeightAny >>= fOldFontHeight ) )
87 {
88 double fNewFontHeight = RelativeSizeHelper::calculate( fOldFontHeight, rOldReferenceSize, rNewReferenceSize );
89 *pAOldAndNewFontHeightAny <<= fNewFontHeight;
90 }
91}
92
94 , const tNameSequence& rPropNames
95 , const uno::Reference< beans::XPropertySet >& xAxisModelProps
96 , const awt::Size& rNewReferenceSize
97 )
98{
99 //handle dynamic font resize:
100 awt::Size aOldReferenceSize;
101 if( xAxisModelProps->getPropertyValue( "ReferencePageSize") >>= aOldReferenceSize )
102 {
103 uno::Any* pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeight" );
104 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
105 pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeightAsian" );
106 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
107 pAOldAndNewFontHeightAny = PropertyMapper::getValuePointer( rPropValues, rPropNames, u"CharHeightComplex" );
108 lcl_doDynamicFontResize( pAOldAndNewFontHeightAny, aOldReferenceSize, rNewReferenceSize );
109 }
110}
111
112namespace
113{
114
115void lcl_correctRotation_Left( double& rfXCorrection, double& rfYCorrection
116 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
117{
118 //correct label positions for labels on a left side of something with a right centered alignment
119 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
120 if( fAnglePositiveDegree==0.0 )
121 {
122 }
123 else if( fAnglePositiveDegree<= 90.0 )
124 {
125 rfXCorrection = -aSize.Height*std::sin( fAnglePi )/2.0;
126 if( bRotateAroundCenter )
127 rfYCorrection = -aSize.Width*std::sin( fAnglePi )/2.0;
128 }
129 else if( fAnglePositiveDegree<= 180.0 )
130 {
131 double beta = fAnglePi-M_PI_2;
132 rfXCorrection = -aSize.Width *std::sin( beta )
133 -aSize.Height *std::cos( beta )/2.0;
134 if( bRotateAroundCenter )
135 rfYCorrection = -aSize.Width *std::cos( beta )/2.0;
136 else
137 rfYCorrection = -aSize.Width *std::cos( beta );
138 }
139 else if( fAnglePositiveDegree<= 270.0 )
140 {
141 double beta = fAnglePi - M_PI;
142 rfXCorrection = -aSize.Width *std::cos( beta )
143 -aSize.Height*std::sin( beta )/2.0;
144 if( bRotateAroundCenter )
145 rfYCorrection = aSize.Width *std::sin( beta )/2.0;
146 else
147 rfYCorrection = aSize.Width *std::sin( beta );
148 }
149 else
150 {
151 double beta = 2*M_PI - fAnglePi;
152 rfXCorrection = -aSize.Height*std::sin( beta )/2.0;
153 if( bRotateAroundCenter )
154 rfYCorrection = aSize.Width*std::sin( beta )/2.0;
155 }
156}
157
158void lcl_correctRotation_Right( double& rfXCorrection, double& rfYCorrection
159 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
160{
161 //correct label positions for labels on a right side of something with a left centered alignment
162 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
163 if( fAnglePositiveDegree== 0.0 )
164 {
165 }
166 else if( fAnglePositiveDegree<= 90.0 )
167 {
168 rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0;
169 if( bRotateAroundCenter )
170 rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0;
171 }
172 else if( fAnglePositiveDegree<= 180.0 )
173 {
174 double beta = M_PI - fAnglePi;
175 rfXCorrection = aSize.Width *std::cos( beta )
176 + aSize.Height*std::sin( beta )/2.0;
177 if( bRotateAroundCenter )
178 rfYCorrection = aSize.Width *std::sin( beta )/2.0;
179 else
180 rfYCorrection = aSize.Width *std::sin( beta );
181 }
182 else if( fAnglePositiveDegree<= 270.0 )
183 {
184 double beta = 3*M_PI_2 - fAnglePi;
185 rfXCorrection = aSize.Width *std::sin( beta )
186 +aSize.Height*std::cos( beta )/2.0;
187 if( bRotateAroundCenter )
188 rfYCorrection = -aSize.Width *std::cos( beta )/2.0;
189 else
190 rfYCorrection = -aSize.Width *std::cos( beta );
191 }
192 else
193 {
194 rfXCorrection = aSize.Height*std::sin( 2*M_PI - fAnglePi )/2.0;
195 if( bRotateAroundCenter )
196 rfYCorrection = -aSize.Width*std::sin( 2*M_PI - fAnglePi )/2.0;
197 }
198}
199
200void lcl_correctRotation_Top( double& rfXCorrection, double& rfYCorrection
201 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
202{
203 //correct label positions for labels on top of something with a bottom centered alignment
204 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
205 if( fAnglePositiveDegree== 0.0 )
206 {
207 }
208 else if( fAnglePositiveDegree<= 90.0 )
209 {
210 rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0;
211 if( !bRotateAroundCenter )
212 rfXCorrection += aSize.Width*std::cos( fAnglePi )/2.0;
213 rfYCorrection = -aSize.Width*std::sin( fAnglePi )/2.0;
214 }
215 else if( fAnglePositiveDegree<= 180.0 )
216 {
217 double beta = fAnglePi - M_PI_2;
218 rfXCorrection = aSize.Height*std::cos( beta )/2.0;
219 if( !bRotateAroundCenter )
220 rfXCorrection -= aSize.Width*std::sin( beta )/2.0;
221 rfYCorrection = -aSize.Width*std::cos( beta )/2.0
222 - aSize.Height*std::sin( beta );
223 }
224 else if( fAnglePositiveDegree<= 270.0 )
225 {
226 double beta = fAnglePi - M_PI;
227 rfXCorrection = -aSize.Height *std::sin( beta )/2.0;
228 if( !bRotateAroundCenter )
229 rfXCorrection += aSize.Width *std::cos( beta )/2.0;
230 rfYCorrection = -aSize.Width *std::sin( beta )/2.0
231 -aSize.Height *std::cos( beta );
232 }
233 else
234 {
235 rfXCorrection = aSize.Height*std::sin( fAnglePi )/2.0;
236 if( !bRotateAroundCenter )
237 rfXCorrection -= aSize.Width*std::cos( fAnglePi )/2.0;
238 rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0;
239 }
240}
241
242void lcl_correctRotation_Bottom( double& rfXCorrection, double& rfYCorrection
243 , double fAnglePositiveDegree, const awt::Size& aSize, bool bRotateAroundCenter )
244{
245 //correct label positions for labels below something with a top centered alignment
246 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
247 if( fAnglePositiveDegree==0.0 )
248 {
249 }
250 else if( fAnglePositiveDegree<= 90.0 )
251 {
252 rfXCorrection = -aSize.Height*std::sin( fAnglePi )/2.0;
253 if( !bRotateAroundCenter )
254 rfXCorrection -= aSize.Width *std::cos( fAnglePi )/2.0;
255 rfYCorrection = aSize.Width*std::sin( fAnglePi )/2.0;
256 }
257 else if( fAnglePositiveDegree<= 180.0 )
258 {
259 double beta = fAnglePi-M_PI_2;
260 rfXCorrection = -aSize.Height*std::cos( beta )/2.0;
261 if( !bRotateAroundCenter )
262 rfXCorrection += aSize.Width *std::sin( beta )/2.0;
263 rfYCorrection = aSize.Width *std::cos( beta )/2.0
264 +aSize.Height*std::sin( beta );
265 }
266 else if( fAnglePositiveDegree<= 270.0 )
267 {
268 double beta = 3*M_PI_2 - fAnglePi;
269 rfXCorrection = aSize.Height*std::cos( beta )/2.0;
270 if( !bRotateAroundCenter )
271 rfXCorrection -= aSize.Width *std::sin( beta )/2.0;
272 rfYCorrection = aSize.Height*std::sin( beta )
273 +aSize.Width*std::cos( beta )/2.0;
274 }
275 else
276 {
277 double beta = 2*M_PI - fAnglePi;
278 rfXCorrection = aSize.Height*std::sin( beta )/2.0;
279 if( !bRotateAroundCenter )
280 rfXCorrection += aSize.Width*std::cos( beta )/2.0;
281 rfYCorrection = aSize.Width*std::sin( beta )/2.0;
282 }
283}
284
285void lcl_correctRotation_Left_Top( double& rfXCorrection, double& rfYCorrection
286 , double fAnglePositiveDegree, const awt::Size& aSize )
287{
288 //correct position for labels at the left top corner of something with a bottom right alignment
289 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
290 if( fAnglePositiveDegree==0.0 )
291 {
292 }
293 else if( fAnglePositiveDegree<= 90.0 )
294 {
295 rfYCorrection = -aSize.Width*std::sin( fAnglePi );
296 }
297 else if( fAnglePositiveDegree<= 180.0 )
298 {
299 double beta = fAnglePi-M_PI_2;
300 rfXCorrection = -aSize.Width*std::sin( beta );
301 rfYCorrection = -aSize.Height*std::sin( beta )
302 -aSize.Width*std::cos( beta );
303 }
304 else if( fAnglePositiveDegree<= 270.0 )
305 {
306 double beta = 3*M_PI_2 - fAnglePi;
307 rfXCorrection = -aSize.Height*std::cos( beta )
308 -aSize.Width*std::sin( beta );
309 rfYCorrection = -aSize.Height*std::sin( beta );
310 }
311 else
312 {
313 rfXCorrection = aSize.Height*std::sin( fAnglePi );
314 }
315}
316
317void lcl_correctRotation_Left_Bottom( double& rfXCorrection, double& rfYCorrection
318 , double fAnglePositiveDegree, const awt::Size& aSize )
319{
320 //correct position for labels at the left bottom corner of something with a top right alignment
321 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
322 if( fAnglePositiveDegree==0.0 )
323 {
324 }
325 else if( fAnglePositiveDegree<= 90.0 )
326 {
327 rfXCorrection = -aSize.Height*std::sin( fAnglePi );
328 }
329 else if( fAnglePositiveDegree<= 180.0 )
330 {
331 double beta = fAnglePi-M_PI_2;
332 rfXCorrection = -aSize.Width*std::sin( beta )
333 -aSize.Height*std::cos( beta );
334 rfYCorrection = aSize.Height*std::sin( beta );
335 }
336 else if( fAnglePositiveDegree<= 270.0 )
337 {
338 double beta = 3*M_PI_2 - fAnglePi;
339 rfXCorrection = -aSize.Width*std::sin( beta );
340 rfYCorrection = aSize.Width*std::cos( beta )
341 +aSize.Height*std::sin( beta );
342 }
343 else
344 {
345 rfYCorrection = -aSize.Width*std::sin( fAnglePi );
346 }
347}
348
349void lcl_correctRotation_Right_Top( double& rfXCorrection, double& rfYCorrection
350 , double fAnglePositiveDegree, const awt::Size& aSize )
351{
352 //correct position for labels at the right top corner of something with a bottom left alignment
353 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
354 if( fAnglePositiveDegree==0.0 )
355 {
356 }
357 else if( fAnglePositiveDegree<= 90.0 )
358 {
359 rfXCorrection = aSize.Height*std::sin( fAnglePi );
360 }
361 else if( fAnglePositiveDegree<= 180.0 )
362 {
363 double beta = fAnglePi-M_PI_2;
364 rfXCorrection = aSize.Width*std::sin( beta )
365 +aSize.Height*std::cos( beta );
366 rfYCorrection = -aSize.Height*std::sin( beta );
367 }
368 else if( fAnglePositiveDegree<= 270.0 )
369 {
370 double beta = 3*M_PI_2 - fAnglePi;
371 rfXCorrection = aSize.Width*std::sin( beta );
372 rfYCorrection = -aSize.Width*std::cos( beta )
373 -aSize.Height*std::sin( beta );
374 }
375 else
376 {
377 rfYCorrection = aSize.Width*std::sin( fAnglePi );
378 }
379}
380
381void lcl_correctRotation_Right_Bottom( double& rfXCorrection, double& rfYCorrection
382 , double fAnglePositiveDegree, const awt::Size& aSize )
383{
384 //correct position for labels at the right bottom corner of something with a top left alignment
385 double fAnglePi = basegfx::deg2rad(fAnglePositiveDegree);
386 if( fAnglePositiveDegree==0.0 )
387 {
388 }
389 else if( fAnglePositiveDegree<= 90.0 )
390 {
391 rfYCorrection = aSize.Width*std::sin( fAnglePi );
392 }
393 else if( fAnglePositiveDegree<= 180.0 )
394 {
395 double beta = fAnglePi-M_PI_2;
396 rfXCorrection = aSize.Width*std::sin( beta );
397 rfYCorrection = aSize.Height*std::sin( beta )
398 +aSize.Width*std::cos( beta );
399 }
400 else if( fAnglePositiveDegree<= 270.0 )
401 {
402 double beta = 3*M_PI_2 - fAnglePi;
403 rfXCorrection = aSize.Height*std::cos( beta )
404 +aSize.Width*std::sin( beta );
405 rfYCorrection = aSize.Height*std::sin( beta );
406 }
407 else
408 {
409 rfXCorrection = -aSize.Height*std::sin( fAnglePi );
410 }
411}
412
413}//end anonymous namespace
414
416 , LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter )
417{
418 if( !xShape2DText.is() )
419 return;
420
421 awt::Point aOldPos = xShape2DText->getPosition();
422 awt::Size aSize = xShape2DText->getSize();
423
424 double fYCorrection = 0.0;
425 double fXCorrection = 0.0;
426
427 double fAnglePositiveDegree = fRotationAngle;
428 while(fAnglePositiveDegree<0.0)
429 fAnglePositiveDegree+=360.0;
430
431 switch(eLabelAlignment)
432 {
433 case LABEL_ALIGN_LEFT:
434 lcl_correctRotation_Left( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
435 break;
437 lcl_correctRotation_Right( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
438 break;
439 case LABEL_ALIGN_TOP:
440 lcl_correctRotation_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
441 break;
443 lcl_correctRotation_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
444 break;
446 lcl_correctRotation_Left_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
447 break;
449 lcl_correctRotation_Left_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
450 break;
452 lcl_correctRotation_Right_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
453 break;
455 lcl_correctRotation_Right_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
456 break;
457 default: //LABEL_ALIGN_CENTER
458 break;
459 }
460
461 xShape2DText->setPosition( awt::Point(
462 static_cast<sal_Int32>(aOldPos.X + fXCorrection )
463 , static_cast<sal_Int32>(aOldPos.Y + fYCorrection ) ) );
464}
465
466} //namespace chart
467
468/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::awt::Point transformSceneToScreenPosition(const css::drawing::Position3D &rScenePosition3D) const
rtl::Reference< SvxShapeGroupAnyD > m_xLogicTarget
static void correctPositionForRotation(const rtl::Reference< SvxShapeText > &xShape2DText, LabelAlignment eLabelAlignment, const double fRotationAngle, bool bRotateAroundCenter)
static void changeTextAdjustment(tAnySequence &rPropValues, const tNameSequence &rPropNames, LabelAlignment eAlignment)
static void doDynamicFontResize(tAnySequence &rPropValues, const tNameSequence &rPropNames, const css::uno::Reference< css::beans::XPropertySet > &xAxisModelProps, const css::awt::Size &rNewReferenceSize)
static css::awt::Point transformSceneToScreenPosition(const css::drawing::Position3D &rScenePosition3D, const rtl::Reference< SvxShapeGroupAnyD > &xSceneTarget, sal_Int32 nDimensionCount)
static css::uno::Any * getValuePointer(tAnySequence &rPropValues, const tNameSequence &rPropNames, std::u16string_view rPropName)
static double calculate(double fValue, const css::awt::Size &rOldReferenceSize, const css::awt::Size &rNewReferenceSize)
float u
constexpr double deg2rad(double v)
static void lcl_doDynamicFontResize(uno::Any *pAOldAndNewFontHeightAny, const awt::Size &rOldReferenceSize, const awt::Size &rNewReferenceSize)
css::uno::Sequence< OUString > tNameSequence
@ LABEL_ALIGN_RIGHT_TOP
@ LABEL_ALIGN_RIGHT_BOTTOM
@ LABEL_ALIGN_TOP
@ LABEL_ALIGN_LEFT_BOTTOM
@ LABEL_ALIGN_LEFT_TOP
@ LABEL_ALIGN_RIGHT
@ LABEL_ALIGN_LEFT
@ LABEL_ALIGN_BOTTOM
css::uno::Sequence< css::uno::Any > tAnySequence