From 9a899023db876630b74493da588b4a5490f90894 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 7 Mar 2017 09:34:38 +0100 Subject: tdf#104287 RTF import: handle bitmap shapes inside tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression from commit 015fd55c94b7b650ed8e572cafaf3b0f903b01b9 (tdf#96275 RTF import: fix anchor of shapes inside tables, 2016-05-10), the problem was that since shapes inside tables are now buffered, some previously hidden problems in the buffering became visible. For one, there was no code to make sure that a bitmap shape is not appended at the end of the buffer again when it gets re-played. For another, only the bitmap shape itself was buffered, not its size. (cherry picked from commit 8240be9170cc473506531dad2fda82469ae84443) Conflicts: sw/qa/extras/rtfimport/rtfimport.cxx writerfilter/source/rtftok/rtfvalue.cxx writerfilter/source/rtftok/rtfvalue.hxx Change-Id: I04d65eb794ff6b160ef77af85479ba25ea5f8aa7 Reviewed-on: https://gerrit.libreoffice.org/34953 Tested-by: Jenkins Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara --- sw/qa/extras/rtfimport/data/tdf104287.rtf | 38 +++++++++++++++++++ sw/qa/extras/rtfimport/rtfimport.cxx | 8 ++++ writerfilter/source/rtftok/rtfdocumentimpl.cxx | 13 +++++++ writerfilter/source/rtftok/rtfdocumentimpl.hxx | 4 +- writerfilter/source/rtftok/rtfvalue.cxx | 52 +++++++++++++++++++------- writerfilter/source/rtftok/rtfvalue.hxx | 6 ++- 6 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 sw/qa/extras/rtfimport/data/tdf104287.rtf diff --git a/sw/qa/extras/rtfimport/data/tdf104287.rtf b/sw/qa/extras/rtfimport/data/tdf104287.rtf new file mode 100644 index 000000000000..2ec87e60c0a4 --- /dev/null +++ b/sw/qa/extras/rtfimport/data/tdf104287.rtf @@ -0,0 +1,38 @@ +{\rtf1\ansi\deff3\adeflang1025 +\deftab709 +\viewscale100 +\formshade\paperh16838\paperw11906\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sectunlocked1\pgndec\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc +{\*\ftnsep\chftnsep} +\trowd\trql\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrhair\brdrw1\brdrcf1\clpadfl3\clpadl55\clbrdrl\brdrhair\brdrw1\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrhair\brdrw1\brdrcf1\clpadfb3\clpadb55\clbrdrr\brdrhair\brdrw1\brdrcf1\clpadfr3\clpadr55\cellx9638\shpwr2\shpwrk3\shpbypara\shpbyignore\shptop0\shpbxcolumn\shpbxignore\shpleft0\pgndec\pard\plain \s20\noline\intbl\rtlch \ltrch\loch +{\*\flymaincnt5\flyanchor0\flycntnt} +{\shp +{\*\shpinst\shpwr2\shpwrk3\shpbypara\shpbyignore\shptop0\shpbottom6332\shpbxcolumn\shpbxignore\shpleft0\shpright9528 +{\sp +{\sn shapeType} +{\sv 75} +} +{\sp +{\sn wzDescription} +{\sv } +} +{\sp +{\sn wzName} +{\sv } +} +{\sp +{\sn pib} +{\sv +{\pict\picscalex63\picscaley63\piccropl0\piccropr0\piccropt0\piccropb0\picw1002\pich666\picwgoal15030\pichgoal9990\pngblip +{\*\blipuid ebd28c5d3cbcfd4779e8e481da18cc69} +89504e470d0a1a0a0000000d4948445200000010000000100802000000909168360000015049444154789c9592c14a02511486bf99714ccb322d7521140541cb +6a11448b164150fb8a363d41f4083d40cba0655044d0a637a837682fd1a6a2488b10b23475bcb77b671c491dc1cee23077e67cf7fcff39139252f29f08b59e3e +1dae8b4c45998ff501a82e070f5cbd3366733acb5c6fa609fc0872651236df0deeca7d002a6cc33d1b941a146ab49ca937e37610e0c590c5c92b67f926a07243 +b293613f8b1108a8a84aadb01575c9799edd0c895010a0ae71048e77b99b6a92e53861a387a48a6033c5d208c297a43ca8a3697601d217b010632dd9a9f34be0 +9968021698bea4c76ab72f5dd0d6216c3211e1bec2a0c5e59bce9303baa770c7bd38aca7d729692bcd4d512b53bb3b7cc2f45dd604ab098e67b499366025ce5e +96a317fd2162e2d76bbbb725bdcd80b12a603aca4581e7aade97e14ec2916ca719ed96e4c54692f5241f755de7019641eacfaff10b469261dc6a800dd30000000049454e44ae426082} +} +} +} +} +\cell\row\pard\pard\plain \s0\widctlpar\hyphpar0\cf0\kerning1\dbch\af8\langfe2052\dbch\af6\afs24\alang1081\loch\f3\hich\af3\fs24\lang1043\rtlch \ltrch\loch +\par } diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx index 54e4758d0a7b..1b9a2cc368a1 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -2738,6 +2738,14 @@ DECLARE_RTFIMPORT_TEST(testTdf104744, "tdf104744.rtf") CPPUNIT_ASSERT_EQUAL(static_cast(1270), getProperty(getParagraph(1), "ParaLeftMargin")); } +DECLARE_RTFIMPORT_TEST(testTdf104287, "tdf104287.rtf") +{ + uno::Reference xShape(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShape.is()); + // This failed, the bitmap had no valid anchor. + CPPUNIT_ASSERT(xShape->getAnchor().is()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 19bc1599e668..07ecb5fd5c2c 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -1530,7 +1530,14 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, else if (std::get<0>(aTuple) == BUFFER_STARTSHAPE) m_pSdrImport->resolve(std::get<1>(aTuple)->getShape(), false, RTFSdrImport::SHAPE); else if (std::get<0>(aTuple) == BUFFER_RESOLVESHAPE) + { + // Make sure there is no current buffer while replaying the shape, + // otherwise it gets re-buffered. + RTFBuffer_t* pCurrentBuffer = m_aStates.top().pCurrentBuffer; + m_aStates.top().pCurrentBuffer = nullptr; m_pSdrImport->resolve(std::get<1>(aTuple)->getShape(), true, RTFSdrImport::SHAPE); + m_aStates.top().pCurrentBuffer = pCurrentBuffer; + } else if (std::get<0>(aTuple) == BUFFER_ENDSHAPE) m_pSdrImport->close(); else if (std::get<0>(aTuple) == BUFFER_RESOLVESUBSTREAM) @@ -1541,6 +1548,8 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, OUString aCustomMark = rAttributes.find(2)->getString(); resolveSubstream(nPos, nId, aCustomMark); } + else if (std::get<0>(aTuple) == BUFFER_PICTURE) + m_aStates.top().aPicture = std::get<1>(aTuple)->getPicture(); else assert(false); } @@ -2085,6 +2094,10 @@ RTFError RTFDocumentImpl::popState() else { // Shape inside table: buffer the import to have correct anchor position. + // Also buffer the RTFPicture of the state stack as it contains + // the shape size. + auto pPictureValue = std::make_shared(m_aStates.top().aPicture); + m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_PICTURE, pPictureValue, nullptr)); auto pValue = std::make_shared(m_aStates.top().aShape); m_aStates.top().pCurrentBuffer->push_back(Buf_t(BUFFER_RESOLVESHAPE, pValue, nullptr)); } diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index 09905dcd50f6..bb79a6ed53df 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -59,7 +59,9 @@ enum RTFBufferTypes /// Imports a shape. BUFFER_RESOLVESHAPE, BUFFER_ENDSHAPE, - BUFFER_RESOLVESUBSTREAM + BUFFER_RESOLVESUBSTREAM, + /// Restores RTFParserState::aPicture. + BUFFER_PICTURE }; /// Form field types diff --git a/writerfilter/source/rtftok/rtfvalue.cxx b/writerfilter/source/rtftok/rtfvalue.cxx index dbfe14cfceaa..4814e883a3b4 100644 --- a/writerfilter/source/rtftok/rtfvalue.cxx +++ b/writerfilter/source/rtftok/rtfvalue.cxx @@ -24,7 +24,8 @@ RTFValue::RTFValue(int nValue, const OUString& sValue, uno::Reference const& xStream, uno::Reference const& xObject, bool bForceString, - const RTFShape& aShape) + const RTFShape& aShape, + const RTFPicture& rPicture) : m_nValue(nValue), m_sValue(sValue), m_pAttributes(std::make_shared(rAttributes)), @@ -33,7 +34,8 @@ RTFValue::RTFValue(int nValue, const OUString& sValue, m_xStream(xStream), m_xObject(xObject), m_bForceString(bForceString), - m_pShape(std::make_shared(aShape)) + m_pShape(std::make_shared(aShape)), + m_pPicture(std::make_shared(rPicture)) { } @@ -46,7 +48,8 @@ RTFValue::RTFValue() m_xStream(), m_xObject(), m_bForceString(false), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -58,7 +61,8 @@ RTFValue::RTFValue(int nValue) m_xShape(), m_xStream(), m_xObject(), - m_bForceString(false) + m_bForceString(false), + m_pPicture(std::make_shared()) { m_pShape.reset(new RTFShape()); } @@ -72,7 +76,8 @@ RTFValue::RTFValue(const OUString& sValue, bool bForce) m_xStream(), m_xObject(), m_bForceString(bForce), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -85,7 +90,8 @@ RTFValue::RTFValue(RTFSprms rAttributes) m_xStream(), m_xObject(), m_bForceString(false), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -98,7 +104,8 @@ RTFValue::RTFValue(RTFSprms rAttributes, RTFSprms rSprms) m_xStream(), m_xObject(), m_bForceString(false), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -111,7 +118,8 @@ RTFValue::RTFValue(uno::Reference const& xShape) m_xStream(), m_xObject(), m_bForceString(false), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -124,7 +132,8 @@ RTFValue::RTFValue(uno::Reference const& xStream) m_xStream(xStream), m_xObject(), m_bForceString(false), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -137,7 +146,8 @@ RTFValue::RTFValue(uno::Reference const& xObject) m_xStream(), m_xObject(xObject), m_bForceString(false), - m_pShape(std::make_shared()) + m_pShape(std::make_shared()), + m_pPicture(std::make_shared()) { } @@ -150,7 +160,18 @@ RTFValue::RTFValue(const RTFShape& aShape) m_xStream(), m_xObject(), m_bForceString(false), - m_pShape(std::make_shared(aShape)) + m_pShape(std::make_shared(aShape)), + m_pPicture(std::make_shared()) +{ +} + +RTFValue::RTFValue(const RTFPicture& rPicture) + : m_nValue(), + m_pAttributes(std::make_shared()), + m_pSprms(std::make_shared()), + m_bForceString(false), + m_pShape(std::make_shared()), + m_pPicture(std::make_shared(rPicture)) { } @@ -195,6 +216,11 @@ RTFShape& RTFValue::getShape() const return *m_pShape; } +RTFPicture& RTFValue::getPicture() const +{ + return *m_pPicture; +} + writerfilter::Reference::Pointer_t RTFValue::getProperties() { return std::make_shared(*m_pAttributes, *m_pSprms); @@ -217,12 +243,12 @@ std::string RTFValue::toString() const RTFValue* RTFValue::Clone() { - return new RTFValue(m_nValue, m_sValue, *m_pAttributes, *m_pSprms, m_xShape, m_xStream, m_xObject, m_bForceString, *m_pShape); + return new RTFValue(m_nValue, m_sValue, *m_pAttributes, *m_pSprms, m_xShape, m_xStream, m_xObject, m_bForceString, *m_pShape, *m_pPicture); } RTFValue* RTFValue::CloneWithSprms(RTFSprms const& rAttributes, RTFSprms const& rSprms) { - return new RTFValue(m_nValue, m_sValue, rAttributes, rSprms, m_xShape, m_xStream, m_xObject, m_bForceString, *m_pShape); + return new RTFValue(m_nValue, m_sValue, rAttributes, rSprms, m_xShape, m_xStream, m_xObject, m_bForceString, *m_pShape, *m_pPicture); } bool RTFValue::equals(RTFValue& rOther) diff --git a/writerfilter/source/rtftok/rtfvalue.hxx b/writerfilter/source/rtftok/rtfvalue.hxx index eeb973094021..689258175507 100644 --- a/writerfilter/source/rtftok/rtfvalue.hxx +++ b/writerfilter/source/rtftok/rtfvalue.hxx @@ -20,6 +20,7 @@ namespace rtftok { class RTFSprms; class RTFShape; +class RTFPicture; /// Value of an RTF keyword class RTFValue : public Value @@ -30,7 +31,7 @@ public: css::uno::Reference const& xShape, css::uno::Reference const& xStream, css::uno::Reference const& xObject, - bool bForceString, const RTFShape& aShape); + bool bForceString, const RTFShape& aShape, const RTFPicture& rPicture); RTFValue(); RTFValue(int nValue); RTFValue(const OUString& sValue, bool bForce = false); @@ -40,6 +41,7 @@ public: RTFValue(css::uno::Reference const& xStream); RTFValue(css::uno::Reference const& xObject); RTFValue(const RTFShape& aShape); + RTFValue(const RTFPicture& rPicture); virtual ~RTFValue() override; void setString(const OUString& sValue); virtual int getInt() const override; @@ -55,6 +57,7 @@ public: RTFSprms& getAttributes(); RTFSprms& getSprms(); RTFShape& getShape() const; + RTFPicture& getPicture() const; bool equals(RTFValue& rOther); private: RTFValue& operator=(RTFValue const& rOther) = delete; @@ -67,6 +70,7 @@ private: css::uno::Reference m_xObject; bool m_bForceString; std::shared_ptr m_pShape; + std::shared_ptr m_pPicture; }; } // namespace rtftok } // namespace writerfilter -- cgit v1.2.3