diff options
author | Regina Henschel <rb.henschel@t-online.de> | 2023-11-19 00:26:16 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-12-01 08:44:01 +0100 |
commit | 44ee19c99bfb3bf0f550d9656e87bca3e20e5ca0 (patch) | |
tree | 3c937a4c86ec15400a12fb1e69ae893fc8541d39 /xmloff | |
parent | a83088b05f177fb938c2e4ffb06cd19362a5a1ca (diff) |
[API CHANGE] Add OOXML way of curved connector routing
The paths generated for curved connectors are basically incompatible
between LibreOffice and OOXML. Thus it was not possible to render curved
connectors the same way as MS Office. The patch adds an OOXML compatible
method for calculating the path. The new method results in a different
svg:d attribute when saved in ODF, but needs no change to ODF.
The patch introduces the boolean connector property 'EdgeOOXMLCurve' to
switch between the two methods. The property value is determined from
the svg:d attribute in case of import from ODF. In case of missing
svg:d attribute the property value is set to 'true', because Word
currently does not write a svg:d attribute when it exports to ODF.
The property value is set to 'true' for import of connectors on a
drawing canvas in docx. Default value for new connectors is 'false'.
The new property has no UI, but can be used via macro.
Currently the new method is used for import of curved connectors on
drawing canvas in docx documents.
Change-Id: I53d99f44febe4d74c2b611f5fdb9de86628c4519
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159708
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'xmloff')
-rw-r--r-- | xmloff/source/draw/ximpshap.cxx | 54 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.hxx | 5 |
2 files changed, 57 insertions, 2 deletions
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index d228b729521c..6cf226274115 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -1749,7 +1749,8 @@ SdXMLConnectorShapeContext::SdXMLConnectorShapeContext( mnEndGlueId(-1), mnDelta1(0), mnDelta2(0), - mnDelta3(0) + mnDelta3(0), + mbLikelyOOXMLCurve(true) { } @@ -1774,6 +1775,50 @@ bool SvXMLImport::needFixPositionAfterZ() const return bWrongPositionAfterZ; } +namespace +{ +bool lcl_IsLikelyOOXMLCurve(const basegfx::B2DPolygon& rPolygon) +{ + sal_uInt32 nCount = rPolygon.count(); + if (!rPolygon.areControlPointsUsed() or nCount < 2) + return false; // no curve at all + + basegfx::B2DVector aStartVec(rPolygon.getNextControlPoint(0) - rPolygon.getB2DPoint(0)); + basegfx::B2DVector aEndVec(rPolygon.getPrevControlPoint(nCount-1) - rPolygon.getB2DPoint(nCount - 1)); + // LibreOffice uses one point less than OOXML for the same underlaying bentConnector or + // STANDARD connector, respectively. A deeper inspection is only needed in case of 2 resulting + // points. Those connector paths look like a quarter ellipse. + switch (nCount) + { + case 2: + { + // In case start and end direction are parallel, it cannot be OOXML because that case + // introduces a handle on the path and the curve has three points then. + if (basegfx::areParallel(aStartVec, aEndVec)) + return false; + // OOXML sets the control point at 1/2, LibreOffice at 2/3 of width or height. + // A tolerance is used because +-1 deviations due to integer arithmetic in many places. + basegfx::B2DRange aRect(rPolygon.getB2DPoint(0), rPolygon.getB2DPoint(1)); + if ((basegfx::fTools::equalZero(aStartVec.getX()) + && basegfx::fTools::equal(aStartVec.getLength() * 2.0, aRect.getHeight(), 2.0)) + || (basegfx::fTools::equalZero(aStartVec.getY()) + && basegfx::fTools::equal(aStartVec.getLength() * 2.0, aRect.getWidth(), 2.0))) + return true; + } + break; + case 3: + case 5: + return basegfx::areParallel(aStartVec, aEndVec); + break; + case 4: // start and end direction are orthogonal + return basegfx::fTools::equalZero(aStartVec.scalar( aEndVec)); + break; + default: + return false; + } + return false; +} +} // end namespace // this is called from the parent group for each unparsed attribute in the attribute list bool SdXMLConnectorShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter ) @@ -1859,6 +1904,8 @@ bool SdXMLConnectorShapeContext::processAttribute( const sax_fastparser::FastAtt aPolyPolygon, aSourcePolyPolygon); maPath <<= aSourcePolyPolygon; + + mbLikelyOOXMLCurve = lcl_IsLikelyOOXMLCurve(aPolyPolygon.getB2DPolygon(0)); } } break; @@ -1921,13 +1968,16 @@ void SdXMLConnectorShapeContext::startFastElement (sal_Int32 nElement, } } + uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY ); + if (xProps.is()) + xProps->setPropertyValue("EdgeOOXMLCurve", Any(mbLikelyOOXMLCurve)); + // add connection ids if( !maStartShapeId.isEmpty() ) GetImport().GetShapeImport()->addShapeConnection( mxShape, true, maStartShapeId, mnStartGlueId ); if( !maEndShapeId.isEmpty() ) GetImport().GetShapeImport()->addShapeConnection( mxShape, false, maEndShapeId, mnEndGlueId ); - uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY ); if( xProps.is() ) { xProps->setPropertyValue("StartPosition", Any(maStart)); diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx index 64b28df579a0..3450a16e5780 100644 --- a/xmloff/source/draw/ximpshap.hxx +++ b/xmloff/source/draw/ximpshap.hxx @@ -296,6 +296,11 @@ private: css::uno::Any maPath; + // Guess from the svg:d attribute whether the shape was rendered using OOXML definition. The + // default value is true to cover files exported to ODF by MS Office, which does not write a + // svg:d attribute. LibreOffice has always written a svg:d attribute. + bool mbLikelyOOXMLCurve; + public: SdXMLConnectorShapeContext( SvXMLImport& rImport, |