diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2024-11-30 01:17:14 +0500 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2024-12-12 16:41:02 +0100 |
commit | a77747d763d9e21469d1a55e1d9f1e5d62acf017 (patch) | |
tree | a4f72ddfe6ac1714cc17a639f0a69ac31d81fdba | |
parent | 344fafb3bce380418ffa5b2910c8662bbc0a9f28 (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.cxx | 38 | ||||
-rw-r--r-- | sd/qa/unit/data/odp/formula.fodp | 41 | ||||
-rw-r--r-- | sd/qa/unit/export-tests-ooxml4.cxx | 47 |
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: */ |