sw/qa/extras/rtfexport/data/fdo82860.odt |binary sw/qa/extras/rtfexport/rtfexport.cxx | 10 + sw/source/filter/ww8/rtfattributeoutput.cxx | 122 +++++++++++++--------- sw/source/filter/ww8/rtfattributeoutput.hxx | 3 sw/source/filter/ww8/rtfexport.cxx | 25 ++++ sw/source/filter/ww8/rtfexport.hxx | 8 + sw/source/filter/ww8/rtfsdrexport.cxx | 31 +++++ sw/source/filter/ww8/rtfsdrexport.hxx | 8 + writerfilter/source/dmapper/DomainMapper_Impl.cxx | 30 +++-- 9 files changed, 175 insertions(+), 62 deletions(-)
New commits: commit 5a5d55a8a0f82406a8001015a723596f21d3562c Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Wed Oct 15 13:00:24 2014 +0200 fdo#82860 RTF import: fix handling of SHAPE fields No need to use fieldmarks for these. Change-Id: I8d2c797f2b00be88e445dab0dd69cb1a9556c02c diff --git a/sw/qa/extras/rtfexport/data/fdo82860.odt b/sw/qa/extras/rtfexport/data/fdo82860.odt new file mode 100644 index 0000000..f680410 Binary files /dev/null and b/sw/qa/extras/rtfexport/data/fdo82860.odt differ diff --git a/sw/qa/extras/rtfexport/rtfexport.cxx b/sw/qa/extras/rtfexport/rtfexport.cxx index 5c74c53..2ffbb38 100644 --- a/sw/qa/extras/rtfexport/rtfexport.cxx +++ b/sw/qa/extras/rtfexport/rtfexport.cxx @@ -709,6 +709,16 @@ DECLARE_RTFEXPORT_TEST(testNumberingFont, "numbering-font.rtf") CPPUNIT_ASSERT_EQUAL(OUString("Verdana"), getProperty<OUString>(xStyle, "CharFontName")); } +DECLARE_RTFEXPORT_TEST(testFdo82860, "fdo82860.odt") +{ + // The problem was that: + // 1) The import tried to use fieldmarks for SHAPE fields + // 2) The exporter did not handle "shape with textbox" text. + uno::Reference<text::XTextRange> xTextRange(getShape(1), uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextRange->getText(); + CPPUNIT_ASSERT_EQUAL(OUString("hello"), getParagraphOfText(1, xText)->getString()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 8bdf7f7..adee004 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -4001,20 +4001,26 @@ void DomainMapper_Impl::CloseFieldCommand() * To handle unsupported fields used fieldmark API. */ OUString aCode( pContext->GetCommand().trim() ); - xFieldInterface = m_xTextFactory->createInstance("com.sun.star.text.Fieldmark"); - const uno::Reference<text::XTextContent> xTextContent(xFieldInterface, uno::UNO_QUERY_THROW); - uno::Reference< text::XTextAppend > xTextAppend; - xTextAppend = m_aTextAppendStack.top().xTextAppend; - uno::Reference< text::XTextCursor > xCrsr = xTextAppend->createTextCursorByRange(pContext->GetStartRange()); - if (xTextContent.is()) + // Don't waste resources on wrapping shapes inside a fieldmark. + if (aCode != "SHAPE") { - xTextAppend->insertTextContent(xCrsr,xTextContent, sal_True); + xFieldInterface = m_xTextFactory->createInstance("com.sun.star.text.Fieldmark"); + const uno::Reference<text::XTextContent> xTextContent(xFieldInterface, uno::UNO_QUERY_THROW); + uno::Reference< text::XTextAppend > xTextAppend; + xTextAppend = m_aTextAppendStack.top().xTextAppend; + uno::Reference< text::XTextCursor > xCrsr = xTextAppend->createTextCursorByRange(pContext->GetStartRange()); + if (xTextContent.is()) + { + xTextAppend->insertTextContent(xCrsr,xTextContent, sal_True); + } + const uno::Reference<uno::XInterface> xContent(xTextContent); + uno::Reference< text::XFormField> xFormField(xContent, uno::UNO_QUERY); + xFormField->setFieldType(aCode); + m_bStartGenericField = true; + pContext->SetFormField( xFormField ); } - const uno::Reference<uno::XInterface> xContent(xTextContent); - uno::Reference< text::XFormField> xFormField(xContent, uno::UNO_QUERY); - xFormField->setFieldType(aCode); - m_bStartGenericField = true; - pContext->SetFormField( xFormField ); + else + m_bParaHadField = false; } //set the text field if there is any pContext->SetTextField( uno::Reference< text::XTextField >( xFieldInterface, uno::UNO_QUERY ) ); commit ecc5cbc69e4c2df4ddbe46bbc2f973cc60a10772 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Wed Oct 15 12:35:47 2014 +0200 fdo#82860 RTF export: if shape has textbox, export its contents as shape text See 8c677716c4707ccd86b152ae504841affb393cc0 (DOCX drawingML export: if shape has textbox, export its contents as shape text, 2014-06-06). Change-Id: I5b1afae4d1b80c9b225096677f7d7ae77ff90f5b diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 0a26834..96c04c6 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -1592,6 +1592,75 @@ void lcl_TextFrameRelativeSize(std::vector< std::pair<OString, OString> >& rFlyP } } +void RtfAttributeOutput::writeTextFrame(const sw::Frame& rFrame, bool bTextBox) +{ + RtfStringBuffer aRunText; + if (bTextBox) + { + m_rExport.setStream(); + aRunText = m_aRunText; + m_aRunText.clear(); + } + + m_rExport.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHPTXT); + + { + // Save table state, in case the inner text also contains a table. + ww8::WW8TableInfo::Pointer_t pTableInfoOrig = m_rExport.mpTableInfo; + m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); + SwWriteTable* pTableWrt = m_pTableWrt; + m_pTableWrt = 0; + sal_uInt32 nTableDepth = m_nTableDepth; + + m_nTableDepth = 0; + /* + * Save m_aRun as we should not lose the opening brace. + * OTOH, just drop the contents of m_aRunText in case something + * would be there, causing a problem later. + */ + OString aSave = m_aRun.makeStringAndClear(); + // Also back m_bInRun and m_bSingleEmptyRun up. + bool bInRunOrig = m_bInRun; + m_bInRun = false; + bool bSingleEmptyRunOrig = m_bSingleEmptyRun; + m_bSingleEmptyRun = false; + m_rExport.bRTFFlySyntax = true; + + const SwFrmFmt& rFrmFmt = rFrame.GetFrmFmt(); + const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx(); + sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0; + sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0; + m_rExport.SaveData(nStt, nEnd); + m_rExport.mpParentFrame = &rFrame; + m_rExport.WriteText(); + m_rExport.RestoreData(); + + m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PARD); + m_rExport.bRTFFlySyntax = false; + m_aRun->append(aSave); + m_aRunText.clear(); + m_bInRun = bInRunOrig; + m_bSingleEmptyRun = bSingleEmptyRunOrig; + + // Restore table state. + m_rExport.mpTableInfo = pTableInfoOrig; + delete m_pTableWrt; + m_pTableWrt = pTableWrt; + m_nTableDepth = nTableDepth; + } + + m_rExport.mpParentFrame = NULL; + + m_rExport.Strm().WriteChar('}'); // shptxt + + if (bTextBox) + { + m_aRunText = aRunText; + m_aRunText->append(m_rExport.getStream()); + m_rExport.resetStream(); + } +} + void RtfAttributeOutput::OutputFlyFrame_Impl(const sw::Frame& rFrame, const Point& /*rNdTopLeft*/) { const SwNode* pNode = rFrame.GetContent(); @@ -1641,55 +1710,8 @@ void RtfAttributeOutput::OutputFlyFrame_Impl(const sw::Frame& rFrame, const Poin } m_aFlyProperties.clear(); - m_rExport.Strm().WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_SHPTXT); - - { - // Save table state, in case the inner text also contains a table. - ww8::WW8TableInfo::Pointer_t pTableInfoOrig = m_rExport.mpTableInfo; - m_rExport.mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); - SwWriteTable* pTableWrt = m_pTableWrt; - m_pTableWrt = 0; - sal_uInt32 nTableDepth = m_nTableDepth; - - m_nTableDepth = 0; - /* - * Save m_aRun as we should not lose the opening brace. - * OTOH, just drop the contents of m_aRunText in case something - * would be there, causing a problem later. - */ - OString aSave = m_aRun.makeStringAndClear(); - // Also back m_bInRun and m_bSingleEmptyRun up. - bool bInRunOrig = m_bInRun; - m_bInRun = false; - bool bSingleEmptyRunOrig = m_bSingleEmptyRun; - m_bSingleEmptyRun = false; - m_rExport.bRTFFlySyntax = true; - - const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx(); - sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0; - sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0; - m_rExport.SaveData(nStt, nEnd); - m_rExport.mpParentFrame = &rFrame; - m_rExport.WriteText(); - m_rExport.RestoreData(); - - m_rExport.Strm().WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PARD); - m_rExport.bRTFFlySyntax = false; - m_aRun->append(aSave); - m_aRunText.clear(); - m_bInRun = bInRunOrig; - m_bSingleEmptyRun = bSingleEmptyRunOrig; - - // Restore table state. - m_rExport.mpTableInfo = pTableInfoOrig; - delete m_pTableWrt; - m_pTableWrt = pTableWrt; - m_nTableDepth = nTableDepth; - } - - m_rExport.mpParentFrame = NULL; + writeTextFrame(rFrame); - m_rExport.Strm().WriteChar('}'); // shptxt m_rExport.Strm().WriteChar('}'); // shpinst m_rExport.Strm().WriteChar('}'); // shp diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index f59a029..87b23ee 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -632,6 +632,9 @@ public: static OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, SvStream* pStream = 0, sal_uInt32 nLimit = 64); void BulletDefinition(int nId, const Graphic& rGraphic, Size aSize) SAL_OVERRIDE; + + /// Handles just the {\shptxt ...} part of a shape export. + void writeTextFrame(const sw::Frame& rFrame, bool bTextBox = false); }; #endif // INCLUDED_SW_SOURCE_FILTER_WW8_RTFATTRIBUTEOUTPUT_HXX diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx index 0d8e1d2..c776688 100644 --- a/sw/source/filter/ww8/rtfexport.cxx +++ b/sw/source/filter/ww8/rtfexport.cxx @@ -840,7 +840,30 @@ RtfExport::~RtfExport() SvStream& RtfExport::Strm() { - return m_pWriter->Strm(); + if (m_pStream) + return *m_pStream; + else + return m_pWriter->Strm(); +} + +void RtfExport::setStream() +{ + m_pStream.reset(new SvMemoryStream()); +} + +OString RtfExport::getStream() +{ + OString aRet; + + if (m_pStream) + aRet = OString(static_cast<const sal_Char*>(m_pStream->GetData()), m_pStream->Tell()); + + return aRet; +} + +void RtfExport::resetStream() +{ + m_pStream.reset(); } SvStream& RtfExport::OutULong(sal_uLong nVal) diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx index c384289..8045147 100644 --- a/sw/source/filter/ww8/rtfexport.hxx +++ b/sw/source/filter/ww8/rtfexport.hxx @@ -173,6 +173,12 @@ public: sal_uLong m_nCurrentNodeIndex; SvStream& Strm(); + /// From now on, let Strm() return a memory stream, not a real one. + void setStream(); + /// Get the contents of the memory stream as a string. + OString getStream(); + /// Return back to the real stream. + void resetStream(); SvStream& OutULong(sal_uLong nVal); SvStream& OutLong(long nVal); void OutUnicode(const sal_Char* pToken, const OUString& rContent, bool bUpr = false); @@ -211,6 +217,8 @@ private: RtfColorTbl m_aColTbl; RtfStyleTbl m_aStyTbl; RtfRedlineTbl m_aRedlineTbl; + /// If set, then Strm() returns this tream, instead of m_pWriter's stream. + std::unique_ptr<SvMemoryStream> m_pStream; }; #endif // INCLUDED_SW_SOURCE_FILTER_WW8_RTFEXPORT_HXX diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx index e25ba1d..e4b86f2 100644 --- a/sw/source/filter/ww8/rtfsdrexport.cxx +++ b/sw/source/filter/ww8/rtfsdrexport.cxx @@ -28,6 +28,7 @@ #include <svx/unoapi.hxx> #include <vcl/cvtgrf.hxx> #include <textboxhelper.hxx> +#include <dcontact.hxx> #include <algorithm> @@ -499,6 +500,27 @@ sal_Int32 RtfSdrExport::StartShape() lcl_AppendSP(m_rAttrOutput.RunText(), "wzName", msfilter::rtfutil::OutString(m_pSdrObject->GetTitle(), m_rExport.eCurrentEncoding)); // now check if we have some text + const SwFrmFmt* pShape = FindFrmFmt(m_pSdrObject); + if (pShape) + { + if (SwFrmFmt* pTextBox = SwTextBoxHelper::findTextBox(pShape)) + { + sw::Frame* pFrame = 0; + for (sw::FrameIter it = m_rExport.maFrames.begin(); it != m_rExport.maFrames.end(); ++it) + { + if (pTextBox == &it->GetFrmFmt()) + { + pFrame = &(*it); + break; + } + } + + if (pFrame) + m_rAttrOutput.writeTextFrame(*pFrame, /*bTextBox=*/true); + return m_nShapeType; + } + } + const SdrTextObj* pTxtObj = dynamic_cast<const SdrTextObj*>(m_pSdrObject); if (pTxtObj) { commit f57ed7edd498d62ca0ed9a8cedd72218985b4daf Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Wed Oct 15 11:31:20 2014 +0200 fdo#82860 RTF export: don't export textboxes of shapes twice See 96965fb39d6d376e91030a01c11f16f9428ddf2e (DOCX drawingML export: don't export textboxes of shapes twice, 2014-06-06). Change-Id: I89c039debeca5f88f172479b9f8ecbaec2dc7bc4 diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index a7eecbc..0a26834 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -1601,6 +1601,10 @@ void RtfAttributeOutput::OutputFlyFrame_Impl(const sw::Frame& rFrame, const Poin { case sw::Frame::eTxtBox: { + // If this is a TextBox of a shape, then ignore: it's handled in RtfSdrExport::StartShape(). + if (m_rExport.SdrExporter().isTextBox(rFrame.GetFrmFmt())) + break; + OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty"); m_rExport.mpParentFrame = &rFrame; diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx index 2b8e5fb..e25ba1d 100644 --- a/sw/source/filter/ww8/rtfsdrexport.cxx +++ b/sw/source/filter/ww8/rtfsdrexport.cxx @@ -27,6 +27,7 @@ #include <svx/svdotext.hxx> #include <svx/unoapi.hxx> #include <vcl/cvtgrf.hxx> +#include <textboxhelper.hxx> #include <algorithm> @@ -41,7 +42,8 @@ RtfSdrExport::RtfSdrExport(RtfExport& rExport) m_nShapeType(ESCHER_ShpInst_Nil), m_nShapeFlags(0) , m_pShapeStyle(new OStringBuffer(200)), - m_pShapeTypeWritten(new bool[ ESCHER_ShpInst_COUNT ]) + m_pShapeTypeWritten(new bool[ ESCHER_ShpInst_COUNT ]), + m_aTextBoxes(SwTextBoxHelper::findTextBoxes(m_rExport.pDoc)) { mnGroupLevel = 1; memset(m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof(bool)); @@ -596,4 +598,9 @@ sal_uInt32 RtfSdrExport::AddSdrObject(const SdrObject& rObj) return EscherEx::AddSdrObject(rObj); } +bool RtfSdrExport::isTextBox(const SwFrmFmt& rFrmFmt) +{ + return m_aTextBoxes.find(&rFrmFmt) != m_aTextBoxes.end(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/rtfsdrexport.hxx b/sw/source/filter/ww8/rtfsdrexport.hxx index 449a538..026a601 100644 --- a/sw/source/filter/ww8/rtfsdrexport.hxx +++ b/sw/source/filter/ww8/rtfsdrexport.hxx @@ -25,9 +25,11 @@ #include <rtl/strbuf.hxx> #include <map> +#include <set> class RtfExport; class RtfAttributeOutput; +class SwFrmFmt; /// Handles export of drawings using RTF markup class RtfSdrExport : public EscherEx @@ -52,6 +54,9 @@ class RtfSdrExport : public EscherEx /// Remember which shape types we had already written. bool* m_pShapeTypeWritten; + /// List of TextBoxes in this document: they are exported as part of their shape, never alone. + std::set<const SwFrmFmt*> m_aTextBoxes; + public: RtfSdrExport(RtfExport& rExport); virtual ~RtfSdrExport(); @@ -61,6 +66,9 @@ public: /// Call this when you need to export the object as Sdr in RTF. sal_uInt32 AddSdrObject(const SdrObject& rObj); + /// Is this a standalone TextFrame, or used as a TextBox of a shape? + bool isTextBox(const SwFrmFmt& rFrmFmt); + protected: /// Start the shape for which we just collected the information. /// _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits