oox/source/export/shapes.cxx       |   38 ++++++++++++++++++++++++++---
 sd/qa/unit/data/odp/formula.fodp   |   41 ++++++++++++++++++++++++++++++++
 sd/qa/unit/export-tests-ooxml4.cxx |   47 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 121 insertions(+), 5 deletions(-)

New commits:
commit a77747d763d9e21469d1a55e1d9f1e5d62acf017
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Nov 30 01:17:14 2024 +0500
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Thu Dec 12 16:41:02 2024 +0100

    tdf#163483: implement export of Math formula's fallback image to PPTX
    
    This was left as a TODO in commit cb890ae43bacd2be24bc74fad2e2e5cce8910995
    (oox: export Math objects to PPTX files, 2016-01-15). Now after commit
    7cfff4751befd678b3db4b6f16b020d38f4e9c32 (Related: tdf#129061 Avoid formula
    import and use fallback for now, 2024-09-11), that relied on the fallback
    being present, our exported documents lost the formulas completely on load.
    So the fallback export became a necessity.
    
    Change-Id: I52d4ef0400ce72ee10fda10a1131b4ba29ea56be
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177564
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177653
    (cherry picked from commit e425b6e0d270b1a315dfecc1ec6571bd5c7a6b52)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177665
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index 35541bb3c721..e57dc6699f00 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -77,6 +77,7 @@
 #include <vcl/graph.hxx>
 #include <vcl/outdev.hxx>
 #include <filter/msfilter/escherex.hxx>
+#include <svtools/embedhlp.hxx>
 #include <svx/svdoashp.hxx>
 #include <svx/svdoole2.hxx>
 #include <comphelper/diagnose_ex.hxx>
@@ -2573,6 +2574,8 @@ void ShapeExport::WriteMathShape(Reference<XShape> const& 
xShape)
     assert(xMathModel.is());
     assert(GetDocumentType() != DOCUMENT_DOCX); // should be written in 
DocxAttributeOutput
     SAL_WARN_IF(GetDocumentType() == DOCUMENT_XLSX, "oox.shape", "Math export 
to XLSX isn't tested, should it happen here?");
+    const OString cNvPr_id = OString::number(GetNewShapeID(xShape));
+    const OUString shapeName = GetShapeName(xShape);
 
     // ECMA standard does not actually allow oMath outside of
     // WordProcessingML so write a MCE like PPT 2010 does
@@ -2582,9 +2585,7 @@ void ShapeExport::WriteMathShape(Reference<XShape> const& 
xShape)
         XML_Requires, "a14");
     mpFS->startElementNS(mnXmlNamespace, XML_sp);
     mpFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
-    mpFS->startElementNS(mnXmlNamespace, XML_cNvPr,
-         XML_id, OString::number(GetNewShapeID(xShape)),
-         XML_name, GetShapeName(xShape));
+    mpFS->startElementNS(mnXmlNamespace, XML_cNvPr, XML_id, cNvPr_id, 
XML_name, shapeName);
     AddExtLst(mpFS, xPropSet);
     mpFS->endElementNS(mnXmlNamespace, XML_cNvPr);
     mpFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
@@ -2612,7 +2613,36 @@ void ShapeExport::WriteMathShape(Reference<XShape> 
const& xShape)
     mpFS->endElementNS(mnXmlNamespace, XML_sp);
     mpFS->endElementNS(XML_mc, XML_Choice);
     mpFS->startElementNS(XML_mc, XML_Fallback);
-    // TODO: export bitmap shape as fallback
+
+    svt::EmbeddedObjectRef ref(
+        
xPropSet->getPropertyValue(u"EmbeddedObject"_ustr).query<css::embed::XEmbeddedObject>(),
+        embed::Aspects::MSOLE_CONTENT);
+    if (auto* graphic = ref.GetGraphic(); graphic && graphic->GetType() != 
GraphicType::NONE)
+    {
+        if (OUString r_id = writeGraphicToStorage(*graphic); !r_id.isEmpty())
+        {
+            mpFS->startElementNS(mnXmlNamespace, XML_sp);
+            mpFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
+            mpFS->startElementNS(mnXmlNamespace, XML_cNvPr, XML_id, cNvPr_id, 
XML_name, shapeName);
+            AddExtLst(mpFS, xPropSet);
+            mpFS->endElementNS(mnXmlNamespace, XML_cNvPr);
+            mpFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
+            mpFS->singleElementNS(mnXmlNamespace, XML_nvPr);
+            mpFS->endElementNS(mnXmlNamespace, XML_nvSpPr);
+            mpFS->startElementNS(mnXmlNamespace, XML_spPr);
+            WriteShapeTransformation(xShape, XML_a);
+            WritePresetShape("rect"_ostr);
+            mpFS->startElementNS(XML_a, XML_blipFill);
+            mpFS->singleElementNS(XML_a, XML_blip, FSNS(XML_r, XML_embed), 
r_id);
+            mpFS->startElementNS(XML_a, XML_stretch);
+            mpFS->singleElementNS(XML_a, XML_fillRect);
+            mpFS->endElementNS(XML_a, XML_stretch);
+            mpFS->endElementNS(XML_a, XML_blipFill);
+            mpFS->endElementNS(mnXmlNamespace, XML_spPr);
+            mpFS->endElementNS(mnXmlNamespace, XML_sp);
+        }
+    }
+
     mpFS->endElementNS(XML_mc, XML_Fallback);
     mpFS->endElementNS(XML_mc, XML_AlternateContent);
 }
