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 <git...@nosperse.com> _______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice