diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2021-03-17 17:30:52 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-03-18 11:53:56 +0100 |
commit | 42d20c2ab73615a8b43957b9f0203bbe9e879d3d (patch) | |
tree | f73ed352b942266d10d68aeb46640d7e6d0bb890 | |
parent | 92471550b8c43d8ff0cef8b414884d697edf9e63 (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.odt | bin | 0 -> 41595 bytes | |||
-rw-r--r-- | sw/qa/extras/htmlexport/htmlexport.cxx | 93 | ||||
-rw-r--r-- | sw/source/filter/html/htmlreqifreader.cxx | 11 | ||||
-rw-r--r-- | vcl/source/filter/wmf/wmfwr.cxx | 8 |
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 Binary files differnew file mode 100644 index 000000000000..9bcca729bc52 --- /dev/null +++ b/sw/qa/extras/htmlexport/data/ole1-pres-data-wmf.odt 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; |