diff --git a/sd/qa/unit/data/odp/formula.fodp b/sd/qa/unit/data/odp/formula.fodp
new file mode 100644
index 000000000000..67ae72f4f3a9
--- /dev/null
+++ b/sd/qa/unit/data/odp/formula.fodp
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; office:version="1.4" 
office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:styles>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="gr1" style:family="graphic">
+   <style:graphic-properties draw:stroke="none" draw:fill="none" 
draw:textarea-horizontal-align="center" draw:textarea-vertical-align="middle" 
draw:ole-draw-aspect="1" style:protect="size"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:presentation>
+   <draw:page>
+    <draw:frame draw:style-name="gr1" svg:width="15.53mm" svg:height="5.28mm" 
svg:x="123.06mm" svg:y="70.06mm">
+     <draw:object>
+      <math xmlns="http://www.w3.org/1998/Math/MathML"; display="block">
+       <semantics>
+        <mrow>
+         <mrow>
+          <msup>
+           <mi mathvariant="normal">e</mi>
+           <mrow>
+            <mi>i</mi>
+            <mi>π</mi>
+           </mrow>
+          </msup>
+          <mo stretchy="false">+</mo>
+          <mn>1</mn>
+         </mrow>
+         <mo stretchy="false">=</mo>
+         <mn>0</mn>
+        </mrow>
+        <annotation encoding="StarMath 5.0">{func e}^{i %pi} + 1 = 
0</annotation>
+       </semantics>
+      </math>
+     </draw:object>
+    </draw:frame>
+   </draw:page>
+  </office:presentation>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sd/qa/unit/export-tests-ooxml4.cxx 
b/sd/qa/unit/export-tests-ooxml4.cxx
index 5524e7e41ab3..aa8aea577a81 100644
--- a/sd/qa/unit/export-tests-ooxml4.cxx
+++ b/sd/qa/unit/export-tests-ooxml4.cxx
@@ -24,6 +24,7 @@
 #include <com/sun/star/awt/FontUnderline.hpp>
 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
 #include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
 #include <com/sun/star/lang/Locale.hpp>
 #include <com/sun/star/text/GraphicCrop.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
@@ -599,7 +600,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf119223)
 
     assertXPath(pXmlDocRels, "//p:cNvPr[@name='SomePicture']"_ostr);
 
-    assertXPath(pXmlDocRels, "//p:cNvPr[@name='SomeFormula']"_ostr);
+    assertXPath(pXmlDocRels, 
"//mc:Choice/p:sp/p:nvSpPr/p:cNvPr[@name='SomeFormula']"_ostr);
 
     assertXPath(pXmlDocRels, "//p:cNvPr[@name='SomeLine']"_ostr);
 
@@ -1204,6 +1205,50 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, 
testTdf159931_slideLayouts)
                          bool(xNameAccess->hasByName("ppt/slideLayouts/" + 
sSlideLayoutName2)));
 }
 
+CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf163483_export_math_fallback)
+{
+    createSdImpressDoc("odp/formula.fodp");
+
+    // Before export-and-reload, there is a formula on page.
+    {
+        auto xProps = getShapeFromPage(0, 0);
+        auto xInfo = 
xProps->getPropertyValue(u"Model"_ustr).queryThrow<css::lang::XServiceInfo>();
+        
CPPUNIT_ASSERT(xInfo->supportsService(u"com.sun.star.formula.FormulaProperties"_ustr));
+        CPPUNIT_ASSERT_THROW(getShapeFromPage(0, 1),
+                             css::lang::IndexOutOfBoundsException); // Only 
one shape on page
+    }
+
+    saveAndReload(u"Impress Office Open XML"_ustr);
+
+    // After save-and-reload, there must still be a single shape; now it's a 
fallback image.
+    // When we start to import formulas from PPTX, that will be formula.
+    {
+        // Without the fix, this threw IndexOutOfBoundsException, because 
there was no fallback,
+        // and no shape got imported.
+        auto xInfo = getShapeFromPage(0, 
0).queryThrow<css::lang::XServiceInfo>();
+        
CPPUNIT_ASSERT(xInfo->supportsService(u"com.sun.star.drawing.CustomShape"_ustr));
+        CPPUNIT_ASSERT_THROW(getShapeFromPage(0, 1),
+                             css::lang::IndexOutOfBoundsException); // Only 
one shape on page
+    }
+
+    xmlDocUniquePtr pXmlDoc = parseExport(u"ppt/slides/slide1.xml"_ustr);
+
+    const OUString cNvPr_id = getXPath(
+        pXmlDoc, 
"/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Choice/p:sp/p:nvSpPr/p:cNvPr"_ostr,
+        "id"_ostr);
+
+    // Check that the alternate content is exported
+    assertXPath(
+        pXmlDoc,
+        
"/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Fallback/p:sp/p:spPr/a:blipFill/a:blip"_ostr,
+        "embed"_ostr, u"rId1"_ustr);
+
+    // Its cNvPr_id must be the same
+    assertXPath(pXmlDoc,
+                
"/p:sld/p:cSld/p:spTree/mc:AlternateContent/mc:Fallback/p:sp/p:nvSpPr/p:cNvPr"_ostr,
+                "id"_ostr, cNvPr_id);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to