[Libreoffice-commits] core.git: Branch 'libreoffice-5-0' - sw/qa writerfilter/inc writerfilter/Library_writerfilter.mk writerfilter/source
Miklos Vajna
vmiklos at collabora.co.uk
Thu Mar 24 13:20:50 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 b5464c15078b57e852100a76f03fadef3186c93d
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.
(cherry picked from commit 6f94cab9c43f88624b58a47ad03ad5f87032595d)
Conflicts:
writerfilter/source/dmapper/DomainMapper_Impl.cxx
writerfilter/source/rtftok/rtfdocumentimpl.hxx
Change-Id: I554fdf017920350144300fd86617bf74eed8995b
Reviewed-on: https://gerrit.libreoffice.org/23298
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Michael Stahl <mstahl at redhat.com>
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 f1d0927..1c4b457 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>
@@ -628,6 +629,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 6149401..c81ff56 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 01a9880..1d96bec 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 02a965a..2906e24 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -2816,7 +2816,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 },
@@ -3516,6 +3516,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 0ce6e1f..a9b8a2e 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 7bf88b2..96f8d15 100644
--- a/writerfilter/source/filter/RtfFilter.cxx
+++ b/writerfilter/source/filter/RtfFilter.cxx
@@ -148,7 +148,7 @@ sal_Bool RtfFilter::filter(const uno::Sequence< beans::PropertyValue >& aDescrip
writerfilter::Stream::Pointer_t pStream(
writerfilter::dmapper::DomainMapperFactory::createMapper(m_xContext, xInputStream, m_xDstDoc, bRepairStorage, eType, xInsertTextRange, 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 c6f3d32..f9cf146 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -35,6 +35,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>
@@ -212,7 +214,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),
@@ -272,7 +274,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));
@@ -343,7 +346,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);
@@ -1544,6 +1547,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);
+ boost::tuple<OUString, std::vector<OUString>, std::vector<OUString> > aResult = writerfilter::dmapper::lcl_SplitFieldCommand(aFieldCommand);
+ m_aPicturePath = boost::get<1>(aResult).empty() ? OUString() : boost::get<1>(aResult).front();
+ }
+
Strm().Seek(nPos);
// Form data should be handled only for form fields if any
@@ -5124,6 +5145,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 863b952..823ccc2 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
@@ -565,6 +565,8 @@ private:
bool m_bFormField;
/// If a frame start token is already sent to dmapper (nesting them is not OK).
bool m_bIsInFrame;
+ /// 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.
@@ -593,6 +595,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