summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2021-03-17 17:30:52 +0100
committerMiklos Vajna <vmiklos@collabora.com>2021-03-18 11:53:56 +0100
commit42d20c2ab73615a8b43957b9f0203bbe9e879d3d (patch)
treef73ed352b942266d10d68aeb46640d7e6d0bb890
parent92471550b8c43d8ff0cef8b414884d697edf9e63 (diff)
sw reqif-xhtml export: make sure OLE1 preview is WMF-only
reqif-xhtml has previews for embedded objects at 4 levels: - png preview - RTF preview - OLE1 preview - OLE2 preview The OLE1 preview has to be a WMF one, and in case our WMF export tries to inject EMF into it, Word will refuse to open the embedded object. So add a new flag to allow opting out of the EMF embedding for reqif-xhtml export purposes. The other option would be what Word does to just omit the OLE1 preview, but then this would break reqif-xhtml consumers who take the preview from the OLE1 data. (cherry picked from commit 5c7255d3a98568a2965f840b76371cf03eb0d99a) Change-Id: Ia8d4626aefb6309743c9f4023f289c9a7b872035
-rw-r--r--sw/qa/extras/htmlexport/data/ole1-pres-data-wmf.odtbin0 -> 41595 bytes
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx93
-rw-r--r--sw/source/filter/html/htmlreqifreader.cxx11
-rw-r--r--vcl/source/filter/wmf/wmfwr.cxx8
4 files changed, 80 insertions, 32 deletions
diff --git a/sw/qa/extras/htmlexport/data/ole1-pres-data-wmf.odt b/sw/qa/extras/htmlexport/data/ole1-pres-data-wmf.odt
new file mode 100644
index 000000000000..9bcca729bc52
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/ole1-pres-data-wmf.odt
Binary files differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index e2a7e5eb6a60..6fdf15730dde 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -109,6 +109,43 @@ bool TestReqIfRtfReader::WriteObjectData(SvStream& rOLE)
rOLE.WriteStream(aStream);
return true;
}
+
+/// Parser for [MS-OLEDS] 2.2.5 EmbeddedObject, aka OLE1.
+struct OLE1Reader
+{
+ sal_uInt32 m_nNativeDataSize;
+ sal_uInt32 m_nPresentationDataSize;
+
+ OLE1Reader(SvStream& rStream);
+};
+
+OLE1Reader::OLE1Reader(SvStream& rStream)
+{
+ // Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
+ rStream.Seek(0);
+ sal_uInt32 nData;
+ rStream.ReadUInt32(nData); // OLEVersion
+ rStream.ReadUInt32(nData); // FormatID
+ rStream.ReadUInt32(nData); // ClassName
+ rStream.SeekRel(nData);
+ rStream.ReadUInt32(nData); // TopicName
+ rStream.SeekRel(nData);
+ rStream.ReadUInt32(nData); // ItemName
+ rStream.SeekRel(nData);
+
+ rStream.ReadUInt32(m_nNativeDataSize);
+ rStream.SeekRel(m_nNativeDataSize);
+
+ rStream.ReadUInt32(nData); // OLEVersion for presentation data
+ CPPUNIT_ASSERT(rStream.good());
+ rStream.ReadUInt32(nData); // FormatID
+ rStream.ReadUInt32(nData); // ClassName
+ rStream.SeekRel(nData);
+ rStream.ReadUInt32(nData); // Width
+ rStream.ReadUInt32(nData); // Height
+ rStream.ReadUInt32(nData); // PresentationDataSize
+ m_nPresentationDataSize = nData;
+}
}
class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
@@ -1024,25 +1061,14 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PDF)
ParseOle1FromRtfUrl(aRtfUrl, aOle1);
// 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
+ OLE1Reader aOle1Reader(aOle1);
// 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_ASSERT_EQUAL(static_cast<sal_uInt32>(0x99ed), aOle1Reader.m_nNativeDataSize);
// Now import this back and check the ODT result.
mxComponent->dispose();
@@ -1228,26 +1254,33 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PresDataNoOle2)
ParseOle1FromRtfUrl(aRtfUrl, aOle1);
// 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
- aOle1.SeekRel(nData);
-
- aOle1.ReadUInt32(nData); // OLEVersion for presentation data
-
// Without the accompanying fix in place, this test would have failed as there was no
// presentation data after the native data in the OLE1 container. The result was not editable in
// Word.
- CPPUNIT_ASSERT(aOle1.good());
+ OLE1Reader aOle1Reader(aOle1);
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PresDataWmfOnly)
+{
+ // Save to reqif-xhtml.
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "ole1-pres-data-wmf.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);
+ OUString aRtfUrl = GetOlePath();
+ SvMemoryStream aOle1;
+ ParseOle1FromRtfUrl(aRtfUrl, aOle1);
+
+ OLE1Reader aOle1Reader(aOle1);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 135660
+ // - Actual : 272376
+ // i.e. we wrote some additional EMF data into the WMF output, which broke Word.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(135660), aOle1Reader.m_nPresentationDataSize);
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index 938d71efd5c5..005dd2788640 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -21,6 +21,11 @@
#include <vcl/cvtgrf.hxx>
#include <ndole.hxx>
#include <sal/log.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <vcl/wmf.hxx>
+#include <comphelper/propertyvalue.hxx>
+
+using namespace com::sun::star;
namespace
{
@@ -431,8 +436,10 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode)
SvMemoryStream aGraphicStream;
if (pGraphic)
{
- if (GraphicConverter::Export(aGraphicStream, *pGraphic, ConvertDataFormat::WMF)
- == ERRCODE_NONE)
+ uno::Sequence<beans::PropertyValue> aFilterData
+ = { comphelper::makePropertyValue("EmbedEMF", false) };
+ FilterConfigItem aConfigItem(&aFilterData);
+ if (ConvertGDIMetaFileToWMF(pGraphic->GetGDIMetaFile(), aGraphicStream, &aConfigItem))
{
pPresentationData = static_cast<const sal_uInt8*>(aGraphicStream.GetData());
nPresentationData = aGraphicStream.TellEnd();
diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx
index d9fa0d61ffe1..db51fb760dd1 100644
--- a/vcl/source/filter/wmf/wmfwr.cxx
+++ b/vcl/source/filter/wmf/wmfwr.cxx
@@ -38,6 +38,7 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <memory>
#include <vcl/fontcharmap.hxx>
+#include <comphelper/sequenceashashmap.hxx>
// MS Windows defines
@@ -1691,6 +1692,13 @@ bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
{
xStatusIndicator->start( OUString(), 100 );
}
+
+ comphelper::SequenceAsHashMap aMap(pFConfigItem->GetFilterData());
+ auto it = aMap.find("EmbedEMF");
+ if (it != aMap.end())
+ {
+ it->second >>= bEmbedEMF;
+ }
}
nLastPercent=0;