diff options
author | EricSeynaeve <github@nosperse.com> | 2013-02-28 23:07:09 +0100 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2013-03-19 02:36:46 +0100 |
commit | bf033461c5cb0053253f410da7f17dd2e12771c3 (patch) | |
tree | c145918c8a4fbe92c2d60aeaea90a6b5611a4e15 | |
parent | 91c8b357ee2a27e50da0e99386e53d351e55cfda (diff) |
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 values used in Gnumeric. These values
are converted to ODF1.3 during save.
Change-Id: I0f04a779de4b65326ed7ce6de56191f11b51c596
-rw-r--r-- | chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx | 72 | ||||
-rw-r--r-- | chart2/source/view/charttypes/AreaChart.cxx | 143 | ||||
-rw-r--r-- | chart2/source/view/charttypes/AreaChart.hxx | 4 | ||||
-rw-r--r-- | offapi/com/sun/star/chart2/CurveStyle.idl | 42 | ||||
-rw-r--r-- | xmloff/inc/xmloff/xmltoken.hxx | 8 | ||||
-rw-r--r-- | xmloff/source/chart/PropertyMap.hxx | 18 | ||||
-rw-r--r-- | xmloff/source/core/xmltoken.cxx | 10 | ||||
-rw-r--r-- | xmloff/source/transform/StyleOASISTContext.cxx | 2 |
8 files changed, 280 insertions, 19 deletions
diff --git a/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx index 53dff54d906a..6f9d57f05860 100644 --- a/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx +++ b/chart2/source/controller/chartapiwrapper/WrappedSplineProperties.cxx @@ -231,12 +231,29 @@ Any WrappedSplineTypeProperty::convertInnerToOuterValue( const Any& rInnerValue 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; + default: + nOuterValue = 0; + } return uno::makeAny(nOuterValue); } @@ -247,12 +264,43 @@ Any WrappedSplineTypeProperty::convertOuterToInnerValue( const Any& rOuterValue 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; + // map the pre-ODF1.3 Gnumeric values to ODF1.3 + case 7: + aInnerValue = chart2::CurveStyle_STEP_START; + break; + case 8: + aInnerValue = chart2::CurveStyle_STEP_END; + break; + case 9: + aInnerValue = chart2::CurveStyle_STEP_CENTER_X; + break; + case 10: + aInnerValue = chart2::CurveStyle_STEP_CENTER_Y; + break; + default: + SAL_WARN_IF(chart2::CurveStyle_LINES != 0, "chart2", "Unknown line style"); + 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 a9e207c628d8..03f13b17db62 100644 --- a/chart2/source/view/charttypes/AreaChart.cxx +++ b/chart2/source/view/charttypes/AreaChart.cxx @@ -287,6 +287,135 @@ void lcl_removeDuplicatePoints( drawing::PolyPolygonShape3D& rPolyPoly, Plotting 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) + 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: + /** 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: + /** +------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: + /** +--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: + /** 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 +438,20 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries 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 + ) { + if (!create_stepped_line(*pSeriesPoly, m_eCurveStyle, pPosHelper, aPoly)) + { + return false; + } + } + else + { // default to creating a straight line + SAL_WARN_IF(CurveStyle_LINES != m_eCurveStyle, "chart2.areachart", "Unknown curve style"); 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 cc8b9ae0012b..cb6ea9f3416d 100644 --- a/chart2/source/view/charttypes/AreaChart.hxx +++ b/chart2/source/view/charttypes/AreaChart.hxx @@ -80,6 +80,10 @@ private: //methods 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 31641862a782..65a7947934ec 100644 --- a/offapi/com/sun/star/chart2/CurveStyle.idl +++ b/offapi/com/sun/star/chart2/CurveStyle.idl @@ -48,7 +48,47 @@ enum CurveStyle /** */ - NURBS + NURBS, + + /** 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 }; } ; // chart2 diff --git a/xmloff/inc/xmloff/xmltoken.hxx b/xmloff/inc/xmloff/xmltoken.hxx index 605256f9229e..8ca24b48a4a9 100644 --- a/xmloff/inc/xmloff/xmltoken.hxx +++ b/xmloff/inc/xmloff/xmltoken.hxx @@ -2555,6 +2555,14 @@ namespace xmloff { namespace token { 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 e8298a6fd70d..023947194930 100644 --- a/xmloff/source/chart/PropertyMap.hxx +++ b/xmloff/source/chart/PropertyMap.hxx @@ -290,10 +290,20 @@ SvXMLEnumMapEntry aXMLChartInterpolationTypeEnumMap[] = { // 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 }, + // the GNM values should only be used for reading Gnumeric ods files + // they should never be used for writing ods file + { ::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 46e3a4f46083..b195b94c41ad 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -2556,6 +2556,16 @@ namespace xmloff { namespace token { 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 ), + // the gnm: values should only used for reading Gnumeric ods file + // these values should never be written + 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 cd76458ad584..fb05750b6e72 100644 --- a/xmloff/source/transform/StyleOASISTContext.cxx +++ b/xmloff/source/transform/StyleOASISTContext.cxx @@ -315,7 +315,7 @@ void XMLPropertiesTContext_Impl::StartElement( break; case XML_OPTACTION_INTERPOLATION: { - // 0: none + // 0: none (default) sal_Int32 nSplineType = 0; if( IsXMLToken( rAttrValue, XML_CUBIC_SPLINE )) nSplineType = 1; |