fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / view / main / LabelPositionHelper.cxx
blobd1faa2e7dd2beaa56278856708d5a2346227645e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
25 #include "macros.hxx"
26 #include "RelativeSizeHelper.hxx"
27 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
28 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
30 namespace chart
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);
71 //VerticalAdjustment
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 );
115 namespace
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;
139 else
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;
149 else
150 rfYCorrection = aSize.Width *rtl::math::sin( beta );
152 else
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;
182 else
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;
192 else
193 rfYCorrection = -aSize.Width *rtl::math::cos( beta );
195 else
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 );
236 else
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;
278 else
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 );
314 else
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 );
346 else
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 );
378 else
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 );
410 else
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() )
422 return;
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 );
438 break;
439 case LABEL_ALIGN_RIGHT:
440 lcl_correctRotation_Right( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
441 break;
442 case LABEL_ALIGN_TOP:
443 lcl_correctRotation_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
444 break;
445 case LABEL_ALIGN_BOTTOM:
446 lcl_correctRotation_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize, bRotateAroundCenter );
447 break;
448 case LABEL_ALIGN_LEFT_TOP:
449 lcl_correctRotation_Left_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
450 break;
451 case LABEL_ALIGN_LEFT_BOTTOM:
452 lcl_correctRotation_Left_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
453 break;
454 case LABEL_ALIGN_RIGHT_TOP:
455 lcl_correctRotation_Right_Top( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
456 break;
457 case LABEL_ALIGN_RIGHT_BOTTOM:
458 lcl_correctRotation_Right_Bottom( fXCorrection, fYCorrection, fAnglePositiveDegree, aSize );
459 break;
460 default: //LABEL_ALIGN_CENTER
461 break;
464 xShape2DText->setPosition( awt::Point(
465 static_cast<sal_Int32>(aOldPos.X + fXCorrection )
466 , static_cast<sal_Int32>(aOldPos.Y + fYCorrection ) ) );
469 } //namespace chart
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */