[Libreoffice-commits] core.git: 3 commits - sw/qa sw/source writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Wed Oct 15 04:19:44 PDT 2014


 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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.
     ///


More information about the Libreoffice-commits mailing list