[Libreoffice-commits] core.git: Branch 'feature/perfwork4' - 6 commits - chart2/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Oct 23 10:40:05 PDT 2014


 chart2/source/view/axes/VAxisBase.cxx       |    4 
 chart2/source/view/axes/VAxisBase.hxx       |    2 
 chart2/source/view/axes/VAxisProperties.cxx |    9 
 chart2/source/view/axes/VAxisProperties.hxx |    4 
 chart2/source/view/axes/VCartesianAxis.cxx  |  300 +++++++++++++++++++++-------
 chart2/source/view/axes/VCartesianAxis.hxx  |   36 ++-
 6 files changed, 277 insertions(+), 78 deletions(-)

New commits:
commit 6a71d5bd7722b30b5cb268487da706c7a6e0c05b
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 23 13:35:54 2014 -0400

    Modify the tick iterator strategy to use fewer ticks.
    
    To pre-determine the size of the largest text label object, auto-staggering
    strategy etc.  In theory (if I read the code correctly) we could achieve
    the same thing by using only 3 ticks rather than 5.
    
    Change-Id: Iee51588061e482c724ee4fb666c51c2a6b636e8c

diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
index 7ff0f99..1209664 100644
--- a/chart2/source/view/axes/VCartesianAxis.cxx
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -407,9 +407,10 @@ void getAxisLabelProperties(
 }
 
 /**
- * Iterate through only the first 2 and last 2 tick info items, and the tick
- * that has the longest text (in terms of character length) in case it's not
- * in the first or last 2 items.
+ * Iterate through only 3 ticks including the one that has the longest text
+ * length.  When the first tick has the longest text, it iterates through
+ * the first 3 ticks.  Otherwise it iterates through 3 ticks such that the
+ * 2nd tick is the one with the longest text.
  */
 class MaxLabelTickIter : public TickIter
 {
@@ -431,21 +432,27 @@ MaxLabelTickIter::MaxLabelTickIter(
     m_rTickInfoVector(rTickInfoVector), m_nCurrentIndex(0)
 {
     assert(!rTickInfoVector.empty()); // should be checked by the caller.
+    assert(nLongestLabelIndex < rTickInfoVector.size());
 
     size_t nMaxIndex = m_rTickInfoVector.size()-1;
     if (nLongestLabelIndex >= nMaxIndex-1)
         nLongestLabelIndex = 0;
 
-    m_aValidIndices.push_back(0);
-    if( nMaxIndex>=1 )
-        m_aValidIndices.push_back(1);
-    if( nLongestLabelIndex>1 )
+    if (nLongestLabelIndex > 0)
+        m_aValidIndices.push_back(nLongestLabelIndex-1);
+
+    m_aValidIndices.push_back(nLongestLabelIndex);
+
+    while (m_aValidIndices.size() < 3)
+    {
+        ++nLongestLabelIndex;
+        if (nLongestLabelIndex > nMaxIndex)
+            break;
+
         m_aValidIndices.push_back(nLongestLabelIndex);
-    if( nMaxIndex > 2 )
-        m_aValidIndices.push_back(nMaxIndex-1);
-    if( nMaxIndex > 1 )
-        m_aValidIndices.push_back(nMaxIndex);
+    }
 }
+
 MaxLabelTickIter::~MaxLabelTickIter()
 {
 }
@@ -624,6 +631,9 @@ TickIter* VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel )
             if( !m_aAllTickInfos.empty() )
             {
                 size_t nLongestLabelIndex = m_bUseTextLabels ? getIndexOfLongestLabel(m_aTextLabels) : 0;
+                if (nLongestLabelIndex >= m_aAllTickInfos[0].size())
+                    return NULL;
+
                 return new MaxLabelTickIter( m_aAllTickInfos[0], nLongestLabelIndex );
             }
         }
commit af7aedbceb694a1193e34eafcb94db632ff089d7
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Oct 23 12:43:30 2014 -0400

    Let's use size_t for the index.
    
    This removes unnecessary static_cast's and check for negative values
    which, from what I've read from the code, never happens.
    
    Change-Id: I9d9e1de5b091df335dd3b7eeb34e4e8f98de0fbd

diff --git a/chart2/source/view/axes/VAxisBase.cxx b/chart2/source/view/axes/VAxisBase.cxx
index c391382..f97655f 100644
--- a/chart2/source/view/axes/VAxisBase.cxx
+++ b/chart2/source/view/axes/VAxisBase.cxx
@@ -187,7 +187,7 @@ bool VAxisBase::prepareShapeCreation()
     return true;
 }
 
-sal_Int32 VAxisBase::getIndexOfLongestLabel( const uno::Sequence< OUString >& rLabels )
+size_t VAxisBase::getIndexOfLongestLabel( const uno::Sequence<OUString>& rLabels )
 {
     sal_Int32 nRet = 0;
     sal_Int32 nLength = 0;
@@ -201,6 +201,8 @@ sal_Int32 VAxisBase::getIndexOfLongestLabel( const uno::Sequence< OUString >& rL
             nRet = nN;
         }
     }
+
+    assert(nRet >= 0);
     return nRet;
 }
 
diff --git a/chart2/source/view/axes/VAxisBase.hxx b/chart2/source/view/axes/VAxisBase.hxx
index d43ef58..ab0e4093 100644
--- a/chart2/source/view/axes/VAxisBase.hxx
+++ b/chart2/source/view/axes/VAxisBase.hxx
@@ -65,7 +65,7 @@ public:
     void setExrtaLinePositionAtOtherAxis( double fCrossingAt );
 
 protected: //methods
-    sal_Int32 getIndexOfLongestLabel( const ::com::sun::star::uno::Sequence< OUString >& rLabels );
+    size_t getIndexOfLongestLabel( const css::uno::Sequence<OUString>& rLabels );
     void removeTextShapesFromTicks();
     void updateUnscaledValuesAtTicks( TickIter& rIter );
 
diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
index fbc5335..7ff0f99 100644
--- a/chart2/source/view/axes/VCartesianAxis.cxx
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -414,8 +414,7 @@ void getAxisLabelProperties(
 class MaxLabelTickIter : public TickIter
 {
 public:
-    MaxLabelTickIter( TickInfoArrayType& rTickInfoVector
-            , sal_Int32 nLongestLabelIndex );
+    MaxLabelTickIter( TickInfoArrayType& rTickInfoVector, size_t nLongestLabelIndex );
     virtual ~MaxLabelTickIter();
 
     virtual TickInfo* firstInfo() SAL_OVERRIDE;
@@ -423,21 +422,21 @@ public:
 
 private:
     TickInfoArrayType& m_rTickInfoVector;
-    ::std::vector< sal_Int32 > m_aValidIndices;
-    sal_Int32 m_nCurrentIndex;
+    std::vector<size_t> m_aValidIndices;
+    size_t m_nCurrentIndex;
 };
 
-MaxLabelTickIter::MaxLabelTickIter( TickInfoArrayType& rTickInfoVector
-            , sal_Int32 nLongestLabelIndex )
-            : m_rTickInfoVector(rTickInfoVector)
-            , m_nCurrentIndex(0)
+MaxLabelTickIter::MaxLabelTickIter(
+    TickInfoArrayType& rTickInfoVector, size_t nLongestLabelIndex ) :
+    m_rTickInfoVector(rTickInfoVector), m_nCurrentIndex(0)
 {
-    sal_Int32 nMaxIndex = m_rTickInfoVector.size()-1;
-    if( nLongestLabelIndex<0 || nLongestLabelIndex>=nMaxIndex-1 )
+    assert(!rTickInfoVector.empty()); // should be checked by the caller.
+
+    size_t nMaxIndex = m_rTickInfoVector.size()-1;
+    if (nLongestLabelIndex >= nMaxIndex-1)
         nLongestLabelIndex = 0;
 
-    if( nMaxIndex>=0 )
-        m_aValidIndices.push_back(0);
+    m_aValidIndices.push_back(0);
     if( nMaxIndex>=1 )
         m_aValidIndices.push_back(1);
     if( nLongestLabelIndex>1 )
@@ -454,7 +453,7 @@ MaxLabelTickIter::~MaxLabelTickIter()
 TickInfo* MaxLabelTickIter::firstInfo()
 {
     m_nCurrentIndex = 0;
-    if( m_nCurrentIndex < static_cast<sal_Int32>(m_aValidIndices.size()) )
+    if (m_nCurrentIndex < m_aValidIndices.size())
         return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
     return 0;
 }
@@ -462,7 +461,7 @@ TickInfo* MaxLabelTickIter::firstInfo()
 TickInfo* MaxLabelTickIter::nextInfo()
 {
     m_nCurrentIndex++;
-    if( m_nCurrentIndex>=0 && m_nCurrentIndex<static_cast<sal_Int32>(m_aValidIndices.size()) )
+    if (m_nCurrentIndex < m_aValidIndices.size())
         return &m_rTickInfoVector[m_aValidIndices[m_nCurrentIndex]];
     return 0;
 }
@@ -624,7 +623,7 @@ TickIter* VCartesianAxis::createMaximumLabelTickIterator( sal_Int32 nTextLevel )
         {
             if( !m_aAllTickInfos.empty() )
             {
-                sal_Int32 nLongestLabelIndex = m_bUseTextLabels ? this->getIndexOfLongestLabel( m_aTextLabels ) : 0;
+                size_t nLongestLabelIndex = m_bUseTextLabels ? getIndexOfLongestLabel(m_aTextLabels) : 0;
                 return new MaxLabelTickIter( m_aAllTickInfos[0], nLongestLabelIndex );
             }
         }
commit 19e33a3ad865e5fbe12dbaca90199f4d6441cc97
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 22 11:50:41 2014 -0400

    Some code sharing.
    
    Change-Id: If80c4b0ceec5e0afd55d12ebe7511fb4f40b4797

diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx
index 3b5502f..3db365d 100644
--- a/chart2/source/view/axes/VAxisProperties.cxx
+++ b/chart2/source/view/axes/VAxisProperties.cxx
@@ -412,6 +412,13 @@ bool AxisLabelProperties::isStaggered() const
     return ( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering );
 }
 
+void AxisLabelProperties::autoRotate45()
+{
+    fRotationAngleDegree = 45;
+    bLineBreakAllowed = false;
+    eStaggering = SIDE_BY_SIDE;
+}
+
 } //namespace chart
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx
index b658925..1eadf70 100644
--- a/chart2/source/view/axes/VAxisProperties.hxx
+++ b/chart2/source/view/axes/VAxisProperties.hxx
@@ -82,6 +82,8 @@ struct AxisLabelProperties SAL_FINAL
                 ::com::sun::star::chart2::XAxis >&  xAxisModel );
 
     bool isStaggered() const;
+
+    void autoRotate45();
 };
 
 struct AxisLabelAlignment
diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
index d43e32f..fbc5335 100644
--- a/chart2/source/view/axes/VCartesianAxis.cxx
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -365,6 +365,47 @@ bool lcl_hasWordBreak( const Reference<drawing::XShape>& xShape )
     return false;
 }
 
+OUString getTextLabelString(
+    const FixedNumberFormatter& rFixedNumberFormatter, const uno::Sequence<OUString>* pCategories,
+    const TickInfo* pTickInfo, bool bComplexCat, sal_Int32& rExtraColor, bool& rHasExtraColor )
+{
+    if (pCategories)
+    {
+        // This is a normal category axis.  Get the label string from the
+        // label string array.
+        sal_Int32 nIndex = static_cast<sal_Int32>(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
+        if( nIndex>=0 && nIndex<pCategories->getLength() )
+            return (*pCategories)[nIndex];
+
+        return OUString();
+    }
+    else if (bComplexCat)
+    {
+        // This is a complex category axis.  The label is stored in the tick.
+        return pTickInfo->aText;
+    }
+
+    // This is a numeric axis.  Format the original tick value per number format.
+    return rFixedNumberFormatter.getFormattedString(pTickInfo->getUnscaledTickValue(), rExtraColor, rHasExtraColor);
+}
+
+void getAxisLabelProperties(
+    tNameSequence& rPropNames, tAnySequence& rPropValues, const AxisProperties& rAxisProp,
+    const AxisLabelProperties& rAxisLabelProp,
+    sal_Int32 nLimitedSpaceForText, bool bLimitedHeight )
+{
+    Reference<beans::XPropertySet> xProps(rAxisProp.m_xAxisModel, uno::UNO_QUERY);
+
+    PropertyMapper::getTextLabelMultiPropertyLists(
+        xProps, rPropNames, rPropValues, false, nLimitedSpaceForText, bLimitedHeight);
+
+    LabelPositionHelper::doDynamicFontResize(
+        rPropValues, rPropNames, xProps, rAxisLabelProp.m_aFontReferenceSize);
+
+    LabelPositionHelper::changeTextAdjustment(
+        rPropValues, rPropNames, rAxisProp.maLabelAlignment.meAlignment);
+}
+
 /**
  * Iterate through only the first 2 and last 2 tick info items, and the tick
  * that has the longest text (in terms of character length) in case it's not
@@ -644,17 +685,12 @@ bool VCartesianAxis::createTextShapes(
     const TickInfo* pPREPreviousVisibleTickInfo = NULL;
     const TickInfo* pLastVisibleNeighbourTickInfo = NULL;
 
+    bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
+
     //prepare properties for multipropertyset-interface of shape
     tNameSequence aPropNames;
     tAnySequence aPropValues;
-
-    bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
-    Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
-    PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
-        , nLimitedSpaceForText, bLimitedHeight );
-    LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
-        , m_aAxisLabelProperties.m_aFontReferenceSize );
-    LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.maLabelAlignment.meAlignment );
+    getAxisLabelProperties(aPropNames, aPropValues, m_aAxisProperties, rAxisLabelProperties, nLimitedSpaceForText, bLimitedHeight);
 
     uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor");
     sal_Int32 nColor = Color( COL_AUTO ).GetColor();
@@ -725,25 +761,9 @@ bool VCartesianAxis::createTextShapes(
         bool bHasExtraColor=false;
         sal_Int32 nExtraColor=0;
 
-        OUString aLabel;
-        if(pCategories)
-        {
-            // This is a normal category axis.  Get the label string from the
-            // label string array.
-            sal_Int32 nIndex = static_cast<sal_Int32>(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
-            if( nIndex>=0 && nIndex<pCategories->getLength() )
-                aLabel = (*pCategories)[nIndex];
-        }
-        else if( m_aAxisProperties.m_bComplexCategories )
-        {
-            // This is a complex category axis.  The label is stored in the tick.
-            aLabel = pTickInfo->aText;
-        }
-        else
-        {
-            // This is a numeric axis.  Format the original tick value per number format.
-            aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
-        }
+        OUString aLabel = getTextLabelString(
+            aFixedNumberFormatter, pCategories, pTickInfo, isComplexCategoryAxis(),
+            nExtraColor, bHasExtraColor);
 
         if(pColorAny)
             *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
@@ -810,10 +830,7 @@ bool VCartesianAxis::createTextShapes(
                         // Try auto-rotating the labels at 45 degrees and
                         // start over.  This rotation angle will be stored for
                         // all future text shape creation runs.
-
-                        rAxisLabelProperties.fRotationAngleDegree = 45;
-                        rAxisLabelProperties.bLineBreakAllowed = false;
-                        rAxisLabelProperties.eStaggering = SIDE_BY_SIDE;
+                        rAxisLabelProperties.autoRotate45();
                         m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs.
                         removeTextShapesFromTicks();
                         return false;
@@ -862,17 +879,12 @@ bool VCartesianAxis::createTextShapesSimple(
     const TickInfo* pPreviousVisibleTickInfo = NULL;
     const TickInfo* pLastVisibleNeighbourTickInfo = NULL;
 
+    bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
+
     //prepare properties for multipropertyset-interface of shape
     tNameSequence aPropNames;
     tAnySequence aPropValues;
-
-    bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
-    Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
-    PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
-        , -1, bLimitedHeight );
-    LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
-        , m_aAxisLabelProperties.m_aFontReferenceSize );
-    LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.maLabelAlignment.meAlignment );
+    getAxisLabelProperties(aPropNames, aPropValues, m_aAxisProperties, rAxisLabelProperties, -1, bLimitedHeight);
 
     uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor");
     sal_Int32 nColor = Color( COL_AUTO ).GetColor();
@@ -921,25 +933,9 @@ bool VCartesianAxis::createTextShapesSimple(
         bool bHasExtraColor=false;
         sal_Int32 nExtraColor=0;
 
-        OUString aLabel;
-        if(pCategories)
-        {
-            // This is a normal category axis.  Get the label string from the
-            // label string array.
-            sal_Int32 nIndex = static_cast<sal_Int32>(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
-            if( nIndex>=0 && nIndex<pCategories->getLength() )
-                aLabel = (*pCategories)[nIndex];
-        }
-        else if( m_aAxisProperties.m_bComplexCategories )
-        {
-            // This is a complex category axis.  The label is stored in the tick.
-            aLabel = pTickInfo->aText;
-        }
-        else
-        {
-            // This is a numeric axis.  Format the original tick value per number format.
-            aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
-        }
+        OUString aLabel = getTextLabelString(
+            aFixedNumberFormatter, pCategories, pTickInfo, isComplexCategoryAxis(),
+            nExtraColor, bHasExtraColor);
 
         if(pColorAny)
             *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
@@ -975,10 +971,7 @@ bool VCartesianAxis::createTextShapesSimple(
                     // Try auto-rotating the labels at 45 degrees and
                     // start over.  This rotation angle will be stored for
                     // all future text shape creation runs.
-
-                    rAxisLabelProperties.fRotationAngleDegree = 45;
-                    rAxisLabelProperties.bLineBreakAllowed = false;
-                    rAxisLabelProperties.eStaggering = SIDE_BY_SIDE;
+                    rAxisLabelProperties.autoRotate45();
                     m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs.
                     removeTextShapesFromTicks();
                     return false;
commit b6601a01b4202ff21bc621fd1fd1da11ede0f06a
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 22 10:51:44 2014 -0400

    Create a variant of createTextShapes for simpler use cases.
    
    So that we can do more aggressive optimization without breaking the other
    cases.
    
    Change-Id: I5d4ceb2a3b7f041f752a570827815236e9de58db

diff --git a/chart2/source/view/axes/VAxisProperties.cxx b/chart2/source/view/axes/VAxisProperties.cxx
index 9b449d5..3b5502f 100644
--- a/chart2/source/view/axes/VAxisProperties.cxx
+++ b/chart2/source/view/axes/VAxisProperties.cxx
@@ -407,7 +407,7 @@ void AxisLabelProperties::init( const uno::Reference< XAxis >& xAxisModel )
     }
 }
 
-bool AxisLabelProperties::getIsStaggered() const
+bool AxisLabelProperties::isStaggered() const
 {
     return ( STAGGER_ODD == eStaggering || STAGGER_EVEN == eStaggering );
 }
diff --git a/chart2/source/view/axes/VAxisProperties.hxx b/chart2/source/view/axes/VAxisProperties.hxx
index 7495c21..b658925 100644
--- a/chart2/source/view/axes/VAxisProperties.hxx
+++ b/chart2/source/view/axes/VAxisProperties.hxx
@@ -81,7 +81,7 @@ struct AxisLabelProperties SAL_FINAL
     void init( const ::com::sun::star::uno::Reference<
                 ::com::sun::star::chart2::XAxis >&  xAxisModel );
 
-    bool getIsStaggered() const;
+    bool isStaggered() const;
 };
 
 struct AxisLabelAlignment
diff --git a/chart2/source/view/axes/VCartesianAxis.cxx b/chart2/source/view/axes/VCartesianAxis.cxx
index d095af5..d43e32f 100644
--- a/chart2/source/view/axes/VCartesianAxis.cxx
+++ b/chart2/source/view/axes/VCartesianAxis.cxx
@@ -600,20 +600,25 @@ sal_Int32 VCartesianAxis::getTextLevelCount() const
 }
 
 bool VCartesianAxis::createTextShapes(
-                       const Reference< drawing::XShapes >& xTarget
-                     , TickIter& rTickIter
-                     , AxisLabelProperties& rAxisLabelProperties
-                     , TickFactory2D* pTickFactory
-                     , sal_Int32 nScreenDistanceBetweenTicks )
+    const Reference<drawing::XShapes>& xTarget, TickIter& rTickIter,
+    AxisLabelProperties& rAxisLabelProperties, TickFactory2D* pTickFactory,
+    sal_Int32 nScreenDistanceBetweenTicks )
 {
+    const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
+    const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
+
+    if (!isBreakOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis) &&
+        !isAutoStaggeringOfLabelsAllowed(rAxisLabelProperties, bIsHorizontalAxis, bIsVerticalAxis) &&
+        !rAxisLabelProperties.isStaggered())
+        return createTextShapesSimple(xTarget, rTickIter, rAxisLabelProperties, pTickFactory);
+
     FixedNumberFormatter aFixedNumberFormatter(
                 m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
 
-    const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
-    const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
-    bool bIsStaggered = rAxisLabelProperties.getIsStaggered();
+    bool bIsStaggered = rAxisLabelProperties.isStaggered();
     B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true);
     sal_Int32 nLimitedSpaceForText = -1;
+
     if( isBreakOfLabelsAllowed( rAxisLabelProperties, bIsHorizontalAxis ) )
     {
         nLimitedSpaceForText = nScreenDistanceBetweenTicks;
@@ -837,6 +842,169 @@ bool VCartesianAxis::createTextShapes(
     return true;
 }
 
+bool VCartesianAxis::createTextShapesSimple(
+    const Reference<drawing::XShapes>& xTarget, TickIter& rTickIter,
+    AxisLabelProperties& rAxisLabelProperties, TickFactory2D* pTickFactory )
+{
+    FixedNumberFormatter aFixedNumberFormatter(
+                m_xNumberFormatsSupplier, rAxisLabelProperties.nNumberFormatKey );
+
+    const bool bIsHorizontalAxis = pTickFactory->isHorizontalAxis();
+    const bool bIsVerticalAxis = pTickFactory->isVerticalAxis();
+    B2DVector aTextToTickDistance = pTickFactory->getDistanceAxisTickToText(m_aAxisProperties, true);
+
+     // Stores an array of text label strings in case of a normal
+     // (non-complex) category axis.
+    const uno::Sequence<OUString>* pCategories = NULL;
+    if( m_bUseTextLabels && !m_aAxisProperties.m_bComplexCategories )
+        pCategories = &m_aTextLabels;
+
+    const TickInfo* pPreviousVisibleTickInfo = NULL;
+    const TickInfo* pLastVisibleNeighbourTickInfo = NULL;
+
+    //prepare properties for multipropertyset-interface of shape
+    tNameSequence aPropNames;
+    tAnySequence aPropValues;
+
+    bool bLimitedHeight = fabs(aTextToTickDistance.getX()) > fabs(aTextToTickDistance.getY());
+    Reference< beans::XPropertySet > xProps( m_aAxisProperties.m_xAxisModel, uno::UNO_QUERY );
+    PropertyMapper::getTextLabelMultiPropertyLists( xProps, aPropNames, aPropValues, false
+        , -1, bLimitedHeight );
+    LabelPositionHelper::doDynamicFontResize( aPropValues, aPropNames, xProps
+        , m_aAxisLabelProperties.m_aFontReferenceSize );
+    LabelPositionHelper::changeTextAdjustment( aPropValues, aPropNames, m_aAxisProperties.maLabelAlignment.meAlignment );
+
+    uno::Any* pColorAny = PropertyMapper::getValuePointer(aPropValues,aPropNames,"CharColor");
+    sal_Int32 nColor = Color( COL_AUTO ).GetColor();
+    if(pColorAny)
+        *pColorAny >>= nColor;
+
+    uno::Any* pLimitedSpaceAny = PropertyMapper::getValuePointerForLimitedSpace(aPropValues,aPropNames,bLimitedHeight);
+
+    sal_Int32 nTick = 0;
+    for( TickInfo* pTickInfo = rTickIter.firstInfo()
+        ; pTickInfo
+        ; pTickInfo = rTickIter.nextInfo(), nTick++ )
+    {
+        pLastVisibleNeighbourTickInfo = pPreviousVisibleTickInfo;
+
+        //don't create labels which does not fit into the rhythm
+        if( nTick%rAxisLabelProperties.nRhythm != 0 )
+            continue;
+
+        //don't create labels for invisible ticks
+        if( !pTickInfo->bPaintIt )
+            continue;
+
+        if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
+        {
+            // Overlapping is not allowed.  If the label overlaps with its
+            // neighbering label, try increasing the tick interval (or rhythm
+            // as it's called) and start over.
+
+            if( lcl_doesShapeOverlapWithTickmark( pLastVisibleNeighbourTickInfo->xTextShape
+                       , rAxisLabelProperties.fRotationAngleDegree
+                       , pTickInfo->aTickScreenPosition
+                       , bIsHorizontalAxis, bIsVerticalAxis ) )
+            {
+                // This tick overlaps with its neighbor. Increment the visible
+                // tick intervals (if that's allowed) and start over.
+
+                if( rAxisLabelProperties.bRhythmIsFix )
+                    continue;
+                rAxisLabelProperties.nRhythm++;
+                removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
+                return false;
+            }
+        }
+
+        bool bHasExtraColor=false;
+        sal_Int32 nExtraColor=0;
+
+        OUString aLabel;
+        if(pCategories)
+        {
+            // This is a normal category axis.  Get the label string from the
+            // label string array.
+            sal_Int32 nIndex = static_cast<sal_Int32>(pTickInfo->getUnscaledTickValue()) - 1; //first category (index 0) matches with real number 1.0
+            if( nIndex>=0 && nIndex<pCategories->getLength() )
+                aLabel = (*pCategories)[nIndex];
+        }
+        else if( m_aAxisProperties.m_bComplexCategories )
+        {
+            // This is a complex category axis.  The label is stored in the tick.
+            aLabel = pTickInfo->aText;
+        }
+        else
+        {
+            // This is a numeric axis.  Format the original tick value per number format.
+            aLabel = aFixedNumberFormatter.getFormattedString( pTickInfo->getUnscaledTickValue(), nExtraColor, bHasExtraColor );
+        }
+
+        if(pColorAny)
+            *pColorAny = uno::makeAny(bHasExtraColor?nExtraColor:nColor);
+        if(pLimitedSpaceAny)
+            *pLimitedSpaceAny = uno::makeAny(sal_Int32(-1*pTickInfo->nFactorForLimitedTextWidth));
+
+        B2DVector aTickScreenPos2D = pTickInfo->aTickScreenPosition;
+        aTickScreenPos2D += aTextToTickDistance;
+        awt::Point aAnchorScreenPosition2D(
+            static_cast<sal_Int32>(aTickScreenPos2D.getX())
+            ,static_cast<sal_Int32>(aTickScreenPos2D.getY()));
+
+        //create single label
+        if(!pTickInfo->xTextShape.is())
+            pTickInfo->xTextShape = createSingleLabel( m_xShapeFactory, xTarget
+                                    , aAnchorScreenPosition2D, aLabel
+                                    , rAxisLabelProperties, m_aAxisProperties
+                                    , aPropNames, aPropValues );
+        if(!pTickInfo->xTextShape.is())
+            continue;
+
+        recordMaximumTextSize( pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree );
+
+        //if NO OVERLAP -> remove overlapping shapes
+        if( pLastVisibleNeighbourTickInfo && !rAxisLabelProperties.bOverlapAllowed )
+        {
+            // Check if the label still overlaps with its neighber.
+            if( doesOverlap( pLastVisibleNeighbourTickInfo->xTextShape, pTickInfo->xTextShape, rAxisLabelProperties.fRotationAngleDegree ) )
+            {
+                // It overlaps.
+                if( !rAxisLabelProperties.bOverlapAllowed && ::rtl::math::approxEqual( rAxisLabelProperties.fRotationAngleDegree, 0.0 ) )
+                {
+                    // Try auto-rotating the labels at 45 degrees and
+                    // start over.  This rotation angle will be stored for
+                    // all future text shape creation runs.
+
+                    rAxisLabelProperties.fRotationAngleDegree = 45;
+                    rAxisLabelProperties.bLineBreakAllowed = false;
+                    rAxisLabelProperties.eStaggering = SIDE_BY_SIDE;
+                    m_aAxisLabelProperties.fRotationAngleDegree = rAxisLabelProperties.fRotationAngleDegree; // Store it for future runs.
+                    removeTextShapesFromTicks();
+                    return false;
+                }
+
+                if( rAxisLabelProperties.bRhythmIsFix )
+                {
+                    // Tick interval is fixed.  We have no choice but to
+                    // remove this label.
+                    xTarget->remove(pTickInfo->xTextShape);
+                    pTickInfo->xTextShape = NULL;
+                    continue;
+                }
+
+                // Try incrementing the tick interval and start over.
+                rAxisLabelProperties.nRhythm++;
+                removeShapesAtWrongRhythm( rTickIter, rAxisLabelProperties.nRhythm, nTick, xTarget );
+                return false;
+            }
+        }
+
+        pPreviousVisibleTickInfo = pTickInfo;
+    }
+    return true;
+}
+
 drawing::PointSequenceSequence lcl_makePointSequence( B2DVector& rStart, B2DVector& rEnd )
 {
     drawing::PointSequenceSequence aPoints(1);
@@ -1377,7 +1545,7 @@ void VCartesianAxis::doStaggeringOfLabels( const AxisLabelProperties& rAxisLabel
             }
         }
     }
-    else if( rAxisLabelProperties.getIsStaggered() )
+    else if (rAxisLabelProperties.isStaggered())
     {
         if( !m_aAllTickInfos.empty() )
         {
diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx
index 3b9886d..839d5e8 100644
--- a/chart2/source/view/axes/VCartesianAxis.hxx
+++ b/chart2/source/view/axes/VCartesianAxis.hxx
@@ -117,12 +117,20 @@ private: //methods
      *         have changed during the call, and the caller needs to call this
      *         method once again to get the text shapes created.
      */
-    bool    createTextShapes( const ::com::sun::star::uno::Reference<
-                       ::com::sun::star::drawing::XShapes >& xTarget
-                     , TickIter& rTickIter
-                     , AxisLabelProperties& rAxisLabelProperties
-                     , TickFactory2D* pTickFactory
-                     , sal_Int32 nScreenDistanceBetweenTicks );
+    bool createTextShapes(
+        const css::uno::Reference<css::drawing::XShapes >& xTarget,
+        TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties,
+        TickFactory2D* pTickFactory, sal_Int32 nScreenDistanceBetweenTicks );
+
+    /**
+     * Variant of createTextShapes where none of auto-staggering and
+     * link-breaking are allowed in case of overlaps.  Overlaps of text shapes
+     * are to be resolved only by adjusting the label tick interval.
+     */
+    bool createTextShapesSimple(
+        const css::uno::Reference<css::drawing::XShapes >& xTarget,
+        TickIter& rTickIter, AxisLabelProperties& rAxisLabelProperties,
+        TickFactory2D* pTickFactory );
 
     void createTickMarkLineShapes( TickInfoArrayType& rTickInfos, const TickmarkProperties& rTickmarkProperties, TickFactory2D& rTickFactory2D, bool bOnlyAtLabels );
 
commit 0bf0c8af7e22ee2745ca32d8c0291ebc687893bd
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 22 10:25:42 2014 -0400

    These methods can be private rather than protected.
    
    Change-Id: I56f1296f5a2df67ae9386ae9f30761aee0fde7f3

diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx
index 8abe4eb..3b9886d 100644
--- a/chart2/source/view/axes/VCartesianAxis.hxx
+++ b/chart2/source/view/axes/VCartesianAxis.hxx
@@ -100,7 +100,7 @@ public:
         ::basegfx::B2DVector aScreenPos;
     };
 
