[Libreoffice-commits] core.git: sw/qa writerfilter/inc writerfilter/Library_writerfilter.mk writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Tue Feb 23 08:15:01 UTC 2016


 sw/qa/extras/rtfimport/data/libreoffice.png       |binary
 sw/qa/extras/rtfimport/data/tdf59699.rtf          |   10 +++
 sw/qa/extras/rtfimport/rtfimport.cxx              |    9 ++
 writerfilter/Library_writerfilter.mk              |    1 
 writerfilter/inc/rtftok/RTFDocument.hxx           |    3 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |    3 
 writerfilter/source/dmapper/FieldTypes.hxx        |    1 
 writerfilter/source/filter/RtfFilter.cxx          |    2 
 writerfilter/source/rtftok/rtfdocumentfactory.cxx |    4 -
 writerfilter/source/rtftok/rtfdocumentimpl.cxx    |   67 +++++++++++++++++++++-
 writerfilter/source/rtftok/rtfdocumentimpl.hxx    |    6 +
 11 files changed, 96 insertions(+), 10 deletions(-)

New commits:
commit 6f94cab9c43f88624b58a47ad03ad5f87032595d
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Feb 23 09:13:40 2016 +0100

    tdf#59699 RTF import: handle INCLUDEPICTURE field
    
    On one hand, don't handle a fieldmark for it in dmapper.
    
    On the other hand, handle the field in the RTF tokenizer as it would be
    {\pict ...hexdump... }, that will result in an inline picture, as
    wanted.
    
    Change-Id: I554fdf017920350144300fd86617bf74eed8995b

diff --git a/sw/qa/extras/rtfimport/data/libreoffice.png b/sw/qa/extras/rtfimport/data/libreoffice.png
new file mode 100644
index 0000000..437f613
Binary files /dev/null and b/sw/qa/extras/rtfimport/data/libreoffice.png differ
diff --git a/sw/qa/extras/rtfimport/data/tdf59699.rtf b/sw/qa/extras/rtfimport/data/tdf59699.rtf
new file mode 100644
index 0000000..94331cc
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/tdf59699.rtf
@@ -0,0 +1,10 @@
+{\rtf1
+\pard\plain
+{\field
+{\*\fldinst 
+{ INCLUDEPICTURE "libreoffice.png" \\* MERGEFORMAT \\d }
+}
+{\fldrslt}
+}
+\par
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 52b9fd0..b1a6292 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -48,6 +48,7 @@
 #include <com/sun/star/text/VertOrientation.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
 
 #include <rtl/ustring.hxx>
 #include <vcl/outdev.hxx>
@@ -633,6 +634,14 @@ DECLARE_RTFIMPORT_TEST(testFdo49659, "fdo49659.rtf")
     CPPUNIT_ASSERT_EQUAL(graphic::GraphicType::PIXEL, getProperty<sal_Int8>(xGraphic, "GraphicType"));
 }
 
