nss: upgrade to release 3.73
[LibreOffice.git] / chart2 / source / view / axes / Tickmarks.cxx
blob8332f01ff9a235f7b0281142ed461e1872e94628
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 "Tickmarks.hxx"
21 #include "Tickmarks_Equidistant.hxx"
22 #include "Tickmarks_Dates.hxx"
23 #include <ViewDefines.hxx>
24 #include "VAxisProperties.hxx"
25 #include <osl/diagnose.h>
26 #include <com/sun/star/chart2/AxisType.hpp>
28 using namespace ::com::sun::star;
29 using ::basegfx::B2DVector;
31 namespace chart {
33 TickInfo::TickInfo( const uno::Reference<chart2::XScaling>& xInverse )
34 : fScaledTickValue( 0.0 )
35 , xInverseScaling( xInverse )
36 , aTickScreenPosition(0.0,0.0)
37 , bPaintIt( true )
38 , nFactorForLimitedTextWidth(1)
42 double TickInfo::getUnscaledTickValue() const
44 if( xInverseScaling.is() )
45 return xInverseScaling->doScaling( fScaledTickValue );
46 else
47 return fScaledTickValue;
50 sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
52 //return the positive distance between the two first tickmarks in screen values
54 B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
55 sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
56 if(nRet<0)
57 nRet *= -1;
58 return nRet;
61 PureTickIter::PureTickIter( TickInfoArrayType& rTickInfoVector )
62 : m_rTickVector(rTickInfoVector)
63 , m_aTickIter(m_rTickVector.begin())
66 PureTickIter::~PureTickIter()
69 TickInfo* PureTickIter::firstInfo()
71 m_aTickIter = m_rTickVector.begin();
72 if(m_aTickIter!=m_rTickVector.end())
73 return &*m_aTickIter;
74 return nullptr;
76 TickInfo* PureTickIter::nextInfo()
78 if(m_aTickIter!=m_rTickVector.end())
80 ++m_aTickIter;
81 if(m_aTickIter!=m_rTickVector.end())
82 return &*m_aTickIter;
84 return nullptr;
87 TickFactory::TickFactory(
88 const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
89 : m_rScale( rScale )
90 , m_rIncrement( rIncrement )
92 //@todo: make sure that the scale is valid for the scaling
94 if( m_rScale.Scaling.is() )
96 m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
97 OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return an inverse Scaling" );
100 m_fScaledVisibleMin = m_rScale.Minimum;
101 if( m_xInverseScaling.is() )
102 m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
104 m_fScaledVisibleMax = m_rScale.Maximum;
105 if( m_xInverseScaling.is() )
106 m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
109 TickFactory::~TickFactory()
113 bool TickFactory::isDateAxis() const
115 return m_rScale.AxisType == chart2::AxisType::DATE;
118 void TickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) const
120 if( isDateAxis() )
121 DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
122 else
123 EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
126 void TickFactory::getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const
128 if( isDateAxis() )
129 DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
130 else
131 EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
134 // ___TickFactory_2D___
135 TickFactory2D::TickFactory2D(
136 const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
137 //, double fStretch_SceneToScreen, double fOffset_SceneToScreen )
138 , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
139 , const B2DVector& rAxisLineToLabelLineShift )
140 : TickFactory( rScale, rIncrement )
141 , m_aAxisStartScreenPosition2D(rStartScreenPos)
142 , m_aAxisEndScreenPosition2D(rEndScreenPos)
143 , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift)
144 , m_fStretch_LogicToScreen(1.0)
145 , m_fOffset_LogicToScreen(0.0)
147 double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
148 if (m_rScale.Orientation == chart2::AxisOrientation_MATHEMATICAL)
150 m_fStretch_LogicToScreen = 1.0/fWidthY;
151 m_fOffset_LogicToScreen = -m_fScaledVisibleMin;
153 else
155 B2DVector aSwap(m_aAxisStartScreenPosition2D);
156 m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D;
157 m_aAxisEndScreenPosition2D = aSwap;
159 m_fStretch_LogicToScreen = -1.0/fWidthY;
160 m_fOffset_LogicToScreen = -m_fScaledVisibleMax;
164 TickFactory2D::~TickFactory2D()
168 bool TickFactory2D::isHorizontalAxis() const
170 // check trivial cases:
171 if ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() )
172 return true;
173 if ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() )
174 return false;
176 // for skew axes compare angle with horizontal vector
177 double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(1.0, 0.0)));
178 return fInclination < F_PI4 || fInclination > (F_PI-F_PI4);
180 bool TickFactory2D::isVerticalAxis() const
182 // check trivial cases:
183 if ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() )
184 return true;
185 if ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() )
186 return false;
188 // for skew axes compare angle with vertical vector
189 double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(0.0, -1.0)));
190 return fInclination < F_PI4 || fInclination > (F_PI-F_PI4);
192 //static
193 sal_Int32 TickFactory2D::getTickScreenDistance( TickIter& rIter )
195 //return the positive distance between the two first tickmarks in screen values
196 //if there are less than two tickmarks -1 is returned
198 const TickInfo* pFirstTickInfo = rIter.firstInfo();
199 const TickInfo* pSecondTickInfo = rIter.nextInfo();
200 if(!pSecondTickInfo || !pFirstTickInfo)
201 return -1;
203 return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
206 B2DVector TickFactory2D::getXaxisStartPos() const
208 return m_aAxisStartScreenPosition2D;
211 B2DVector TickFactory2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
213 B2DVector aRet(m_aAxisStartScreenPosition2D);
214 aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
215 *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStretch_LogicToScreen);
216 return aRet;
219 void TickFactory2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints
220 , sal_Int32 nSequenceIndex
221 , double fScaledLogicTickValue, double fInnerDirectionSign
222 , const TickmarkProperties& rTickmarkProperties
223 , bool bPlaceAtLabels ) const
225 if( fInnerDirectionSign==0.0 )
226 fInnerDirectionSign = 1.0;
228 B2DVector aTickScreenPosition = getTickScreenPosition2D(fScaledLogicTickValue);
229 if( bPlaceAtLabels )
230 aTickScreenPosition += m_aAxisLineToLabelLineShift;
232 B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
233 aMainDirection.normalize();
234 B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
235 aOrthoDirection *= fInnerDirectionSign;
236 aOrthoDirection.normalize();
238 B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
239 B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
241 rPoints[nSequenceIndex].realloc(2);
242 rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX());
243 rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY());
244 rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX());
245 rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY());
248 B2DVector TickFactory2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
250 bool bFarAwayLabels = false;
251 if( rAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START
252 || rAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END )
253 bFarAwayLabels = true;
255 double fInnerDirectionSign = rAxisProperties.maLabelAlignment.mfInnerTickDirection;
256 if( fInnerDirectionSign==0.0 )
257 fInnerDirectionSign = 1.0;
259 B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
260 aMainDirection.normalize();
261 B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
262 aOrthoDirection *= fInnerDirectionSign;
263 aOrthoDirection.normalize();
265 B2DVector aStart(0,0), aEnd(0,0);
266 if( bFarAwayLabels )
268 TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
269 aStart = aOrthoDirection*aProps.RelativePos;
270 aEnd = aStart - aOrthoDirection*aProps.Length;
272 else
274 for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
276 const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
277 B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
278 B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
279 if(aNewStart.getLength()>aStart.getLength())
280 aStart=aNewStart;
281 if(aNewEnd.getLength()>aEnd.getLength())
282 aEnd=aNewEnd;
286 B2DVector aLabelDirection(aStart);
287 if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
288 aLabelDirection = aEnd;
290 B2DVector aOrthoLabelDirection(aOrthoDirection);
291 if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
292 aOrthoLabelDirection*=-1.0;
293 aOrthoLabelDirection.normalize();
294 if( bIncludeSpaceBetweenTickAndText )
295 aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
296 if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
297 aLabelDirection += m_aAxisLineToLabelLineShift;
298 return aLabelDirection;
301 void TickFactory2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
303 rPoints[0].realloc(2);
304 rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX());
305 rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY());
306 rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX());
307 rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY());
310 void TickFactory2D::updateScreenValues( TickInfoArraysType& rAllTickInfos ) const
312 //get the transformed screen values for all tickmarks in rAllTickInfos
313 for (auto & tickInfos : rAllTickInfos)
315 for (auto & tickInfo : tickInfos)
317 tickInfo.aTickScreenPosition =
318 getTickScreenPosition2D(tickInfo.fScaledTickValue);
323 } //namespace chart
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */