[PATCH] fdo#61135 stepped lines graph: handle ods files

Eric Seynaeve (via Code Review) gerrit at gerrit.libreoffice.org
Thu Feb 28 14:45:44 PST 2013


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/2476

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/76/2476/1

fdo#61135 stepped lines graph: handle ods files

The boilerplate code for drawing the 4 types of stepped is in place (as
described in ODF1.3,
https://tools.oasis-open.org/issues/browse/OFFICE-3662).
We can also read the current attribute used in Gnumeric and keep this
during saves from LO.

Change-Id: I0f04a779de4b65326ed7ce6de56191f11b51c596
---
M chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx
M chart2/source/view/charttypes/AreaChart.cxx
M chart2/source/view/charttypes/AreaChart.hxx
M offapi/com/sun/star/chart2/CurveStyle.idl
M xmloff/inc/xmloff/xmltoken.hxx
M xmloff/source/chart/PropertyMap.hxx
M xmloff/source/core/xmltoken.cxx
M xmloff/source/transform/StyleOASISTContext.cxx
8 files changed, 316 insertions(+), 22 deletions(-)



diff --git a/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx
index d68bdc5..d3db08d 100644
--- a/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx
+++ b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx
@@ -231,12 +231,41 @@
     rInnerValue >>= aInnerValue;
 
     sal_Int32 nOuterValue;
-    if( chart2::CurveStyle_CUBIC_SPLINES == aInnerValue )
-        nOuterValue = 1;
-    else if( chart2::CurveStyle_B_SPLINES == aInnerValue )
-        nOuterValue = 2;
-    else
-        nOuterValue = 0;
+    switch (aInnerValue)
+    {
+        case chart2::CurveStyle_CUBIC_SPLINES:
+            nOuterValue = 1;
+            break;
+        case chart2::CurveStyle_B_SPLINES:
+            nOuterValue = 2;
+            break;
+        case chart2::CurveStyle_STEP_START:
+            nOuterValue = 3;
+            break;
+        case chart2::CurveStyle_STEP_END:
+            nOuterValue = 4;
+            break;
+        case chart2::CurveStyle_STEP_CENTER_X:
+            nOuterValue = 5;
+            break;
+        case chart2::CurveStyle_STEP_CENTER_Y:
+            nOuterValue = 6;
+            break;
+        case chart2::CurveStyle_GNM_STEP_START:
+            nOuterValue = 7;
+            break;
+        case chart2::CurveStyle_GNM_STEP_END:
+            nOuterValue = 8;
+            break;
+        case chart2::CurveStyle_GNM_STEP_CENTER_X:
+            nOuterValue = 9;
+            break;
+        case chart2::CurveStyle_GNM_STEP_CENTER_Y:
+            nOuterValue = 10;
+            break;
+        default:
+            nOuterValue = 0;
+    }
 
     return uno::makeAny(nOuterValue);
 }
@@ -247,12 +276,42 @@
 
     chart2::CurveStyle aInnerValue;
 
-    if(1==nOuterValue)
-        aInnerValue = chart2::CurveStyle_CUBIC_SPLINES;
-    else if(2==nOuterValue)
-        aInnerValue = chart2::CurveStyle_B_SPLINES;
-    else
-        aInnerValue = chart2::CurveStyle_LINES;
+    switch (nOuterValue)
+    {
+        case 1:
+            aInnerValue = chart2::CurveStyle_CUBIC_SPLINES;
+            break;
+        case 2:
+            aInnerValue = chart2::CurveStyle_B_SPLINES;
+            break;
+        case 3:
+            aInnerValue = chart2::CurveStyle_STEP_START;
+            break;
+        case 4:
+            aInnerValue = chart2::CurveStyle_STEP_END;
+            break;
+        case 5:
+            aInnerValue = chart2::CurveStyle_STEP_CENTER_X;
+            break;
+        case 6:
+            aInnerValue = chart2::CurveStyle_STEP_CENTER_Y;
+            break;
+        case 7:
+            aInnerValue = chart2::CurveStyle_GNM_STEP_START;
+            break;
+        case 8:
+            aInnerValue = chart2::CurveStyle_GNM_STEP_END;
+            break;
+        case 9:
+            aInnerValue = chart2::CurveStyle_GNM_STEP_CENTER_X;
+            break;
+        case 10:
+            aInnerValue = chart2::CurveStyle_GNM_STEP_CENTER_Y;
+            break;
+        default:
+            // TODO: add an error is nOuterValue != 0 and we're in debugging mode
+            aInnerValue = chart2::CurveStyle_LINES;
+    }
 
     return uno::makeAny(aInnerValue);
 }
diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx
index a9e207c..a1bacc3 100644
--- a/chart2/source/view/charttypes/AreaChart.cxx
+++ b/chart2/source/view/charttypes/AreaChart.cxx
@@ -287,6 +287,140 @@
     rPolyPoly=aTmp;
 }
 
+bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, chart2::CurveStyle eCurveStyle, PlottingPositionHelper* pPosHelper, drawing::PolyPolygonShape3D &aPoly )
+{
+    drawing::PolyPolygonShape3D aSteppedPoly;
+
+    aSteppedPoly.SequenceX.realloc(0);
+    aSteppedPoly.SequenceY.realloc(0);
+    aSteppedPoly.SequenceZ.realloc(0);
+
+    sal_uInt32 nOuterCount = aStartPoly.SequenceX.getLength();
+    if ( !nOuterCount )
+        return false;
+
+    aSteppedPoly.SequenceX.realloc(nOuterCount);
+    aSteppedPoly.SequenceY.realloc(nOuterCount);
+    aSteppedPoly.SequenceZ.realloc(nOuterCount);
+    for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+    {
+        if( aStartPoly.SequenceX[nOuter].getLength() <= 1 )
+            continue; //we need at least two points
+
+        sal_uInt32 nMaxIndexPoints = aStartPoly.SequenceX[nOuter].getLength()-1; // is >1
+        sal_uInt32 nNewIndexPoints = 0;
+        if ( CurveStyle_STEP_START==eCurveStyle || CurveStyle_STEP_END==eCurveStyle ||
+             CurveStyle_GNM_STEP_START==eCurveStyle || CurveStyle_GNM_STEP_END==eCurveStyle)
+            nNewIndexPoints = nMaxIndexPoints * 2 + 1;
+        else
+            nNewIndexPoints = nMaxIndexPoints * 3 + 1;
+
+        const double* pOldX = aStartPoly.SequenceX[nOuter].getConstArray();
+        const double* pOldY = aStartPoly.SequenceY[nOuter].getConstArray();
+        const double* pOldZ = aStartPoly.SequenceZ[nOuter].getConstArray();
+
+        aSteppedPoly.SequenceX[nOuter].realloc( nNewIndexPoints );
+        aSteppedPoly.SequenceY[nOuter].realloc( nNewIndexPoints );
+        aSteppedPoly.SequenceZ[nOuter].realloc( nNewIndexPoints );
+
+        double* pNewX = aSteppedPoly.SequenceX[nOuter].getArray();
+        double* pNewY = aSteppedPoly.SequenceY[nOuter].getArray();
+        double* pNewZ = aSteppedPoly.SequenceZ[nOuter].getArray();
+
+        pNewX[0] = pOldX[0];
+        pNewY[0] = pOldY[0];
+        pNewZ[0] = pOldZ[0];
+        for( sal_uInt32 oi = 0; oi < nMaxIndexPoints; oi++ )
+        {
+            switch ( eCurveStyle )
+            {
+                case CurveStyle_STEP_START:
+                case CurveStyle_GNM_STEP_START:
+                     /**           O
+                                   |
+                                   |
+                                   |
+                             O-----+
+                     */
+                    // create the intermediate point
+                    pNewX[1+oi*2] = pOldX[oi+1];
+                    pNewY[1+oi*2] = pOldY[oi];
+                    pNewZ[1+oi*2] = pOldZ[oi];
+                    // and now the normal one
+                    pNewX[1+oi*2+1] = pOldX[oi+1];
+                    pNewY[1+oi*2+1] = pOldY[oi+1];
+                    pNewZ[1+oi*2+1] = pOldZ[oi+1];
+                    break;
+                case CurveStyle_STEP_END:
+                case CurveStyle_GNM_STEP_END:
+                     /**    +------O
+                            |
+                            |
+                            |
+                            O
+                     */
+                    // create the intermediate point
+                    pNewX[1+oi*2] = pOldX[oi];
+                    pNewY[1+oi*2] = pOldY[oi+1];
+                    pNewZ[1+oi*2] = pOldZ[oi];
+                    // and now the normal one
+                    pNewX[1+oi*2+1] = pOldX[oi+1];
+                    pNewY[1+oi*2+1] = pOldY[oi+1];
+                    pNewZ[1+oi*2+1] = pOldZ[oi+1];
+                    break;
+                case CurveStyle_STEP_CENTER_X:
+                case CurveStyle_GNM_STEP_CENTER_X:
+                     /**        +--O
+                                |
+                                |
+                                |
+                             O--+
+                     */
+                    // create the first intermediate point
+                    pNewX[1+oi*3] = (pOldX[oi]+pOldX[oi+1])/2;
+                    pNewY[1+oi*3] = pOldY[oi];
+                    pNewZ[1+oi*3] = pOldZ[oi];
+                    // create the second intermediate point
+                    pNewX[1+oi*3+1] = (pOldX[oi]+pOldX[oi+1])/2;
+                    pNewY[1+oi*3+1] = pOldY[oi+1];
+                    pNewZ[1+oi*3+1] = pOldZ[oi];
+                    // and now the normal one
+                    pNewX[1+oi*3+2] = pOldX[oi+1];
+                    pNewY[1+oi*3+2] = pOldY[oi+1];
+                    pNewZ[1+oi*3+2] = pOldZ[oi+1];
+                    break;
+                case CurveStyle_STEP_CENTER_Y:
+                case CurveStyle_GNM_STEP_CENTER_Y:
+                     /**           O
+                                   |
+                             +-----+
+                             |
+                             O
+                     */
+                    // create the first intermediate point
+                    pNewX[1+oi*3] = pOldX[oi];
+                    pNewY[1+oi*3] = (pOldY[oi]+pOldY[oi+1])/2;
+                    pNewZ[1+oi*3] = pOldZ[oi];
+                    // create the second intermediate point
+                    pNewX[1+oi*3+1] = pOldX[oi+1];
+                    pNewY[1+oi*3+1] = (pOldY[oi]+pOldY[oi+1])/2;
+                    pNewZ[1+oi*3+1] = pOldZ[oi];
+                    // and now the normal one
+                    pNewX[1+oi*3+2] = pOldX[oi+1];
+                    pNewY[1+oi*3+2] = pOldY[oi+1];
+                    pNewZ[1+oi*3+2] = pOldZ[oi+1];
+                    break;
+                default:
+                    // this should never be executed
+                    OSL_FAIL("Unknown curvestyle in AreaChart::create_stepped_line");
+            }
+        }
+    }
+    Clipping::clipPolygonAtRectangle( aSteppedPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
+
+    return true;
+}
+
 bool AreaChart::impl_createLine( VDataSeries* pSeries
                 , drawing::PolyPolygonShape3D* pSeriesPoly
                 , PlottingPositionHelper* pPosHelper )
@@ -309,8 +443,23 @@
         lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
         Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
     }
-    else
+    else if (CurveStyle_STEP_START==m_eCurveStyle ||
+             CurveStyle_STEP_END==m_eCurveStyle ||
+             CurveStyle_STEP_CENTER_Y==m_eCurveStyle ||
+             CurveStyle_STEP_CENTER_X==m_eCurveStyle ||
+             CurveStyle_GNM_STEP_START==m_eCurveStyle ||
+             CurveStyle_GNM_STEP_END==m_eCurveStyle ||
+             CurveStyle_GNM_STEP_CENTER_Y==m_eCurveStyle ||
+             CurveStyle_GNM_STEP_CENTER_X==m_eCurveStyle)
     {
+        if (!create_stepped_line(*pSeriesPoly, m_eCurveStyle, pPosHelper, aPoly))
+        {
+            return false;
+        }
+    }
+    else
+    { // default to creating a straight line
+        // TODO: in debugging mode, print a warning when the linetype is not CurveStyle_LINES
         bool bIsClipped = false;
         if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
         {
diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx
index cc8b9ae..cb6ea9f 100644
--- a/chart2/source/view/charttypes/AreaChart.hxx
+++ b/chart2/source/view/charttypes/AreaChart.hxx
@@ -80,6 +80,10 @@
     bool impl_createLine( VDataSeries* pSeries
                 , ::com::sun::star::drawing::PolyPolygonShape3D* pSeriesPoly
                 , PlottingPositionHelper* pPosHelper );
+    bool create_stepped_line( ::com::sun::star::drawing::PolyPolygonShape3D aStartPoly
+                , ::com::sun::star::chart2::CurveStyle eCurveStyle
+                , PlottingPositionHelper* pPosHelper
+                , ::com::sun::star::drawing::PolyPolygonShape3D &aPoly );
 
 private: //member
     PlottingPositionHelper*             m_pMainPosHelper;
diff --git a/offapi/com/sun/star/chart2/CurveStyle.idl b/offapi/com/sun/star/chart2/CurveStyle.idl
index 3164186..5a6fdac 100644
--- a/offapi/com/sun/star/chart2/CurveStyle.idl
+++ b/offapi/com/sun/star/chart2/CurveStyle.idl
@@ -46,6 +46,55 @@
      */
     B_SPLINES,
 
+    /** Data points are connected via a 2-segmented stepped line.
+        The line starts horizontally.
+                   O
+                   |
+                   |
+                   |
+             O-----+
+     */
+    STEP_START,
+
+    /** Data points are connected via a 2-segmented stepped line.
+        The line ends horizontally.
+            +------O
+            |
+            |
+            |
+            O
+     */
+    STEP_END,
+
+    /** Data points are connected via a 3-segmented stepped line.
+        The lines is horizontal till the center of the X values.
+                +--O
+                |
+                |
+                |
+             O--+
+     */
+    STEP_CENTER_X,
+
+    /** Data points are connected via a 3-segmented stepped line.
+        The lines is horizontal at the center of the Y values.
+                   O
+                   |
+             +-----+
+             |
+             O
+     */
+    STEP_CENTER_Y,
+
+    /** These have the same meaning as above,
+        but are linked to the older Gnumeric attributes before
+        ODF1.3 was approved.
+     */
+    GNM_STEP_START,
+    GNM_STEP_END,
+    GNM_STEP_CENTER_X,
+    GNM_STEP_CENTER_Y,
+
     /**
      */
     NURBS
diff --git a/xmloff/inc/xmloff/xmltoken.hxx b/xmloff/inc/xmloff/xmltoken.hxx
index e7e886e..96025e4 100644
--- a/xmloff/inc/xmloff/xmltoken.hxx
+++ b/xmloff/inc/xmloff/xmltoken.hxx
@@ -2555,6 +2555,14 @@
         XML_INTERPOLATION,
         XML_CUBIC_SPLINE,
         XML_B_SPLINE,
+        XML_STEP_START,
+        XML_STEP_END,
+        XML_STEP_CENTER_X,
+        XML_STEP_CENTER_Y,
+        XML_GNM_STEP_START,
+        XML_GNM_STEP_END,
+        XML_GNM_STEP_CENTER_X,
+        XML_GNM_STEP_CENTER_Y,
         XML_N_DB_OASIS,
 
         XML_SHOW_FILTER_BUTTON,
diff --git a/xmloff/source/chart/PropertyMap.hxx b/xmloff/source/chart/PropertyMap.hxx
index e8298a6..d455a4a 100644
--- a/xmloff/source/chart/PropertyMap.hxx
+++ b/xmloff/source/chart/PropertyMap.hxx
@@ -290,10 +290,18 @@
 {
     // this is neither an enum nor a constants group, but just a
     // documented long property
-    { ::xmloff::token::XML_NONE,         0 },
-    { ::xmloff::token::XML_CUBIC_SPLINE, 1 },
-    { ::xmloff::token::XML_B_SPLINE,     2 },
-    { ::xmloff::token::XML_TOKEN_INVALID,0 }
+    { ::xmloff::token::XML_NONE,               0 },
+    { ::xmloff::token::XML_CUBIC_SPLINE,       1 },
+    { ::xmloff::token::XML_B_SPLINE,           2 },
+    { ::xmloff::token::XML_STEP_START,         3 },
+    { ::xmloff::token::XML_STEP_END,           4 },
+    { ::xmloff::token::XML_STEP_CENTER_X,      5 },
+    { ::xmloff::token::XML_STEP_CENTER_Y,      6 },
+    { ::xmloff::token::XML_GNM_STEP_START,     7 },
+    { ::xmloff::token::XML_GNM_STEP_END,       8 },
+    { ::xmloff::token::XML_GNM_STEP_CENTER_X,  9 },
+    { ::xmloff::token::XML_GNM_STEP_CENTER_Y, 10 },
+    { ::xmloff::token::XML_TOKEN_INVALID,      0 }
 };
 
 SvXMLEnumMapEntry aXMLChartDataLabelPlacementEnumMap[] =
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index afd52ba..c2d94d4 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -2556,6 +2556,15 @@
         TOKEN( "interpolation",                XML_INTERPOLATION ),
         TOKEN( "cubic-spline",                 XML_CUBIC_SPLINE ),
         TOKEN( "b-spline",                     XML_B_SPLINE ),
+        TOKEN( "step-start",                   XML_STEP_START ),
+        TOKEN( "step-end",                     XML_STEP_END ),
+        TOKEN( "step-center-x",                XML_STEP_CENTER_X ),
+        TOKEN( "step-center-y",                XML_STEP_CENTER_Y ),
+        // also understand the older Gnumeric tookens
+        TOKEN( "gnm:step-start",               XML_GNM_STEP_START ),
+        TOKEN( "gnm:step-end",                 XML_GNM_STEP_END ),
+        TOKEN( "gnm:step-center-x",            XML_GNM_STEP_CENTER_X ),
+        TOKEN( "gnm:step-center-y",            XML_GNM_STEP_CENTER_Y ),
         TOKEN( "urn:oasis:names:tc:opendocument:xmlns:database:1.0",     XML_N_DB_OASIS ),
 
         TOKEN( "show-filter-button",                   XML_SHOW_FILTER_BUTTON ),
diff --git a/xmloff/source/transform/StyleOASISTContext.cxx b/xmloff/source/transform/StyleOASISTContext.cxx
index 6f7caf7..f5fc845 100644
--- a/xmloff/source/transform/StyleOASISTContext.cxx
+++ b/xmloff/source/transform/StyleOASISTContext.cxx
@@ -315,18 +315,26 @@
                     break;
                 case XML_OPTACTION_INTERPOLATION:
                     {
-                        // 0: none
-                        sal_Int32 nSplineType = 0;
+                        // 0: none (default)
+                        sal_Int32 nLineType = 0;
                         if( IsXMLToken( rAttrValue, XML_CUBIC_SPLINE ))
-                            nSplineType = 1;
+                            nLineType = 1;
                         else if( IsXMLToken( rAttrValue, XML_B_SPLINE ))
-                            nSplineType = 2;
+                            nLineType = 2;
+                        else if( IsXMLToken( rAttrValue, XML_STEP_START )    || IsXMLToken( rAttrValue, XML_GNM_STEP_START ) )
+                            nLineType = 3;
+                        else if( IsXMLToken( rAttrValue, XML_STEP_END )      || IsXMLToken( rAttrValue, XML_GNM_STEP_END ) )
+                            nLineType = 4;
+                        else if( IsXMLToken( rAttrValue, XML_STEP_CENTER_X ) || IsXMLToken( rAttrValue, XML_GNM_STEP_CENTER_X ) )
+                            nLineType = 5;
+                        else if( IsXMLToken( rAttrValue, XML_STEP_CENTER_Y ) || IsXMLToken( rAttrValue, XML_GNM_STEP_CENTER_Y ) )
+                            nLineType = 6;
 
                         pAttrList->AddAttribute(
                             GetTransformer().GetNamespaceMap().GetQNameByKey(
                                 XML_NAMESPACE_CHART,
                                 GetXMLToken( XML_SPLINES )),
-                            OUString::valueOf( nSplineType ));
+                            OUString::valueOf( nLineType ));
                     }
                     break;
                 case XML_OPTACTION_INTERVAL_MAJOR:

-- 
To view, visit https://gerrit.libreoffice.org/2476
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0f04a779de4b65326ed7ce6de56191f11b51c596
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: master
Gerrit-Owner: Eric Seynaeve <github at nosperse.com>



More information about the LibreOffice mailing list