From 481c185e327cb83ffcb29657d5a354eae2c4a5f3 Mon Sep 17 00:00:00 2001 From: Andras Timar Date: Tue, 26 May 2015 19:35:08 +0200 Subject: tdf#90338 tdf#84254 DrawingML export fix Change-Id: I610d8099f057a2a34a1f9573d8ac16b5b8da9fc7 Reviewed-on: https://gerrit.libreoffice.org/15918 Tested-by: Jenkins Reviewed-by: Andras Timar --- oox/source/export/drawingml.cxx | 206 ++++++++++++++++++++++++++++++++++++++++ oox/source/export/shapes.cxx | 17 ++-- 2 files changed, 213 insertions(+), 10 deletions(-) (limited to 'oox') diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index d202f12fc637..55e87e935551 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -43,6 +43,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -2198,6 +2202,208 @@ void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool b mpFS->endElementNS( XML_a, XML_prstGeom ); } +void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) +{ + uno::Reference< beans::XPropertySet > aXPropSet; + uno::Any aAny( rXShape->queryInterface(cppu::UnoType::get())); + + if ( ! (aAny >>= aXPropSet) ) + return; + + try + { + aAny = aXPropSet->getPropertyValue( "CustomShapeGeometry" ); + if ( !aAny.hasValue() ) + return; + } + catch( const ::uno::Exception& ) + { + return; + } + + + mpFS->startElementNS( XML_a, XML_custGeom, FSEND ); + mpFS->singleElementNS( XML_a, XML_avLst, FSEND ); + mpFS->singleElementNS( XML_a, XML_gdLst, FSEND ); + mpFS->singleElementNS( XML_a, XML_ahLst, FSEND ); + mpFS->singleElementNS( XML_a, XML_rect, + XML_l, "l", + XML_t, "t", + XML_r, "r", + XML_b, "b", + FSEND ); + + mpFS->startElementNS( XML_a, XML_pathLst, FSEND ); + + uno::Sequence< beans::PropertyValue > const * pGeometrySeq = + static_cast const *>(aAny.getValue()); + + if ( pGeometrySeq ) + { + for( int i = 0; i < pGeometrySeq->getLength(); ++i ) + { + const beans::PropertyValue& rProp = (*pGeometrySeq)[ i ]; + if ( rProp.Name == "Path" ) + { + uno::Sequence aPathProp; + rProp.Value >>= aPathProp; + + uno::Sequence aPairs; + uno::Sequence aSegments; + uno::Sequence aPathSize; + bool bHasSubViewSize = false; + 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; + else if (rPathProp.Name == "SubViewSize") + { + rPathProp.Value >>= aPathSize; + bHasSubViewSize = true; + } + } + + if ( bHasSubViewSize ) + { + mpFS->startElementNS( XML_a, XML_path, + XML_w, I64S( aPathSize[0].Width ), + XML_h, I64S( aPathSize[0].Height ), + FSEND ); + } + else + { + sal_Int32 nXMin = aPairs[0].First.Value.get(); + sal_Int32 nXMax = nXMin; + sal_Int32 nYMin = aPairs[0].Second.Value.get(); + sal_Int32 nYMax = nYMin; + + for ( int j = 0; j < aPairs.getLength(); ++j ) + { + if ( aPairs[j].First.Value.get() < nXMin ) + nXMin = aPairs[j].First.Value.get(); + if ( aPairs[j].Second.Value.get() < nYMin ) + nYMin = aPairs[j].Second.Value.get(); + if ( aPairs[j].First.Value.get() > nXMax ) + nXMax = aPairs[j].First.Value.get(); + if ( aPairs[j].Second.Value.get() > nYMax ) + nYMax = aPairs[j].Second.Value.get(); + } + mpFS->startElementNS( XML_a, XML_path, + XML_w, I64S( nXMax - nXMin ), + XML_h, I64S( nYMax - nYMin ), + FSEND ); + } + + + int nPairIndex = 0; + for( int j = 0; j < aSegments.getLength(); ++j ) + { + if ( aSegments[ j ].Command == drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH ) + { + mpFS->singleElementNS( XML_a, XML_close, FSEND ); + } + for ( int k = 0; k < aSegments[j].Count; ++k ) + { + switch( aSegments[ j ].Command ) + { + case drawing::EnhancedCustomShapeSegmentCommand::MOVETO : + { + mpFS->startElementNS( XML_a, XML_moveTo, FSEND ); + + mpFS->singleElementNS( XML_a, XML_pt, + XML_x, I64S( aPairs[nPairIndex].First.Value.get() ), + XML_y, I64S( aPairs[nPairIndex].Second.Value.get() ), + FSEND ); + + mpFS->endElementNS( XML_a, XML_moveTo ); + nPairIndex++; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::LINETO : + { + mpFS->startElementNS( XML_a, XML_lnTo, FSEND ); + mpFS->singleElementNS( XML_a, XML_pt, + XML_x, I64S( aPairs[nPairIndex].First.Value.get() ), + XML_y, I64S( aPairs[nPairIndex].Second.Value.get() ), + FSEND ); + mpFS->endElementNS( XML_a, XML_lnTo ); + nPairIndex++; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::CURVETO : + { + mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND ); + for( sal_uInt8 l = 0; l <= 2; ++l ) + { + mpFS->singleElementNS( XML_a, XML_pt, + XML_x, I64S( aPairs[nPairIndex+l].First.Value.get() ), + XML_y, I64S( aPairs[nPairIndex+l].Second.Value.get() ), + FSEND ); + + } + mpFS->endElementNS( XML_a, XML_cubicBezTo ); + nPairIndex += 3; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO : + case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE : + { + nPairIndex += 3; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::ARCTO : + case drawing::EnhancedCustomShapeSegmentCommand::ARC : + case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO : + case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC : + { + nPairIndex += 4; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX : + case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY : + { + nPairIndex++; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO : + { + mpFS->startElementNS( XML_a, XML_quadBezTo, FSEND ); + for( sal_uInt8 l = 0; l < 2; ++l ) + { + mpFS->singleElementNS( XML_a, XML_pt, + XML_x, I64S( aPairs[nPairIndex+l].First.Value.get() ), + XML_y, I64S( aPairs[nPairIndex+l].Second.Value.get() ), + FSEND ); + + } + mpFS->endElementNS( XML_a, XML_quadBezTo ); + nPairIndex += 2; + break; + } + case drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO : + { + nPairIndex += 2; + break; + } + default: + // do nothing + break; + } + } + } + mpFS->endElementNS( XML_a, XML_path ); + } + } + } + + mpFS->endElementNS( XML_a, XML_pathLst ); + + mpFS->endElementNS( XML_a, XML_custGeom ); +} + void DrawingML::WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon ) { if( rPolyPolygon.Count() < 1 ) diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index fb311b2fb54e..fedeefb34ebe 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -291,6 +291,7 @@ static bool lcl_IsOnBlacklist(OUString& rShapeType) static #endif const std::initializer_list vBlacklist = { + OUStringLiteral("ellipse"), OUStringLiteral("ring"), OUStringLiteral("can"), OUStringLiteral("cube"), @@ -478,17 +479,13 @@ ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape ) else if( bHasHandles ) bCustGeom = true; - if (bCustGeom && pShape) + if (bHasHandles && bCustGeom && pShape) { - basegfx::B2DPolyPolygon aB2DPolyPolygon = pShape->GetLineGeometry(true); - tools::PolyPolygon aPolyPolygon; - for( sal_uInt32 i = 0; i < aB2DPolyPolygon.count(); ++i ) - { - basegfx::B2DPolygon aB2DPolygon = aB2DPolyPolygon.getB2DPolygon(i); - aPolyPolygon.Insert( Polygon( aB2DPolygon ), POLYPOLY_APPEND ); - } - - WritePolyPolygon( aPolyPolygon ); + WritePolyPolygon( tools::PolyPolygon( pShape->GetLineGeometry(true) ) ); + } + else if (bCustGeom && pShape) + { + WriteCustomGeometry( xShape ); } else // preset geometry { -- cgit