+DECLARE_OOXMLIMPORT_TEST(testTdf59699, "tdf59699.rtf")
+{
+    // This resulted in a lang.IndexOutOfBoundsException: the referenced graphic data wasn't imported.
+    uno::Reference<beans::XPropertySet> xImage(getShape(1), uno::UNO_QUERY);
+    auto xGraphic = getProperty<uno::Reference<graphic::XGraphic> >(xImage, "Graphic");
+    CPPUNIT_ASSERT(xGraphic.is());
+}
+
 DECLARE_RTFIMPORT_TEST(testFdo46966, "fdo46966.rtf")
 {
     /*
diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk
index 792b162..8d3508d 100644
--- a/writerfilter/Library_writerfilter.mk
+++ b/writerfilter/Library_writerfilter.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_Library_set_include,writerfilter,\
     $$(INCLUDE) \
     -I$(SRCDIR)/writerfilter/inc \
     -I$(SRCDIR)/writerfilter/source \
+    -I$(SRCDIR)/writerfilter/source/dmapper \
 ))
 
 $(eval $(call gb_Library_use_sdk_api,writerfilter))
diff --git a/writerfilter/inc/rtftok/RTFDocument.hxx b/writerfilter/inc/rtftok/RTFDocument.hxx
index ac40a9c..c3f65b7 100644
--- a/writerfilter/inc/rtftok/RTFDocument.hxx
+++ b/writerfilter/inc/rtftok/RTFDocument.hxx
@@ -15,6 +15,7 @@
 #include <com/sun/star/lang/XComponent.hpp>
 #include <com/sun/star/frame/XFrame.hpp>
 #include <com/sun/star/task/XStatusIndicator.hpp>
+#include <unotools/mediadescriptor.hxx>
 
 namespace writerfilter
 {
@@ -44,7 +45,7 @@ public:
                    css::uno::Reference<css::lang::XComponent> const& xDstDoc,
                    css::uno::Reference<css::frame::XFrame> const& xFrame,
                    css::uno::Reference<css::task::XStatusIndicator> const& xStatusIndicator,
-                   bool bIsNewDoc);
+                   const utl::MediaDescriptor& rMediaDescriptor);
 };
 } // namespace rtftok
 } // namespace writerfilter
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 8783535..3dc0040 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -2807,7 +2807,7 @@ if(!bFilled)
             {OUString("HYPERLINK"),     "",                         FIELD_HYPERLINK    },
             {OUString("IF"),            "ConditionalText",          FIELD_IF           },
 //            {OUString("INFO"),      "",FIELD_INFO         },
-//            {OUString("INCLUDEPICTURE"), "",                        FIELD_INCLUDEPICTURE},
+            {OUString("INCLUDEPICTURE"), "",                        FIELD_INCLUDEPICTURE},
             {OUString("KEYWORDS"),      "DocInfo.KeyWords",         FIELD_KEYWORDS     },
             {OUString("LASTSAVEDBY"),   "DocInfo.ChangeAuthor",                         FIELD_LASTSAVEDBY  },
             {OUString("MACROBUTTON"),   "Macro",                         FIELD_MACROBUTTON  },
@@ -3572,6 +3572,7 @@ void DomainMapper_Impl::CloseFieldCommand()
                 case FIELD_CITATION:
                 case FIELD_TC:
                 case FIELD_EQ:
+                case FIELD_INCLUDEPICTURE:
                         bCreateField = false;
                         break;
                 case FIELD_FORMCHECKBOX :
diff --git a/writerfilter/source/dmapper/FieldTypes.hxx b/writerfilter/source/dmapper/FieldTypes.hxx
index dc5eb7c..5c446a3 100644
--- a/writerfilter/source/dmapper/FieldTypes.hxx
+++ b/writerfilter/source/dmapper/FieldTypes.hxx
@@ -120,7 +120,6 @@ enum FieldId
     ,FIELD_INFO
     /* INCLUDEPICTURE path \* MERGEFORMAT->
      old filter imports an embedded picture
-     todo: not yet supported
      */
     ,FIELD_INCLUDEPICTURE
     /* KEYWORDS keyword \* defaultswitch \* Numberingswitch \* MERGEFORMAT ->
diff --git a/writerfilter/source/filter/RtfFilter.cxx b/writerfilter/source/filter/RtfFilter.cxx
index b2f0555..a482dcc 100644
--- a/writerfilter/source/filter/RtfFilter.cxx
+++ b/writerfilter/source/filter/RtfFilter.cxx
@@ -145,7 +145,7 @@ sal_Bool RtfFilter::filter(const uno::Sequence< beans::PropertyValue >& aDescrip
         writerfilter::dmapper::SourceDocumentType eType = writerfilter::dmapper::SourceDocumentType::RTF;
         writerfilter::Stream::Pointer_t pStream(writerfilter::dmapper::DomainMapperFactory::createMapper(m_xContext, xInputStream, m_xDstDoc, bRepairStorage, eType, aMediaDesc));
         writerfilter::rtftok::RTFDocument::Pointer_t pDocument(
-            writerfilter::rtftok::RTFDocumentFactory::createDocument(m_xContext, xInputStream, m_xDstDoc, xFrame, xStatusIndicator, bIsNewDoc));
+            writerfilter::rtftok::RTFDocumentFactory::createDocument(m_xContext, xInputStream, m_xDstDoc, xFrame, xStatusIndicator, aMediaDesc));
         pDocument->resolve(*pStream);
         bResult = true;
         sal_uInt32 nEndTime = osl_getGlobalTimer();
diff --git a/writerfilter/source/rtftok/rtfdocumentfactory.cxx b/writerfilter/source/rtftok/rtfdocumentfactory.cxx
index 0722bff..aadfc38 100644
--- a/writerfilter/source/rtftok/rtfdocumentfactory.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentfactory.cxx
@@ -19,9 +19,9 @@ RTFDocument::Pointer_t RTFDocumentFactory::createDocument(css::uno::Reference< c
         css::uno::Reference< css::lang::XComponent > const& xDstDoc,
         css::uno::Reference< css::frame::XFrame > const& xFrame,
         css::uno::Reference< css::task::XStatusIndicator > const& xStatusIndicator,
-        bool bIsNewDoc)
+        const utl::MediaDescriptor& rMediaDescriptor)
 {
-    return std::make_shared<RTFDocumentImpl>(xContext, xInputStream, xDstDoc, xFrame, xStatusIndicator, bIsNewDoc);
+    return std::make_shared<RTFDocumentImpl>(xContext, xInputStream, xDstDoc, xFrame, xStatusIndicator, rMediaDescriptor);
 }
 
 } // namespace rtftok
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index bf41bbe..7473a98 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -34,6 +34,8 @@
 #include <ooxml/resourceids.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
+#include <rtl/uri.hxx>
+#include <dmapper/DomainMapper_Impl.hxx>
 #include <rtfsdrimport.hxx>
 #include <rtflookahead.hxx>
 #include <rtfcharsets.hxx>
@@ -211,7 +213,7 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
                                  uno::Reference<lang::XComponent> const& xDstDoc,
                                  uno::Reference<frame::XFrame> const& xFrame,
                                  uno::Reference<task::XStatusIndicator> const& xStatusIndicator,
-                                 bool bIsNewDoc)
+                                 const utl::MediaDescriptor& rMediaDescriptor)
     : m_xContext(xContext),
       m_xInputStream(xInputStream),
       m_xDstDoc(xDstDoc),
@@ -270,7 +272,8 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
       m_bHadSect(false),
       m_nCellxMax(0),
       m_nListPictureId(0),
-      m_bIsNewDoc(bIsNewDoc)
+      m_bIsNewDoc(!rMediaDescriptor.getUnpackedValueOrDefault("InsertMode", false)),
+      m_rMediaDescriptor(rMediaDescriptor)
 {
     OSL_ASSERT(xInputStream.is());
     m_pInStream.reset(utl::UcbStreamHelper::CreateStream(xInputStream, true));
@@ -341,7 +344,7 @@ void RTFDocumentImpl::resolveSubstream(sal_Size nPos, Id nId, OUString& rIgnoreF
 {
     sal_Size nCurrent = Strm().Tell();
     // Seek to header position, parse, then seek back.
-    auto pImpl = std::make_shared<RTFDocumentImpl>(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame, m_xStatusIndicator, m_bIsNewDoc);
+    auto pImpl = std::make_shared<RTFDocumentImpl>(m_xContext, m_xInputStream, m_xDstDoc, m_xFrame, m_xStatusIndicator, m_rMediaDescriptor);
     pImpl->setSuperstream(this);
     pImpl->setStreamType(nId);
     pImpl->setIgnoreFirst(rIgnoreFirst);
@@ -1548,6 +1551,24 @@ RTFError RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
                 if (!aBuf.isEmpty() && !isalnum(ch))
                     bFoundCode = true;
             }
+
+            if (aBuf.toString() == "INCLUDEPICTURE")
+            {
+                // Extract the field argument of INCLUDEPICTURE: we handle that
+                // at a tokenizer level, as DOCX has no such field.
+                aBuf.append(ch);
+                while (true)
+                {
+                    Strm().ReadChar(ch);
+                    if (ch == '}')
+                        break;
+                    aBuf.append(ch);
+                }
+                OUString aFieldCommand = OStringToOUString(aBuf.toString(), RTL_TEXTENCODING_UTF8);
+                std::tuple<OUString, std::vector<OUString>, std::vector<OUString> > aResult = writerfilter::dmapper::lcl_SplitFieldCommand(aFieldCommand);
+                m_aPicturePath = std::get<1>(aResult).empty() ? OUString() : std::get<1>(aResult).front();
+            }
+
             Strm().Seek(nPos);
 
             // Form data should be handled only for form fields if any
@@ -5149,6 +5170,46 @@ RTFError RTFDocumentImpl::popState()
     break;
     case Destination::FIELDRESULT:
         singleChar(cFieldEnd);
+
+        if (!m_aPicturePath.isEmpty())
+        {
+            // Read the picture into m_aStates.top().aDestinationText.
+            pushState();
+            dispatchDestination(RTF_PICT);
+            if (m_aPicturePath.endsWith(".png"))
+                dispatchFlag(RTF_PNGBLIP);
+            OUString aFileURL = m_rMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL(), OUString());
+            OUString aPictureURL;
+            try
+            {
+                aPictureURL = rtl::Uri::convertRelToAbs(aFileURL, m_aPicturePath);
+            }
+            catch(const rtl::MalformedUriException& rException)
+            {
+                SAL_WARN("writerfilter", "rtl::Uri::convertRelToAbs() failed: " << rException.getMessage());
+            }
+
+            if (!aPictureURL.isEmpty())
+            {
+                SvFileStream aStream(aPictureURL, StreamMode::READ);
+                if (aStream.IsOpen())
+                {
+                    OUStringBuffer aBuf;
+                    while (aStream.good())
+                    {
+                        unsigned char ch = 0;
+                        aStream.ReadUChar(ch);
+                        if (ch < 16)
+                            aBuf.append("0");
+                        aBuf.append(OUString::number(ch, 16));
+                    }
+                    m_aStates.top().aDestinationText = aBuf;
+                }
+            }
+            popState();
+            m_aPicturePath.clear();
+        }
+
         break;
     case Destination::LEVELTEXT:
     {
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 830eddd..227e940 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -332,7 +332,7 @@ public:
                     css::uno::Reference<css::lang::XComponent> const& xDstDoc,
                     css::uno::Reference<css::frame::XFrame> const& xFrame,
                     css::uno::Reference<css::task::XStatusIndicator> const& xStatusIndicator,
-                    bool bIsNewDoc);
+                    const utl::MediaDescriptor& rMediaDescriptor);
     virtual ~RTFDocumentImpl();
 
     // RTFDocument
@@ -564,6 +564,8 @@ private:
     RTFReferenceTable::Entries_t m_aStyleTableEntries;
     int m_nCurrentStyleIndex;
     bool m_bFormField;
+    /// For the INCLUDEPICTURE field's argument.
+    OUString m_aPicturePath;
     // Unicode characters are collected here so we don't have to send them one by one.
     OUStringBuffer m_aUnicodeBuffer;
     /// Same for hex characters.
@@ -592,6 +594,8 @@ private:
 
     /// New document means not pasting into an existing one.
     bool m_bIsNewDoc;
+    /// The media descriptor contains e.g. the base URL of the document.
+    const utl::MediaDescriptor& m_rMediaDescriptor;
 };
 } // namespace rtftok
 } // namespace writerfilter


More information about the Libreoffice-commits mailing list