summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTibor Nagy <tibor.nagy.extern@allotropia.de>2025-03-20 11:47:57 +0100
committerNagy Tibor <tibor.nagy.extern@allotropia.de>2025-03-20 16:49:11 +0100
commit612891865a74777950ab7355a4d794fa5577c5fc (patch)
treeadd363540622470209f060dce06ebf14754880aa
parent5e42599f91fc98d7f31c03e45378b95c756964d4 (diff)
tdf#165670 PPTX export: fix glue points export regression
In some cases, we exported non-integer values for the glue points, and their positions were also incorrect. this regression is caused by commit Id4a127e7ef462611bf63da791717f8260ec51be0 (tdf165262 PPTX export: fix shape export regression). Change-Id: I978fa180ef181391651abad5c2b748e0b606b320 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183165 Reviewed-by: Nagy Tibor <tibor.nagy.extern@allotropia.de> Tested-by: Jenkins
-rw-r--r--oox/source/export/drawingml.cxx191
-rw-r--r--sd/qa/unit/data/pptx/tdf165670.pptxbin0 -> 33317 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml3.cxx25
3 files changed, 130 insertions, 86 deletions
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 6f9905a4c612..65dc3f86b1b8 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -4691,52 +4691,53 @@ void prepareTextArea(const EnhancedCustomShape2d& rEnhancedCustomShape2d,
return;
}
-void prepareGluePoints(const EnhancedCustomShape2d& rEnhancedCustomShape2d,
- std::vector<Guide>& rGuideList,
- const uno::Sequence<drawing::EnhancedCustomShapeParameterPair>& rGluePoints,
- const uno::Sequence<drawing::EnhancedCustomShapeTextFrame>& aTextFrames)
+OUString GetFormula(const OUString& sEquation, const OUString& sReplace, const OUString& sNewStr)
{
- if (rGluePoints.hasElements())
+ OUString sFormula = sEquation;
+ size_t nPos = sFormula.indexOf(sReplace);
+ if (nPos != std::string::npos)
{
- OString sWidth, sHeight;
- if (aTextFrames.hasElements())
- {
- double fTop = 0.0, fLeft = 0.0, fBottom = 0.0, fRight = 0.0;
-
- rEnhancedCustomShape2d.GetParameter(fTop, aTextFrames[0].TopLeft.First, true, false);
- rEnhancedCustomShape2d.GetParameter(fLeft, aTextFrames[0].TopLeft.Second, true, false);
- rEnhancedCustomShape2d.GetParameter(fBottom, aTextFrames[0].BottomRight.First, false,
- true);
- rEnhancedCustomShape2d.GetParameter(fRight, aTextFrames[0].BottomRight.Second, false,
- true);
+ OUString sModifiedEquation = sFormula.replaceAt(nPos, sReplace.getLength(), sNewStr);
+ sFormula = "*/ " + sModifiedEquation;
+ }
- sWidth = OString::number(fLeft + fRight);
- sHeight = OString::number(fTop + fBottom);
- }
- else
- {
- tools::Rectangle aLogicRectLO(rEnhancedCustomShape2d.GetLogicRect());
- sal_Int32 nWidth = aLogicRectLO.Right() - aLogicRectLO.Left();
- sal_Int32 nHeight = aLogicRectLO.Bottom() - aLogicRectLO.Top();
- sWidth = OString::number(oox::drawingml::convertHmmToEmu(nWidth));
- sHeight = OString::number(oox::drawingml::convertHmmToEmu(nHeight));
- }
+ return sFormula;
+}
+void prepareGluePoints(std::vector<Guide>& rGuideList,
+ const css::uno::Sequence<OUString>& aEquations,
+ const uno::Sequence<drawing::EnhancedCustomShapeParameterPair>& rGluePoints,
+ const bool bIsOOXML, const sal_Int32 nWidth, const sal_Int32 nHeight)
+{
+ if (rGluePoints.hasElements())
+ {
sal_Int32 nIndex = 1;
for (auto const& rGluePoint : rGluePoints)
{
- Guide aGuide;
- double fRetValueX;
- rEnhancedCustomShape2d.GetParameter(fRetValueX, rGluePoint.First, false, false);
- aGuide.sName = "GluePoint"_ostr + OString::number(nIndex) + "X";
- aGuide.sFormula = "*/ " + OString::number(fRetValueX) + " w " + sWidth;
- rGuideList.push_back(aGuide);
-
- double fRetValueY;
- rEnhancedCustomShape2d.GetParameter(fRetValueY, rGluePoint.Second, false, false);
- aGuide.sName = "GluePoint"_ostr + OString::number(nIndex) + "Y";
- aGuide.sFormula = "*/ " + OString::number(fRetValueY) + " h " + sHeight;
- rGuideList.push_back(aGuide);
+ sal_Int32 nIdx1 = -1;
+ sal_Int32 nIdx2 = -1;
+ rGluePoint.First.Value >>= nIdx1;
+ rGluePoint.Second.Value >>= nIdx2;
+
+ if (nIdx1 != -1 && nIdx2 != -1)
+ {
+ Guide aGuideX;
+ aGuideX.sName = "GluePoint"_ostr + OString::number(nIndex) + "X";
+ aGuideX.sFormula
+ = (bIsOOXML && aEquations.hasElements())
+ ? GetFormula(aEquations[nIdx1], "*logwidth/", " w ").toUtf8()
+ : "*/ " + OString::number(nIdx1) + " w " + OString::number(nWidth);
+ rGuideList.push_back(aGuideX);
+
+ Guide aGuideY;
+ aGuideY.sName = "GluePoint"_ostr + OString::number(nIndex) + "Y";
+ aGuideY.sFormula
+ = (bIsOOXML && aEquations.hasElements())
+ ? GetFormula(aEquations[nIdx2], "*logheight/", " h ").toUtf8()
+ : "*/ " + OString::number(nIdx2) + " h " + OString::number(nHeight);
+ rGuideList.push_back(aGuideY);
+ }
+
nIndex++;
}
}
@@ -4776,8 +4777,28 @@ bool DrawingML::WriteCustomGeometry(
uno::Sequence<beans::PropertyValue> aPathProp;
pPathProp->Value >>= aPathProp;
+ auto pShapeType = std::find_if(std::cbegin(*pGeometrySeq), std::cend(*pGeometrySeq),
+ [](const PropertyValue& rProp) { return rProp.Name == "Type"; });
+ bool bOOXML = false;
+ if (pShapeType != std::cend(*pGeometrySeq))
+ {
+ OUString sShapeType;
+ pShapeType->Value >>= sShapeType;
+ if (sShapeType.startsWith("ooxml"))
+ bOOXML = true;
+ }
+
+ auto pEquationsProp
+ = std::find_if(std::cbegin(*pGeometrySeq), std::cend(*pGeometrySeq),
+ [](const PropertyValue& rProp) { return rProp.Name == "Equations"; });
+
+ css::uno::Sequence<OUString> aEquationSeq;
+ if (pEquationsProp != std::cend(*pGeometrySeq))
+ {
+ pEquationsProp->Value >>= aEquationSeq;
+ }
+
uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aGluePoints;
- uno::Sequence<drawing::EnhancedCustomShapeTextFrame> aTextFrames;
uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aPairs;
uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
uno::Sequence<awt::Size> aPathSize;
@@ -4791,8 +4812,6 @@ bool DrawingML::WriteCustomGeometry(
rPathProp.Value >>= aSegments;
else if (rPathProp.Name == "GluePoints")
rPathProp.Value >>= aGluePoints;
- else if (rPathProp.Name == "TextFrames")
- rPathProp.Value >>= aTextFrames;
else if (rPathProp.Name == "SubViewSize")
rPathProp.Value >>= aPathSize;
else if (rPathProp.Name == "StretchX")
@@ -4829,50 +4848,6 @@ bool DrawingML::WriteCustomGeometry(
// entire method.
const EnhancedCustomShape2d aCustomShape2d(const_cast<SdrObjCustomShape&>(rSdrObjCustomShape));
- TextAreaRect aTextAreaRect;
- std::vector<Guide> aGuideList; // for now only for <a:rect>
- prepareTextArea(aCustomShape2d, aGuideList, aTextAreaRect);
- prepareGluePoints(aCustomShape2d, aGuideList, aGluePoints, aTextFrames);
- mpFS->startElementNS(XML_a, XML_custGeom);
- mpFS->singleElementNS(XML_a, XML_avLst);
- if (aGuideList.empty())
- {
- mpFS->singleElementNS(XML_a, XML_gdLst);
- }
- else
- {
- mpFS->startElementNS(XML_a, XML_gdLst);
- for (auto const& elem : aGuideList)
- {
- mpFS->singleElementNS(XML_a, XML_gd, XML_name, elem.sName, XML_fmla, elem.sFormula);
- }
- mpFS->endElementNS(XML_a, XML_gdLst);
- }
- mpFS->singleElementNS(XML_a, XML_ahLst);
-
- if (!aGuideList.empty())
- {
- mpFS->startElementNS(XML_a, XML_cxnLst);
- for (auto it = aGuideList.begin(); it != aGuideList.end(); ++it)
- {
- auto aNextIt = std::next(it);
- if (aNextIt != aGuideList.end() && it->sName.startsWith("GluePoint")
- && aNextIt->sName.startsWith("GluePoint"))
- {
- mpFS->startElementNS(XML_a, XML_cxn, XML_ang, "0");
- mpFS->singleElementNS(XML_a, XML_pos, XML_x, it->sName, XML_y, aNextIt->sName);
- mpFS->endElementNS(XML_a, XML_cxn);
-
- ++it;
- }
- }
- mpFS->endElementNS(XML_a, XML_cxnLst);
- }
-
- mpFS->singleElementNS(XML_a, XML_rect, XML_l, aTextAreaRect.left, XML_t, aTextAreaRect.top,
- XML_r, aTextAreaRect.right, XML_b, aTextAreaRect.bottom);
- mpFS->startElementNS(XML_a, XML_pathLst);
-
// Prepare width and height for <a:path>
bool bUseGlobalViewBox(false);
@@ -4942,6 +4917,50 @@ bool DrawingML::WriteCustomGeometry(
// shift of the resulting path coordinates.
}
+ TextAreaRect aTextAreaRect;
+ std::vector<Guide> aGuideList; // for now only for <a:rect>
+ prepareTextArea(aCustomShape2d, aGuideList, aTextAreaRect);
+ prepareGluePoints(aGuideList, aEquationSeq, aGluePoints, bOOXML, nViewBoxWidth, nViewBoxHeight);
+ mpFS->startElementNS(XML_a, XML_custGeom);
+ mpFS->singleElementNS(XML_a, XML_avLst);
+ if (aGuideList.empty())
+ {
+ mpFS->singleElementNS(XML_a, XML_gdLst);
+ }
+ else
+ {
+ mpFS->startElementNS(XML_a, XML_gdLst);
+ for (auto const& elem : aGuideList)
+ {
+ mpFS->singleElementNS(XML_a, XML_gd, XML_name, elem.sName, XML_fmla, elem.sFormula);
+ }
+ mpFS->endElementNS(XML_a, XML_gdLst);
+ }
+ mpFS->singleElementNS(XML_a, XML_ahLst);
+
+ if (!aGuideList.empty())
+ {
+ mpFS->startElementNS(XML_a, XML_cxnLst);
+ for (auto it = aGuideList.begin(); it != aGuideList.end(); ++it)
+ {
+ auto aNextIt = std::next(it);
+ if (aNextIt != aGuideList.end() && it->sName.startsWith("GluePoint")
+ && aNextIt->sName.startsWith("GluePoint"))
+ {
+ mpFS->startElementNS(XML_a, XML_cxn, XML_ang, "0");
+ mpFS->singleElementNS(XML_a, XML_pos, XML_x, it->sName, XML_y, aNextIt->sName);
+ mpFS->endElementNS(XML_a, XML_cxn);
+
+ ++it;
+ }
+ }
+ mpFS->endElementNS(XML_a, XML_cxnLst);
+ }
+
+ mpFS->singleElementNS(XML_a, XML_rect, XML_l, aTextAreaRect.left, XML_t, aTextAreaRect.top,
+ XML_r, aTextAreaRect.right, XML_b, aTextAreaRect.bottom);
+ mpFS->startElementNS(XML_a, XML_pathLst);
+
// Iterate over subpaths
sal_Int32 nPairIndex = 0; // index over "Coordinates"
sal_Int32 nPathSizeIndex = 0; // index over "SubViewSize"
diff --git a/sd/qa/unit/data/pptx/tdf165670.pptx b/sd/qa/unit/data/pptx/tdf165670.pptx
new file mode 100644
index 000000000000..66e7c54041f5
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf165670.pptx
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx
index 7d06160b4ce2..639a64555566 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -27,6 +27,31 @@ public:
int testTdf115005_FallBack_Images(bool bAddReplacementImages);
};
+CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf165670)
+{
+ createSdImpressDoc("pptx/tdf165670.pptx");
+ save(u"Impress Office Open XML"_ustr);
+
+ xmlDocUniquePtr pXmlDoc1 = parseExport(u"ppt/slides/slide1.xml"_ustr);
+
+ // glue points export
+ // without the fix in place, this test would have failed with
+ // - Expected: "*/ 690465 w 2407298"
+ // - Actual : "*/ 1917.97586131837 w 5236"
+ assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:custGeom/a:gdLst/a:gd[5]", "name",
+ u"GluePoint1X");
+ assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:custGeom/a:gdLst/a:gd[5]", "fmla",
+ u"*/ 690465 w 2407298");
+
+ // without the fix in place, this test would have failed with
+ // - Expected: "*/ 802433 h 1884784"
+ // - Actual : "*/ 2229.18869642357 h 6687"
+ assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:custGeom/a:gdLst/a:gd[6]", "name",
+ u"GluePoint1Y");
+ assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:custGeom/a:gdLst/a:gd[6]", "fmla",
+ u"*/ 802433 h 1884784");
+}
+
CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf165262)
{
createSdImpressDoc("ppt/tdf165262.ppt");