diff options
author | Regina Henschel <rb.henschel@t-online.de> | 2022-04-23 21:52:29 +0200 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2022-04-27 13:20:00 +0200 |
commit | e9786a1439db437cc378f426c7cb496db20959fd (patch) | |
tree | 22eefee62af224b77fc2636871d99d3b360cffaa /oox | |
parent | d00bcd99a01e09259afa3c2ef17424aa2282a48b (diff) |
Do not start a:path with lnTo in export to OOXML
This is a follow up to commit 2029b2f6dd0109c5892e5ac5640022b31fe42fd2
The commands A, W, T or L of a draw:enhanced-path draw a line from
current point to start of the arc or end of line, respectivly. If
there is no current point the path is faulty and behavior is not
defined in ODF.
LibreOffice is tolerant and makes a move to the start point of the
arc or to the end point of the line. With this patch we do the same
now in export to OOXML, so the user gets the same shape geometry as in
LO. If a path starts with lnTo, MS Office will show nothing.
I wouldn't care about user-created faulty paths, but LO produces such
faulty path when an EllipseRibbon shape from binary MS Office is
imported. Even when that will be fixed, we need the fix here, because
the faulty path had been written to document markup and will be used
when such document is opened.
Change-Id: Ic52ec3bc78231b26efb592ddadee2e3042fdc065
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133349
Tested-by: Jenkins
Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133370
Diffstat (limited to 'oox')
-rw-r--r-- | oox/qa/unit/data/FaultyPathStart.odp | bin | 0 -> 14582 bytes | |||
-rw-r--r-- | oox/qa/unit/export.cxx | 20 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 25 |
3 files changed, 39 insertions, 6 deletions
diff --git a/oox/qa/unit/data/FaultyPathStart.odp b/oox/qa/unit/data/FaultyPathStart.odp Binary files differnew file mode 100644 index 000000000000..219795ffa58b --- /dev/null +++ b/oox/qa/unit/data/FaultyPathStart.odp diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx index e104b4effdd7..26d1a0e973bb 100644 --- a/oox/qa/unit/export.cxx +++ b/oox/qa/unit/export.cxx @@ -529,6 +529,26 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf147978_subpath) assertXPath(pXmlDoc, "//a:pathLst/a:path[4]", "w", "80"); assertXPath(pXmlDoc, "//a:pathLst/a:path[4]", "h", "80"); } + +CPPUNIT_TEST_FIXTURE(Test, testFaultyPathCommandsAWT) +{ + // The odp file contains shapes whose path starts with command A, W, T or L. That is a faulty + // path. LO is tolerant and renders it so that is makes a moveTo to the start point of the arc or + // the end of the line respectively. Export to OOXML does the same now and writes a moveTo + // instead of the normally used lnTo. If a lnTo is written, MS Office shows nothing of the shape. + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "FaultyPathStart.odp"; + + loadAndSave(aURL, "Impress Office Open XML"); + + // Verify the markup: + std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), "ppt/slides/slide1.xml"); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + // First child of a:path should be a moveTo in all four shapes. + assertXPath(pXmlDoc, "//p:spTree/p:sp[1]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"); + assertXPath(pXmlDoc, "//p:spTree/p:sp[2]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"); + assertXPath(pXmlDoc, "//p:spTree/p:sp[3]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"); + assertXPath(pXmlDoc, "//p:spTree/p:sp[4]/p:spPr/a:custGeom/a:pathLst/a:path/a:moveTo"); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 311669bd5cbe..c2bdf39042a4 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -3997,10 +3997,21 @@ bool DrawingML::WriteCustomGeometrySegment( { if (rnPairIndex >= rPairs.getLength()) return false; - - mpFS->startElementNS(XML_a, XML_lnTo); - WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d); - mpFS->endElementNS(XML_a, XML_lnTo); + // LINETO without valid current point is a faulty path. LO is tolerant and makes a + // moveTo instead. Do the same on export. MS OFFICE requires a current point for lnTo, + // otherwise it shows nothing of the shape. + if (rbCurrentValid) + { + mpFS->startElementNS(XML_a, XML_lnTo); + WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d); + mpFS->endElementNS(XML_a, XML_lnTo); + } + else + { + mpFS->startElementNS(XML_a, XML_moveTo); + WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d); + mpFS->endElementNS(XML_a, XML_moveTo); + } rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex].First, false, false); rCustomShape2d.GetParameter(rfCurrentY, rPairs[rnPairIndex].Second, false, false); rbCurrentValid = true; @@ -4063,7 +4074,8 @@ bool DrawingML::WriteCustomGeometrySegment( getEllipsePointFromViewAngle(fSx, fSy, fWR, fHR, fCx, fCy, fStartAngle); // write markup for going to start point - if (eCommand == ANGLEELLIPSETO) + // lnTo requires a valid current point + if (eCommand == ANGLEELLIPSETO && rbCurrentValid) { mpFS->startElementNS(XML_a, XML_lnTo); mpFS->singleElementNS(XML_a, XML_pt, XML_x, OString::number(std::lround(fSx)), @@ -4126,7 +4138,8 @@ bool DrawingML::WriteCustomGeometrySegment( getEllipsePointAndAngleFromRayPoint(fStartAngle, fPx, fPy, fWR, fHR, fCx, fCy, fX3, fY3); // markup for going to start point - if (eCommand == ARCTO || eCommand == CLOCKWISEARCTO) + // lnTo requires a valid current point. + if ((eCommand == ARCTO || eCommand == CLOCKWISEARCTO) && rbCurrentValid) { mpFS->startElementNS(XML_a, XML_lnTo); mpFS->singleElementNS(XML_a, XML_pt, XML_x, OString::number(std::lround(fPx)), |