diff options
author | Zolnai Tamás <tamas.zolnai@collabora.com> | 2014-02-03 02:46:30 +0100 |
---|---|---|
committer | Zolnai Tamás <tamas.zolnai@collabora.com> | 2014-02-03 02:46:30 +0100 |
commit | 5c39b6b997ddc85e6848efc230a427a124b97264 (patch) | |
tree | 0a4faac2c991f3134a3f5963f5258e28d1931c3b | |
parent | 72b2fafebfc44fa90f08cc198e2fa5fc26154c5b (diff) |
drawingML export: custom geometry with cubic bezier curves
When the custom shape is not a preset shape then construct a
PolyPolygon and use DrawingML::WritePolyPolygon() to export it.
Change-Id: I6598976a475bfcb92305338af9016e09df4c9456
-rw-r--r-- | filter/source/msfilter/escherex.cxx | 89 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 2 | ||||
-rw-r--r-- | oox/source/export/shapes.cxx | 20 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/dml-customgeometry-cubicbezier.docx | bin | 0 -> 17348 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 64 |
5 files changed, 168 insertions, 7 deletions
diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx index 5a4cf4dddac1..293aead70e2b 100644 --- a/filter/source/msfilter/escherex.cxx +++ b/filter/source/msfilter/escherex.cxx @@ -1785,6 +1785,7 @@ PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno OUString sPolyPolygonBezier ( "PolyPolygonBezier" ); OUString sPolyPolygon ( "PolyPolygon" ); OUString sPolygon ( "Polygon" ); + OUString sCustomShapeGeometry ( "CustomShapeGeometry" ); if ( aAny >>= aXPropSet ) { @@ -1793,6 +1794,8 @@ PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygon, sal_True ); if ( !bHasProperty ) bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolygon, sal_True ); + if ( !bHasProperty ) + bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sCustomShapeGeometry, sal_True ); if ( bHasProperty ) aRetPolyPoly = GetPolyPolygon( aAny ); } @@ -1918,6 +1921,92 @@ PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno } } } + else if ( rAny.getValueType() == ::getCppuType( ( const uno::Sequence< beans::PropertyValue >* ) 0 ) ) + { + uno::Sequence< beans::PropertyValue >* pGeometrySeq = + (uno::Sequence< beans::PropertyValue >*)rAny.getValue(); + + if ( pGeometrySeq ) + { + for( int i = 0; i < pGeometrySeq->getLength(); ++i ) + { + const beans::PropertyValue& rProp = (*pGeometrySeq)[ i ]; + if ( rProp.Name == "Path" ) + { + uno::Sequence<beans::PropertyValue> aPathProp; + rProp.Value >>= aPathProp; + + uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aPairs; + uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments; + for (int j = 0; j < aPathProp.getLength(); ++j ) + { + const beans::PropertyValue& rPathProp = aPathProp[j]; + if (rPathProp.Name == "Coordinates") + rPathProp.Value >>= aPairs; + else if (rPathProp.Name == "Segments") + rPathProp.Value >>= aSegments; + } + + aPolygon = Polygon( aPairs.getLength() ); + for( int j = 0; j < aPairs.getLength(); ++j ) + { + aPolygon[j] = Point( aPairs[j].First.Value.get<sal_Int32>(), aPairs[j].Second.Value.get<sal_Int32>() ); + } + + int nPointIndex = 0; + for( int j = 0; j < aSegments.getLength(); ++j ) + { + for ( int k = 0; k < aSegments[j].Count; ++k ) + { + switch( aSegments[ j ].Command ) + { + case drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN: break; + case drawing::EnhancedCustomShapeSegmentCommand::MOVETO : nPointIndex++; break; + case drawing::EnhancedCustomShapeSegmentCommand::LINETO : nPointIndex++; break; + case drawing::EnhancedCustomShapeSegmentCommand::CURVETO : + { + aPolygon.SetFlags( nPointIndex, POLY_CONTROL); + aPolygon.SetFlags( nPointIndex+1, POLY_CONTROL); + aPolygon.SetFlags( nPointIndex+2, POLY_CONTROL); + nPointIndex += 3; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH : + case drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH : + case drawing::EnhancedCustomShapeSegmentCommand::NOFILL : + case drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE : + break; + case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO : + case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE : + nPointIndex += 3; + break; + case drawing::EnhancedCustomShapeSegmentCommand::ARCTO : + case drawing::EnhancedCustomShapeSegmentCommand::ARC : + case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO : + case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC : + nPointIndex += 4; + break; + case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX : + case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY : + nPointIndex++; + break; + case drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO : + case drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO : + nPointIndex += 2; + break; + case drawing::EnhancedCustomShapeSegmentCommand::DARKEN : break; + case drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS : break; + case drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN : break; + case drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS : break; + break; + } + } + } + aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND ); + } + } + } + } return aPolyPolygon; } diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 459b4253c984..3db4c04a10bc 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -1671,7 +1671,7 @@ void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon ) XML_y, I64S( rPoly[j].Y() - aRect.Top() ), FSEND ); - if( ( flags == POLY_NORMAL || flags == POLY_SYMMTR ) && bBezier ) + if( ( flags == POLY_NORMAL || flags == POLY_SYMMTR || j == rPoly.GetSize() - 1) && bBezier ) { mpFS->endElementNS( XML_a, XML_cubicBezTo ); bBezier = sal_False; diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index e55c2f3c8f8a..90b7ffa7e268 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -353,14 +353,22 @@ ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape ) // visual shape properties pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, false); - if( nAdjustmentValuesIndex != -1 ) + + if( sShapeType == "ooxml-non-primitive" ) // non-primitiv -> custom geometry { - sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0; - WritePresetShape( sPresetShape, eShapeType, bPredefinedHandlesUsed, - nAdjustmentsWhichNeedsToBeConverted, aGeometrySeq[ nAdjustmentValuesIndex ] ); + WritePolyPolygon( EscherPropertyContainer::GetPolyPolygon( xShape ) ); + } + else // preset geometry + { + if( nAdjustmentValuesIndex != -1 ) + { + sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0; + WritePresetShape( sPresetShape, eShapeType, bPredefinedHandlesUsed, + nAdjustmentsWhichNeedsToBeConverted, aGeometrySeq[ nAdjustmentValuesIndex ] ); + } + else + WritePresetShape( sPresetShape ); } - else - WritePresetShape( sPresetShape ); if( rXPropSet.is() ) { WriteFill( rXPropSet ); diff --git a/sw/qa/extras/ooxmlexport/data/dml-customgeometry-cubicbezier.docx b/sw/qa/extras/ooxmlexport/data/dml-customgeometry-cubicbezier.docx Binary files differnew file mode 100644 index 000000000000..baa47f43c102 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/dml-customgeometry-cubicbezier.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 8f1982d26de0..239bb0286c03 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -46,6 +46,9 @@ #include <rtl/strbuf.hxx> #include <comphelper/sequenceashashmap.hxx> #include <com/sun/star/text/XDocumentIndex.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> #include <libxml/xpathInternals.h> #include <libxml/parserInternals.h> @@ -2717,6 +2720,67 @@ DECLARE_OOXMLEXPORT_TEST(testDMLSolidfillAlpha, "dml-solidfill-alpha.docx") xShape.set(getShape(2), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(sal_Int16(20), getProperty<sal_Int16>(xShape, "FillTransparence")); } + +DECLARE_OOXMLEXPORT_TEST(testDMLCustomGeometry, "dml-customgeometry-cubicbezier.docx") +{ + + // The problem was that a custom shape was not exported. + uno::Sequence<beans::PropertyValue> aProps = getProperty< uno::Sequence<beans::PropertyValue> >(getShape(1), "CustomShapeGeometry"); + uno::Sequence<beans::PropertyValue> aPathProps; + for (int i = 0; i < aProps.getLength(); ++i) + { + const beans::PropertyValue& rProp = aProps[i]; + if (rProp.Name == "Path") + rProp.Value >>= aPathProps; + } + uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aPairs; + uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments; + for (int i = 0; i < aPathProps.getLength(); ++i) + { + const beans::PropertyValue& rProp = aPathProps[i]; + if (rProp.Name == "Coordinates") + rProp.Value >>= aPairs; + else if (rProp.Name == "Segments") + rProp.Value >>= aSegments; + } + + // (a:moveTo) + CPPUNIT_ASSERT_EQUAL(sal_Int16(1), aSegments[0].Count); + CPPUNIT_ASSERT_EQUAL(sal_Int16(drawing::EnhancedCustomShapeSegmentCommand::MOVETO), aSegments[0].Command ); + + // (a:cubicBezTo) + CPPUNIT_ASSERT_EQUAL(sal_Int16(5), aSegments[1].Count); + CPPUNIT_ASSERT_EQUAL(sal_Int16(drawing::EnhancedCustomShapeSegmentCommand::CURVETO), aSegments[1].Command ); + + // Coordinates + sal_Int32 nLength = 16; + CPPUNIT_ASSERT_EQUAL(nLength, aPairs.getLength()); + std::pair<sal_Int32,sal_Int32> aCoordinates[] = + { + std::pair<sal_Int32,sal_Int32>(607, 0), + std::pair<sal_Int32,sal_Int32>(450, 44), + std::pair<sal_Int32,sal_Int32>(300, 57), + std::pair<sal_Int32,sal_Int32>(176, 57), + std::pair<sal_Int32,sal_Int32>(109, 57), + std::pair<sal_Int32,sal_Int32>(49, 53), + std::pair<sal_Int32,sal_Int32>(0, 48), + std::pair<sal_Int32,sal_Int32>(66, 58), + std::pair<sal_Int32,sal_Int32>(152, 66), + std::pair<sal_Int32,sal_Int32>(251, 66), + std::pair<sal_Int32,sal_Int32>(358, 66), + std::pair<sal_Int32,sal_Int32>(480, 56), + std::pair<sal_Int32,sal_Int32>(607, 27), + std::pair<sal_Int32,sal_Int32>(607, 0), + std::pair<sal_Int32,sal_Int32>(607, 0), + std::pair<sal_Int32,sal_Int32>(607, 0) + }; + + for( int i = 0; i < nLength; ++i ) + { + CPPUNIT_ASSERT_EQUAL(aCoordinates[i].first, aPairs[i].First.Value.get<sal_Int32>()); + CPPUNIT_ASSERT_EQUAL(aCoordinates[i].second, aPairs[i].Second.Value.get<sal_Int32>()); + } +} #endif CPPUNIT_PLUGIN_IMPLEMENT(); |