diff options
author | Attila Bakos (NISZ) <bakos.attilakaroly@nisz.hu> | 2022-01-19 17:43:54 +0100 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2022-02-03 09:12:20 +0100 |
commit | 4a38ca4035ac03571925e72cb47e0beb8da2003a (patch) | |
tree | 6c472f1efe01827320bfd3ae35404f38ee18ba9a | |
parent | b8925251e48534706c6960a54c320d3879317321 (diff) |
tdf#146802 OOXML import: fix embedded VML in grouped textbox
E.g. OLE formulas inside them broke document load.
Regression from 121cbc250b36290f0f8c7265fea57256dad69553
"tdf#66039 DOCX: import textboxes (with tables, images etc.)
in group shapes".
Note: now embedded VML OLE is loaded in WPG shapes, thanks to
that the ShapeHandler in oox/ has a stack having the start
token inside for each shape.
Change-Id: I973d78ed88c5c83efffd9629061e2a2c6fdd25e4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128627
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r-- | include/oox/shape/ShapeContextHandler.hxx | 18 | ||||
-rw-r--r-- | oox/source/shape/ShapeContextHandler.cxx | 31 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf146802.docx | bin | 0 -> 72360 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 13 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFastContextHandler.cxx | 5 |
5 files changed, 48 insertions, 19 deletions
diff --git a/include/oox/shape/ShapeContextHandler.hxx b/include/oox/shape/ShapeContextHandler.hxx index 27b70d2cf2c4..a245224730ed 100644 --- a/include/oox/shape/ShapeContextHandler.hxx +++ b/include/oox/shape/ShapeContextHandler.hxx @@ -19,6 +19,7 @@ #pragma once #include <memory> +#include <stack> #include <cppuhelper/implbase.hxx> #include <oox/drawingml/graphicshapecontext.hxx> #include <oox/core/fragmenthandler2.hxx> @@ -90,12 +91,15 @@ public: void setRelationFragmentPath(const OUString & the_value); sal_Int32 getStartToken() const; - void setStartToken( sal_Int32 _starttoken ); + void popStartToken(); + void pushStartToken( sal_Int32 _starttoken ); void setPosition(const css::awt::Point& rPosition); - const bool& getFullWPGSupport() { return m_bFullWPGSUpport; }; - void setFullWPGSupport(const bool& rbUse) { m_bFullWPGSUpport = rbUse; }; + const bool& getFullWPGSupport() { return m_bFullWPGSUpport; } + void setFullWPGSupport(const bool& rbUse) { m_bFullWPGSUpport = rbUse; } + + bool isWordProcessingGroupShape() const { return mxWpgContext ? true : false; } void setDocumentProperties(const css::uno::Reference<css::document::XDocumentProperties>& xDocProps); void setMediaDescriptor(const css::uno::Sequence<css::beans::PropertyValue>& rMediaDescriptor); @@ -109,9 +113,13 @@ private: ShapeContextHandler(ShapeContextHandler const &) = delete; void operator =(ShapeContextHandler const &) = delete; - ::sal_uInt32 mnStartToken; + // Special stack which always has at least one element. + // In case of group shapes with embedded content it will have more element than one. + std::stack<sal_uInt32> mnStartTokenStack; + css::awt::Point maPosition; - bool m_bFullWPGSUpport; + bool m_bFullWPGSUpport; // Is this DrawingML shape supposed to be proccessed as WPG? + drawingml::ShapePtr mpShape; std::shared_ptr< vml::Drawing > mpDrawing; diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx index 6eb9e5ce9083..cacd46d82d14 100644 --- a/oox/source/shape/ShapeContextHandler.cxx +++ b/oox/source/shape/ShapeContextHandler.cxx @@ -44,7 +44,6 @@ using namespace core; using namespace drawingml; ShapeContextHandler::ShapeContextHandler(const rtl::Reference<ShapeFilterBase>& xFilterBase) : - mnStartToken(0), m_bFullWPGSUpport(false), mxShapeFilterBase(xFilterBase) @@ -225,8 +224,9 @@ uno::Reference<xml::sax::XFastContextHandler> ShapeContextHandler::getContextHandler(sal_Int32 nElement) { uno::Reference<xml::sax::XFastContextHandler> xResult; + const sal_uInt32 nStartToken = getStartToken(); - switch (getNamespace( mnStartToken )) + switch (getNamespace( nStartToken )) { case NMSP_doc: case NMSP_vml: @@ -236,19 +236,19 @@ ShapeContextHandler::getContextHandler(sal_Int32 nElement) xResult.set(getDiagramShapeContext()); break; case NMSP_dmlLockedCanvas: - xResult.set(getLockedCanvasContext(mnStartToken)); + xResult.set(getLockedCanvasContext(nStartToken)); break; case NMSP_dmlChart: - xResult.set(getChartShapeContext(mnStartToken)); + xResult.set(getChartShapeContext(nStartToken)); break; case NMSP_wps: - xResult.set(getWpsContext(mnStartToken, nElement)); + xResult.set(getWpsContext(nStartToken, nElement)); break; case NMSP_wpg: - xResult.set(getWpgContext(mnStartToken)); + xResult.set(getWpgContext(nStartToken)); break; default: - xResult.set(getGraphicShapeContext(mnStartToken)); + xResult.set(getGraphicShapeContext(nStartToken)); break; } @@ -456,7 +456,7 @@ ShapeContextHandler::getShape() //NMSP_dmlChart == getNamespace( mnStartToken ) check is introduced to make sure that //mnStartToken is set as NMSP_dmlChart in setStartToken. //Only in case it is set then only the below block of code for ChartShapeContext should be executed. - else if (mxChartShapeContext.is() && (NMSP_dmlChart == getNamespace( mnStartToken ))) + else if (mxChartShapeContext.is() && (NMSP_dmlChart == getNamespace( getStartToken() ))) { ChartGraphicDataContext* pChartGraphicDataContext = dynamic_cast<ChartGraphicDataContext*>(mxChartShapeContext.get()); if (pChartGraphicDataContext) @@ -514,6 +514,8 @@ ShapeContextHandler::getShape() } } + if (xResult) + popStartToken(); return xResult; } @@ -537,12 +539,19 @@ void ShapeContextHandler::setRelationFragmentPath(const OUString & the_value) sal_Int32 ShapeContextHandler::getStartToken() const { - return mnStartToken; + assert(mnStartTokenStack.size() && "This stack must not be empty!"); + return mnStartTokenStack.top(); } -void ShapeContextHandler::setStartToken( sal_Int32 _starttoken ) +void ShapeContextHandler::popStartToken() { - mnStartToken = _starttoken; + if (mnStartTokenStack.size() > 1) + mnStartTokenStack.pop(); +} + +void ShapeContextHandler::pushStartToken( sal_Int32 _starttoken ) +{ + mnStartTokenStack.push(_starttoken); } void ShapeContextHandler::setPosition(const awt::Point& rPosition) diff --git a/sw/qa/extras/ooxmlexport/data/tdf146802.docx b/sw/qa/extras/ooxmlexport/data/tdf146802.docx Binary files differnew file mode 100644 index 000000000000..80d2ee17a0bc --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf146802.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 6feb92b15149..ee7b37dfc151 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -51,6 +51,19 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf135906) // just test round-tripping. The document was exported as corrupt and didn't re-load. } +CPPUNIT_TEST_FIXTURE(Test, TestTdf146802) +{ + load(DATA_DIRECTORY, "tdf146802.docx"); + + // First check if the load failed, as before the fix. + CPPUNIT_ASSERT(mxComponent); + + // There is a group shape with text box inside having an embedded VML formula, + // check if something missing. + CPPUNIT_ASSERT_EQUAL_MESSAGE("Where is the formula?", 2, getShapes()); + // Before the fix the bugdoc failed to load or the formula was missing. +} + CPPUNIT_TEST_FIXTURE(Test, testParaStyleNumLevel) { loadAndSave("para-style-num-level.docx"); diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx index e245e37b4772..aa9de6408202 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx @@ -1721,7 +1721,7 @@ void OOXMLFastContextHandlerShape::setToken(Token_t nToken) OOXMLFastContextHandler::setToken(nToken); if (mrShapeContext.is()) - mrShapeContext->setStartToken(nToken); + mrShapeContext->pushStartToken(nToken); } void OOXMLFastContextHandlerShape::sendShape( Token_t Element ) @@ -1761,8 +1761,7 @@ void OOXMLFastContextHandlerShape::sendShape( Token_t Element ) bool OOXMLFastContextHandlerShape::isDMLGroupShape() const { - return (mrShapeContext->getFullWPGSupport() && - (mrShapeContext->getStartToken() == Token_t(oox::NMSP_wpg | oox::XML_wgp))); + return (mrShapeContext->getFullWPGSupport() && mrShapeContext->isWordProcessingGroupShape()); }; void OOXMLFastContextHandlerShape::lcl_endFastElement |