-protected: //methods
+private: //methods
     /**
      * Go through all tick label positions and decide which labels to display
      * based on the text shape geometry, overlap setting, tick interval,
commit 15a501b6e05fb2490b69a98a4c0782f09dd326d2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 22 09:56:01 2014 -0400

    More method descriptions.
    
    I'm starting to "get" this axis label layout code.
    
    Change-Id: I797a92698cb81a1b9325f81b5275cb033cb7c342

diff --git a/chart2/source/view/axes/VCartesianAxis.hxx b/chart2/source/view/axes/VCartesianAxis.hxx
index 2492bb0..8abe4eb 100644
--- a/chart2/source/view/axes/VCartesianAxis.hxx
+++ b/chart2/source/view/axes/VCartesianAxis.hxx
@@ -131,14 +131,24 @@ protected: //methods
 
     /**
      * Shift the screen positions of the tick labels according to the stagger
-     * settings.  Stagger setting is finalized during the createTextShapes
+     * settings.  Final stagger setting is decided during the createTextShapes
      * call, but this method does the physical shifting of the label
-     * positions.
+     * positions based on the final stagger setting.
      */
     void    doStaggeringOfLabels( const AxisLabelProperties& rAxisLabelProperties
                             , TickFactory2D* pTickFactory2D );
+
+    /**
+     * @return true if we can try to stagger labels in order to avoid
+     *         overlaps, otherwise false.
+     */
     bool isAutoStaggeringOfLabelsAllowed(
         const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis, bool bIsVerticalAxis ) const;
+
+    /**
+     * @return true if we can break a single line label text into multiple
+     *         lines for better fitting, otherwise false.
+     */
     bool isBreakOfLabelsAllowed( const AxisLabelProperties& rAxisLabelProperties, bool bIsHorizontalAxis ) const;
 
     ::basegfx::B2DVector getScreenPosition( double fLogicX, double fLogicY, double fLogicZ ) const;


More information about the Libreoffice-commits mailing list