summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2024-11-30 01:17:14 +0500
committerMichael Weghorn <m.weghorn@posteo.de>2024-12-12 16:41:02 +0100
commita77747d763d9e21469d1a55e1d9f1e5d62acf017 (patch)
treea4f72ddfe6ac1714cc17a639f0a69ac31d81fdba
parent344fafb3bce380418ffa5b2910c8662bbc0a9f28 (diff)
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.kaganski@collabora.com> Tested-by: Jenkins Signed-off-by: Xisco Fauli <xiscofauli@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.stahl@allotropia.de> Reviewed-by: Michael Weghorn <m.weghorn@posteo.de> Tested-by: Michael Weghorn <m.weghorn@posteo.de>
-rw-r--r--oox/source/export/shapes.cxx38
-rw-r--r--sd/qa/unit/data/odp/formula.fodp41
-rw-r--r--sd/qa/unit/export-tests-ooxml4.cxx47
3 files changed, 121 insertions, 5 deletions
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: */