[Libreoffice-commits] core.git: Branch 'distro/vector/vector-5.4' - 4 commits - filter/source include/tools sw/CppunitTest_sw_htmlexport.mk sw/qa sw/source tools/source
Miklos Vajna (via logerrit)
logerrit at kemper.freedesktop.org
Mon May 4 15:49:15 UTC 2020
filter/source/msfilter/rtfutil.cxx | 86 ++++++++++++++-
include/tools/stream.hxx | 1
sw/CppunitTest_sw_htmlexport.mk | 3
sw/qa/extras/htmlexport/data/pdf-ole.odt |binary
sw/qa/extras/htmlexport/htmlexport.cxx | 169 ++++++++++++++++++++++++++++++
sw/source/filter/html/htmlreqifreader.cxx | 99 +++++++++++++++++
tools/source/stream/stream.cxx | 20 +++
7 files changed, 372 insertions(+), 6 deletions(-)
New commits:
commit 2059ea2a92f73cc8ea4bcf9bad833132c8f4c39c
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon May 4 10:48:07 2020 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon May 4 16:59:37 2020 +0200
sw reqif-xhtml import, embedded objects: handle Ole10Native stream
This is the import side of commit
1392fd6a7eaf9f507639096984c2a0108f254795 (sw reqif-xhtml export,
embedded objects: handle Ole10Native stream, 2020-04-30).
(cherry picked from commit 800085d4fb0831f2065e86bfd99164cd89998fcd)
Conflicts:
filter/source/msfilter/rtfutil.cxx
sw/CppunitTest_sw_htmlexport.mk
Change-Id: Ib98620f06c471a58e75b0e6c0230d37820dbc928
diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx
index ee7b4c7b74bc..497554163b8d 100644
--- a/filter/source/msfilter/rtfutil.cxx
+++ b/filter/source/msfilter/rtfutil.cxx
@@ -15,6 +15,68 @@
#include <tools/stream.hxx>
#include <unotools/streamwrap.hxx>
#include <vector>
+#include <sot/stg.hxx>
+#include <sot/storage.hxx>
+
+namespace
+{
+/// If rOle1 is native OLE1 data of size nOle1Size, wraps it in an OLE2 container.
+void WrapOle1InOle2(SvStream& rOle1, sal_uInt32 nOle1Size, SvStream& rOle2)
+{
+ tools::SvRef<SotStorage> pStorage = new SotStorage(rOle2);
+ // OLE Package Object
+ SvGlobalName aName(0x0003000C, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46);
+ pStorage->SetClass(aName, SotClipboardFormatId::NONE, "");
+
+ // [MS-OLEDS] 2.3.7 CompObjHeader
+ tools::SvRef<SotStorageStream> pCompObj = pStorage->OpenSotStream("\1CompObj");
+ // Reserved1
+ pCompObj->WriteUInt32(0xfffe0001);
+ // Version
+ pCompObj->WriteUInt32(0x00000a03);
+ // Reserved2
+ pCompObj->WriteUInt32(0xffffffff);
+ pCompObj->WriteUInt32(0x0003000c);
+ pCompObj->WriteUInt32(0x00000000);
+ pCompObj->WriteUInt32(0x000000c0);
+ pCompObj->WriteUInt32(0x46000000);
+ // Rest of CompObjStream
+ // AnsiUserType
+ OString aAnsiUserType("OLE Package");
+ pCompObj->WriteUInt32(aAnsiUserType.getLength() + 1);
+ pCompObj->WriteOString(aAnsiUserType);
+ pCompObj->WriteChar(0);
+ // AnsiClipboardFormat
+ pCompObj->WriteUInt32(0x00000000);
+ // Reserved1
+ OString aReserved1("Package");
+ pCompObj->WriteUInt32(aReserved1.getLength() + 1);
+ pCompObj->WriteOString(aReserved1);
+ pCompObj->WriteChar(0);
+ // UnicodeMarker
+ pCompObj->WriteUInt32(0x71B239F4);
+ // UnicodeUserType
+ pCompObj->WriteUInt32(0x00000000);
+ // UnicodeClipboardFormat
+ pCompObj->WriteUInt32(0x00000000);
+ // Reserved2
+ pCompObj->WriteUInt32(0x00000000);
+ pCompObj->Commit();
+ pCompObj.clear();
+
+ // [MS-OLEDS] 2.3.6 OLENativeStream
+ tools::SvRef<SotStorageStream> pOleNative = pStorage->OpenSotStream("\1Ole10Native");
+ // NativeDataSize
+ pOleNative->WriteUInt32(nOle1Size);
+ pOleNative->WriteStream(rOle1, nOle1Size);
+ pOleNative->Commit();
+ pOleNative.clear();
+
+ pStorage->Commit();
+ pStorage.clear();
+ rOle2.Seek(0);
+}
+}
namespace msfilter
{
@@ -277,10 +339,26 @@ bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
if (nData)
{
- // NativeData
- std::vector<char> aBuffer(nData);
- aStream.ReadBytes(aBuffer.data(), aBuffer.size());
- rOle2.WriteBytes(aBuffer.data(), aBuffer.size());
+ sal_uInt64 nPos = aStream.Tell();
+ sal_uInt8 aSignature[8];
+ aStream.ReadBytes(aSignature, SAL_N_ELEMENTS(aSignature));
+ aStream.Seek(nPos);
+ const sal_uInt8 aOle2Signature[8] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
+ // Don't use Storage::IsStorageFile() here, that would seek to the start of the stream,
+ // where the magic will always mismatch.
+ if (std::memcmp(aSignature, aOle2Signature, SAL_N_ELEMENTS(aSignature)) == 0)
+ {
+ // NativeData
+ std::vector<char> aBuffer(nData);
+ aStream.ReadBytes(aBuffer.data(), aBuffer.size());
+ rOle2.WriteBytes(aBuffer.data(), aBuffer.size());
+ }
+ else
+ {
+ SvMemoryStream aStorage;
+ WrapOle1InOle2(aStream, nData, aStorage);
+ rOle2.WriteStream(aStorage);
+ }
rOle2.Seek(0);
}
}
diff --git a/sw/CppunitTest_sw_htmlexport.mk b/sw/CppunitTest_sw_htmlexport.mk
index a464e571b27f..0d8cd44f4619 100644
--- a/sw/CppunitTest_sw_htmlexport.mk
+++ b/sw/CppunitTest_sw_htmlexport.mk
@@ -23,6 +23,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_htmlexport, \
msfilter \
sal \
sfx \
+ sot \
svt \
sw \
test \
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 4cc9ea879238..b19a6bf3ad19 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -34,6 +34,7 @@
#include <rtl/strbuf.hxx>
#include <svtools/rtftoken.h>
#include <filter/msfilter/rtfutil.hxx>
+#include <sot/storage.hxx>
class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
{
@@ -1045,6 +1046,36 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PDF)
// i.e. we did not work with the Ole10Native stream, rather created an OLE1 wrapper around the
// OLE1-in-OLE2 data, resulting in additional size.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0x99ed), nData);
+
+ // Now import this back and check the ODT result.
+ mxComponent->dispose();
+ mxComponent.clear();
+ uno::Sequence<beans::PropertyValue> aLoadProperties = {
+ comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")),
+ comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")),
+ };
+ mxComponent
+ = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument", aLoadProperties);
+ xStorable.set(mxComponent, uno::UNO_QUERY);
+ utl::TempFile aTempFile;
+ aStoreProperties = {
+ comphelper::makePropertyValue("FilterName", OUString("writer8")),
+ };
+ xStorable->storeToURL(aTempFile.GetURL(), aStoreProperties);
+ uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
+ = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory),
+ aTempFile.GetURL());
+ uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName("Object 2"),
+ uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ tools::SvRef<SotStorage> pStorage = new SotStorage(*pStream);
+ tools::SvRef<SotStorageStream> pOleNative = pStorage->OpenSotStream("\1Ole10Native");
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 39409
+ // - Actual : 0
+ // i.e. we didn't handle the case when the ole1 payload was not an ole2 container. Note how the
+ // expected value is the same as nData above + 4 bytes, since this data is length-prefixed.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(39409), pOleNative->GetSize());
}
CPPUNIT_PLUGIN_IMPLEMENT();
commit ba8768e43fe357f2049659b6fc1ef6c13a1c74ef
Author: Caolán McNamara <caolanm at redhat.com>
AuthorDate: Fri Feb 16 09:20:12 2018 +0000
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon May 4 16:59:36 2020 +0200
Resolves: tdf#115750 SvStream::WriteStream was broken
and didn't stop copying at the size limit arg
(cherry picked from commit bcdaaf62d41728eb757ff2b9cb95c2df2791e2f4)
Change-Id: I8f1be0310160f5158d2f64c62d6b2c09c0157930
diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx
index b83729e35fbf..530f6e8c0620 100644
--- a/tools/source/stream/stream.cxx
+++ b/tools/source/stream/stream.cxx
@@ -1184,13 +1184,12 @@ sal_uInt64 SvStream::WriteStream( SvStream& rStream, sal_uInt64 nSize )
sal_uInt32 nCount;
sal_uInt64 nWriteSize = nSize;
- do {
- if ( nSize >= nCurBufLen )
- nWriteSize -= nCurBufLen;
- else
- nCurBufLen = nWriteSize;
- nCount = rStream.ReadBytes( pBuf.get(), nCurBufLen );
+ do
+ {
+ nCurBufLen = std::min<sal_uInt64>(nCurBufLen, nWriteSize);
+ nCount = rStream.ReadBytes(pBuf.get(), nCurBufLen);
WriteBytes( pBuf.get(), nCount );
+ nWriteSize -= nCount;
}
while( nWriteSize && nCount == nCurBufLen );
commit 9394cb57ecb24160649d7e3188c75f64d810ca51
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Apr 30 12:40:24 2020 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon May 4 15:05:13 2020 +0200
sw reqif-xhtml export, embedded objects: handle Ole10Native stream
Normally the embedded object has some OLE2 native data, and we insert
our OLE1 header before that. But in case the OLE2 data already has an
Ole10Native stream, then don't create an OLE1-in-OLE2-in-OLE1 output:
it's pointless and some consumers have trouble parsing that.
(cherry picked from commit 1392fd6a7eaf9f507639096984c2a0108f254795)
Change-Id: Ifc8b37494f97da89ce66a147e08a49eaa2f7ae1e
diff --git a/sw/CppunitTest_sw_htmlexport.mk b/sw/CppunitTest_sw_htmlexport.mk
index 4dabbe61606f..a464e571b27f 100644
--- a/sw/CppunitTest_sw_htmlexport.mk
+++ b/sw/CppunitTest_sw_htmlexport.mk
@@ -20,8 +20,10 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_htmlexport, \
cppu \
cppuhelper \
i18nlangtag \
+ msfilter \
sal \
sfx \
+ svt \
sw \
test \
tl \
diff --git a/sw/qa/extras/htmlexport/data/pdf-ole.odt b/sw/qa/extras/htmlexport/data/pdf-ole.odt
new file mode 100644
index 000000000000..184449a4f829
Binary files /dev/null and b/sw/qa/extras/htmlexport/data/pdf-ole.odt differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 92375cbe2c81..4cc9ea879238 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -30,6 +30,10 @@
#include <svtools/rtfkeywd.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/propertysequence.hxx>
+#include <svtools/parrtf.hxx>
+#include <rtl/strbuf.hxx>
+#include <svtools/rtftoken.h>
+#include <filter/msfilter/rtfutil.hxx>
class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
{
@@ -909,6 +913,140 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifParagraphAlignment)
assertXPathNoAttribute(pDoc, "//reqif-xhtml:p", "align");
}
+namespace
+{
+/// Test RTF parser that just extracts a single OLE2 object from a file.
+class TestReqIfRtfReader : public SvRTFParser
+{
+public:
+ TestReqIfRtfReader(SvStream& rStream);
+ void NextToken(int nToken) override;
+ bool WriteObjectData(SvStream& rOLE);
+
+private:
+ bool m_bInObjData = false;
+ OStringBuffer m_aHex;
+};
+
+TestReqIfRtfReader::TestReqIfRtfReader(SvStream& rStream)
+ : SvRTFParser(rStream)
+{
+}
+
+void TestReqIfRtfReader::NextToken(int nToken)
+{
+ switch (nToken)
+ {
+ case '}':
+ m_bInObjData = false;
+ break;
+ case RTF_TEXTTOKEN:
+ if (m_bInObjData)
+ m_aHex.append(OUStringToOString(aToken, RTL_TEXTENCODING_ASCII_US));
+ break;
+ case RTF_OBJDATA:
+ m_bInObjData = true;
+ break;
+ }
+}
+
+bool TestReqIfRtfReader::WriteObjectData(SvStream& rOLE)
+{
+ OString aObjdata = m_aHex.makeStringAndClear();
+
+ SvMemoryStream aStream;
+ int b = 0;
+ int count = 2;
+
+ // Feed the destination text to a stream.
+ for (int i = 0; i < aObjdata.getLength(); ++i)
+ {
+ char ch = aObjdata[i];
+ if (ch != 0x0d && ch != 0x0a)
+ {
+ b = b << 4;
+ sal_Int8 parsed = msfilter::rtfutil::AsHex(ch);
+ if (parsed == -1)
+ return false;
+ b += parsed;
+ count--;
+ if (!count)
+ {
+ aStream.WriteChar(b);
+ count = 2;
+ b = 0;
+ }
+ }
+ }
+
+ aStream.Seek(0);
+ rOLE.WriteStream(aStream);
+ return true;
+}
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PDF)
+{
+ // Save to reqif-xhtml.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf-ole.odt";
+ mxComponent = loadFromDesktop(aURL, "com.sun.star.text.TextDocument", {});
+
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aStoreProperties = {
+ comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")),
+ comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")),
+ };
+ xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+ // Get the .ole path.
+ SvMemoryStream aStream;
+ HtmlExportTest::wrapFragment(maTempFile, aStream);
+ xmlDocPtr pDoc = parseXmlStream(&aStream);
+ CPPUNIT_ASSERT(pDoc);
+ OUString aOlePath = getXPath(
+ pDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p/reqif-xhtml:object", "data");
+ OUString aOleSuffix(".ole");
+ CPPUNIT_ASSERT(aOlePath.endsWith(aOleSuffix));
+ INetURLObject aUrl(maTempFile.GetURL());
+ aUrl.setBase(aOlePath.copy(0, aOlePath.getLength() - aOleSuffix.getLength()));
+ aUrl.setExtension("ole");
+ OUString aRtfUrl = aUrl.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+
+ // Parse the ole1 data out of that.
+ SvFileStream aRtfStream(aRtfUrl, StreamMode::READ);
+ SvMemoryStream aRtf;
+ aRtf.WriteOString("{\\rtf1");
+ aRtf.WriteStream(aRtfStream);
+ aRtf.WriteOString("}");
+ aRtf.Seek(0);
+ tools::SvRef<TestReqIfRtfReader> xReader(new TestReqIfRtfReader(aRtf));
+ CPPUNIT_ASSERT(xReader->CallParser() != SvParserState::Error);
+ SvMemoryStream aOle1;
+ CPPUNIT_ASSERT(xReader->WriteObjectData(aOle1));
+ CPPUNIT_ASSERT(aOle1.Tell());
+
+ // Check the content of the ole1 data.
+ // Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
+ aOle1.Seek(0);
+ sal_uInt32 nData;
+ aOle1.ReadUInt32(nData); // OLEVersion
+ aOle1.ReadUInt32(nData); // FormatID
+ aOle1.ReadUInt32(nData); // ClassName
+ aOle1.SeekRel(nData);
+ aOle1.ReadUInt32(nData); // TopicName
+ aOle1.SeekRel(nData);
+ aOle1.ReadUInt32(nData); // ItemName
+ aOle1.SeekRel(nData);
+ aOle1.ReadUInt32(nData); // NativeDataSize
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 39405
+ // - Actual : 43008
+ // i.e. we did not work with the Ole10Native stream, rather created an OLE1 wrapper around the
+ // OLE1-in-OLE2 data, resulting in additional size.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0x99ed), nData);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index 9f657663b126..5600ec189094 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -144,14 +144,109 @@ bool ParseOLE2Presentation(SvStream& rOle2, sal_uInt32& nWidth, sal_uInt32& nHei
return true;
}
+/**
+ * Inserts an OLE1 header before an OLE2 storage, assuming that the storage has an Ole10Native
+ * stream.
+ */
+OString InsertOLE1HeaderFromOle10NativeStream(tools::SvRef<SotStorage>& xStorage,
+ SwOLENode& rOLENode, SvStream& rOle1)
+{
+ tools::SvRef<SotStorageStream> xOle1Stream
+ = xStorage->OpenSotStream("\1Ole10Native", StreamMode::STD_READ);
+ sal_uInt32 nOle1Size = 0;
+ xOle1Stream->ReadUInt32(nOle1Size);
+
+ OString aClassName("Package");
+
+ // Write ObjectHeader, see [MS-OLEDS] 2.2.4.
+ rOle1.Seek(0);
+ // OLEVersion.
+ rOle1.WriteUInt32(0x00000501);
+
+ // FormatID is EmbeddedObject.
+ rOle1.WriteUInt32(0x00000002);
+
+ // ClassName
+ rOle1.WriteUInt32(aClassName.isEmpty() ? 0 : aClassName.getLength() + 1);
+ if (!aClassName.isEmpty())
+ {
+ rOle1.WriteOString(aClassName);
+ // Null terminated pascal string.
+ rOle1.WriteChar(0);
+ }
+
+ // TopicName.
+ rOle1.WriteUInt32(0);
+
+ // ItemName.
+ rOle1.WriteUInt32(0);
+
+ // NativeDataSize
+ rOle1.WriteUInt32(nOle1Size);
+
+ // Write the actual native data.
+ rOle1.WriteStream(*xOle1Stream, nOle1Size);
+
+ // Write Presentation.
+ if (!rOLENode.GetGraphic())
+ {
+ return aClassName;
+ }
+
+ const Graphic& rGraphic = *rOLENode.GetGraphic();
+ Size aSize = rOLENode.GetTwipSize();
+ SvMemoryStream aGraphicStream;
+ if (GraphicConverter::Export(aGraphicStream, rGraphic, ConvertDataFormat::WMF) != ERRCODE_NONE)
+ {
+ return aClassName;
+ }
+
+ auto pGraphicAry = static_cast<const sal_uInt8*>(aGraphicStream.GetData());
+ sal_uInt64 nPos = aGraphicStream.Tell();
+ aGraphicStream.Seek(STREAM_SEEK_TO_END);
+ sal_uInt64 nPresentationData = aGraphicStream.Tell();
+ aGraphicStream.Seek(nPos);
+ msfilter::rtfutil::StripMetafileHeader(pGraphicAry, nPresentationData);
+
+ // OLEVersion.
+ rOle1.WriteUInt32(0x00000501);
+ // FormatID: constant means the ClassName field is present.
+ rOle1.WriteUInt32(0x00000005);
+ // ClassName: null terminated pascal string.
+ OString aPresentationClassName("METAFILEPICT");
+ rOle1.WriteUInt32(aPresentationClassName.getLength() + 1);
+ rOle1.WriteOString(aPresentationClassName);
+ rOle1.WriteChar(0);
+ // Width.
+ rOle1.WriteUInt32(aSize.getWidth());
+ // Height.
+ rOle1.WriteUInt32(aSize.getHeight() * -1);
+ // PresentationDataSize
+ rOle1.WriteUInt32(8 + nPresentationData);
+ // Reserved1-4.
+ rOle1.WriteUInt16(0x0008);
+ rOle1.WriteUInt16(0x31b1);
+ rOle1.WriteUInt16(0x1dd9);
+ rOle1.WriteUInt16(0x0000);
+ rOle1.WriteBytes(pGraphicAry, nPresentationData);
+
+ return aClassName;
+}
+
/// Inserts an OLE1 header before an OLE2 storage.
-OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1, sal_uInt32& nWidth, sal_uInt32& nHeight)
+OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1, sal_uInt32& nWidth, sal_uInt32& nHeight,
+ SwOLENode& rOLENode)
{
rOle2.Seek(0);
tools::SvRef<SotStorage> xStorage(new SotStorage(rOle2));
if (xStorage->GetError() != ERRCODE_NONE)
return OString();
+ if (xStorage->IsStream("\1Ole10Native"))
+ {
+ return InsertOLE1HeaderFromOle10NativeStream(xStorage, rOLENode, rOle1);
+ }
+
OString aClassName = ExtractOLEClassName(xStorage);
// Write ObjectHeader, see [MS-OLEDS] 2.2.4.
@@ -308,7 +403,7 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode)
SvMemoryStream aOLE1;
sal_uInt32 nWidth = 0;
sal_uInt32 nHeight = 0;
- OString aClassName = InsertOLE1Header(rOle2, aOLE1, nWidth, nHeight);
+ OString aClassName = InsertOLE1Header(rOle2, aOLE1, nWidth, nHeight, rOLENode);
// Start object.
rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_OBJECT);
commit 93e463274a1a4c1bb3e10faa60c0512cdce65952
Author: Jan-Marek Glogowski <glogow at fbihome.de>
AuthorDate: Thu Oct 26 16:05:54 2017 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon May 4 13:45:18 2020 +0200
tdf#108748 generate PDF preview on SwapIn
When including a PDF as an image, it's represented internally as
a Bitmap with additional PDF data. On SwapIn, LibreOffice just
imported the PDF data missing the PDF preview. The Graphic also
gad the wrong image type, which results in a busy loop on master,
with a strange / unhelpful STR_COMCORE_READERROR generated by
SwNoTextFrame::PaintPicture.
This is a workaround to generate the Bitmap on SwapIn, which
will really slow down LibreOffice when importing many PDFs.
I guess the job of generating the PDF previews should probably
be deferred to a thread or a low priority Scheduler task, just
like the general image loading is handled.
(cherry picked from commit 3a88795c1211c62277dc646e61c2ba8306febe37)
Change-Id: I8084e4533995ecddc5b03ef19cb0c6a2dbf60ebd
diff --git a/include/tools/stream.hxx b/include/tools/stream.hxx
index 0bc3766807fa..608f7f0adde0 100644
--- a/include/tools/stream.hxx
+++ b/include/tools/stream.hxx
@@ -257,6 +257,7 @@ public:
SvStream& WriteOString(const OString& rStr)
{ return WriteCharPtr(rStr.getStr()); }
SvStream& WriteStream( SvStream& rStream );
+ sal_uInt64 WriteStream( SvStream& rStream, sal_uInt64 nSize );
SvStream& WriteBool( bool b )
{ return WriteUChar(static_cast<unsigned char>(b)); }
diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx
index 488348719892..b83729e35fbf 100644
--- a/tools/source/stream/stream.cxx
+++ b/tools/source/stream/stream.cxx
@@ -1176,6 +1176,27 @@ SvStream& SvStream::WriteStream( SvStream& rStream )
return *this;
}
+sal_uInt64 SvStream::WriteStream( SvStream& rStream, sal_uInt64 nSize )
+{
+ const sal_uInt32 cBufLen = 0x8000;
+ std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
+ sal_uInt32 nCurBufLen = cBufLen;
+ sal_uInt32 nCount;
+ sal_uInt64 nWriteSize = nSize;
+
+ do {
+ if ( nSize >= nCurBufLen )
+ nWriteSize -= nCurBufLen;
+ else
+ nCurBufLen = nWriteSize;
+ nCount = rStream.ReadBytes( pBuf.get(), nCurBufLen );
+ WriteBytes( pBuf.get(), nCount );
+ }
+ while( nWriteSize && nCount == nCurBufLen );
+
+ return nSize - nWriteSize;
+}
+
OUString SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet )
{
// read UTF-16 string directly from stream ?
More information about the Libreoffice-commits
mailing list