oox/source/export/drawingml.cxx    |   78 +++++++++++++++++++++++++++++++++++++
 oox/source/export/shapes.cxx       |    5 +-
 sd/qa/unit/data/ppt/tdf165262.ppt  |binary
 sd/qa/unit/export-tests-ooxml3.cxx |   23 ++++++++++
 4 files changed, 104 insertions(+), 2 deletions(-)

New commits:
commit 86d36ee56521438069504fbacff8dc2aff3a1afc
Author:     Tibor Nagy <tibor.nagy.ext...@allotropia.de>
AuthorDate: Sun Feb 23 21:35:17 2025 +0100
Commit:     Nagy Tibor <tibor.nagy.ext...@allotropia.de>
CommitDate: Mon Feb 24 14:22:14 2025 +0100

    tdf165262 PPTX export: fix shape export regression
    
    When exporting a shape from PPT to PPTX, the preset shape export is
    sometimes incorrect. In such cases, we export the shapes as custom
    shapes. The export of glue points is also important, so it has been
    added to the fix.
    
    this regression is
    caused by commit I378ffffc2ba09fcffcaa4e5dcf74bfd19e9f704d
    (tdf#149126 fix export of PPTX preset shapes).
    
    Change-Id: Id4a127e7ef462611bf63da791717f8260ec51be0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182068
    Tested-by: Jenkins
    Reviewed-by: Nagy Tibor <tibor.nagy.ext...@allotropia.de>

diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 754ae8bd7c32..77baafbe755d 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -4690,6 +4690,57 @@ 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)
+{
+    if (rGluePoints.hasElements())
+    {
+        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);
+
+            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));
+        }
+
+        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);
+            nIndex++;
+        }
+    }
+}
 }
 
 bool DrawingML::WriteCustomGeometry(
@@ -4725,6 +4776,8 @@ bool DrawingML::WriteCustomGeometry(
     uno::Sequence<beans::PropertyValue> aPathProp;
     pPathProp->Value >>= aPathProp;
 
+    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;
@@ -4736,6 +4789,10 @@ bool DrawingML::WriteCustomGeometry(
             rPathProp.Value >>= aPairs;
         else if (rPathProp.Name == "Segments")
             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")
@@ -4775,6 +4832,7 @@ bool DrawingML::WriteCustomGeometry(
     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())
@@ -4791,6 +4849,26 @@ bool DrawingML::WriteCustomGeometry(
         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);
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index 40bed3208567..e7dc5f4ef307 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -622,13 +622,14 @@ constexpr frozen::set<std::u16string_view, 57> 
constDenySet(
     u"flowchart-display"
 });
 
-constexpr frozen::set<std::u16string_view, 5> constAllowSet(
+constexpr frozen::set<std::u16string_view, 6> constAllowSet(
 {
     u"heart",
     u"puzzle",
     u"col-60da8460",
     u"col-502ad400",
-    u"sinusoid"
+    u"sinusoid",
+    u"mso-spt100"
 });
 
 } // end anonymous namespace
diff --git a/sd/qa/unit/data/ppt/tdf165262.ppt 
b/sd/qa/unit/data/ppt/tdf165262.ppt
new file mode 100644
index 000000000000..8fcb7379407b
Binary files /dev/null and b/sd/qa/unit/data/ppt/tdf165262.ppt differ
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx 
b/sd/qa/unit/export-tests-ooxml3.cxx
index 9e0b36b9096d..7d06160b4ce2 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -27,6 +27,29 @@ public:
     int testTdf115005_FallBack_Images(bool bAddReplacementImages);
 };
 
+CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf165262)
+{
+    createSdImpressDoc("ppt/tdf165262.ppt");
+    save(u"Impress Office Open XML"_ustr);
+
+    xmlDocUniquePtr pXmlDoc1 = parseExport(u"ppt/slides/slide1.xml"_ustr);
+    assertXPath(pXmlDoc1, 
"/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[1]/p:spPr/a:custGeom");
+
+    // glue points export
+    assertXPath(pXmlDoc1,
+                
"/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[1]/p:spPr/a:custGeom/a:gdLst/a:gd[5]", 
"name",
+                u"GluePoint1X");
+    assertXPath(pXmlDoc1,
+                
"/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[1]/p:spPr/a:custGeom/a:gdLst/a:gd[5]", 
"fmla",
+                u"*/ 15 w 21600");
+    assertXPath(pXmlDoc1,
+                
"/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[1]/p:spPr/a:custGeom/a:gdLst/a:gd[6]", 
"name",
+                u"GluePoint1Y");
+    assertXPath(pXmlDoc1,
+                
"/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[1]/p:spPr/a:custGeom/a:gdLst/a:gd[6]", 
"fmla",
+                u"*/ 0 h 21600");
+}
+
 CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf164775_ConnectorShape)
 {
     createSdImpressDoc("odp/tdf164775.odp");

Reply via email to