emfio/inc/wmfreader.hxx | 5 + emfio/source/emfuno/xemfparser.cxx | 5 + emfio/source/reader/emfreader.cxx | 2 emfio/source/reader/wmfreader.cxx | 1 vcl/qa/cppunit/GraphicTest.cxx | 81 +++++++++++++++++++++++++++ vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf |binary vcl/source/filter/wmf/wmf.cxx | 12 ++-- 7 files changed, 100 insertions(+), 6 deletions(-)
New commits: commit 1193a0bb63ab3cc3601b4afcbbf095ef91202da6 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Fri Jun 11 15:51:32 2021 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Jun 15 17:55:43 2021 +0200 when converting WMF to WMF, simply do a direct copy Actually, if we have the graphics data, just copy the graphics data, that'll keep both the EMF+ and non-EMF+ content. Change-Id: Ia14df0ba2a94d4310ee745b49de1d2190e425f05 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117063 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> (cherry picked from commit 6b349bcc32336664a31deed3f4463e40dd028f63) diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx index acabc316bc4b..e4a1f9b53f81 100644 --- a/vcl/qa/cppunit/GraphicTest.cxx +++ b/vcl/qa/cppunit/GraphicTest.cxx @@ -27,6 +27,7 @@ #include <unotools/tempfile.hxx> #include <vcl/cvtgrf.hxx> #include <vcl/metaact.hxx> +#include <vcl/wmf.hxx> #include <impgraph.hxx> #include <graphic/GraphicFormatDetector.hxx> @@ -53,6 +54,7 @@ private: void testSwapping(); void testSwappingVectorGraphic(); void testWMFRoundtrip(); + void testWMFWithEmfPlusRoundtrip(); void testEmfToWmfConversion(); CPPUNIT_TEST_SUITE(GraphicTest); @@ -64,6 +66,7 @@ private: CPPUNIT_TEST(testSwapping); CPPUNIT_TEST(testSwappingVectorGraphic); CPPUNIT_TEST(testWMFRoundtrip); + CPPUNIT_TEST(testWMFWithEmfPlusRoundtrip); CPPUNIT_TEST(testEmfToWmfConversion); CPPUNIT_TEST_SUITE_END(); }; @@ -303,6 +306,84 @@ void GraphicTest::testUnloadedGraphicSizeUnit() CPPUNIT_ASSERT_EQUAL(Size(400, 363), aGraphic.GetPrefSize()); } +int getEmfPlusActionsCount(const Graphic& graphic) +{ + const GDIMetaFile& metafile = graphic.GetGDIMetaFile(); + int emfPlusCount = 0; + for (size_t i = 0; i < metafile.GetActionSize(); ++i) + { + MetaAction* action = metafile.GetAction(i); + if (action->GetType() == MetaActionType::COMMENT) + { + const MetaCommentAction* commentAction = static_cast<const MetaCommentAction*>(action); + if (commentAction->GetComment() == "EMF_PLUS") + ++emfPlusCount; + } + } + return emfPlusCount; +} + +int getPolygonActionsCount(const Graphic& graphic) +{ + const GDIMetaFile& metafile = graphic.GetGDIMetaFile(); + int polygonCount = 0; + for (size_t i = 0; i < metafile.GetActionSize(); ++i) + { + MetaAction* action = metafile.GetAction(i); + if (action->GetType() == MetaActionType::POLYGON) + ++polygonCount; + } + return polygonCount; +} + +void GraphicTest::testWMFWithEmfPlusRoundtrip() +{ + // Load a WMF file. + test::Directories aDirectories; + OUString aURL = aDirectories.getURLFromSrc(u"vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf"); + SvFileStream aStream(aURL, StreamMode::READ); + sal_uInt64 nExpectedSize = aStream.TellEnd(); + GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream); + + CPPUNIT_ASSERT_GREATER(0, getEmfPlusActionsCount(aGraphic)); + CPPUNIT_ASSERT_EQUAL(0, getPolygonActionsCount(aGraphic)); + + for (bool useConvertMetafile : { false, true }) + { + // Save as WMF. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + SvStream& rOutStream = *aTempFile.GetStream(StreamMode::READWRITE); + if (useConvertMetafile) + ConvertGraphicToWMF(aGraphic, rOutStream, nullptr); + else + { + sal_uInt16 nFormat = rGraphicFilter.GetExportFormatNumberForShortName(u"WMF"); + rGraphicFilter.ExportGraphic(aGraphic, OUString(), rOutStream, nFormat); + } + CPPUNIT_ASSERT_EQUAL(nExpectedSize, rOutStream.TellEnd()); + + rOutStream.Seek(0); + Graphic aNewGraphic = rGraphicFilter.ImportUnloadedGraphic(rOutStream); + // Check that reading the WMF back preserves the EMF+ actions in it. + CPPUNIT_ASSERT_GREATER(0, getEmfPlusActionsCount(aNewGraphic)); + // EmfReader::ReadEnhWMF() drops non-EMF+ drawing actions if EMF+ is found. + CPPUNIT_ASSERT_EQUAL(0, getPolygonActionsCount(aNewGraphic)); + + // With EMF+ disabled there should be no EMF+ actions. + const GfxLink& rLink = aNewGraphic.GetGfxLink(); + uno::Sequence<sal_Int8> aData(reinterpret_cast<const sal_Int8*>(rLink.GetData()), + rLink.GetDataSize()); + auto aVectorGraphicData + = std::make_shared<VectorGraphicData>(aData, OUString(), VectorGraphicDataType::Wmf); + aVectorGraphicData->setEnableEMFPlus(false); + Graphic aNoEmfPlusGraphic(aVectorGraphicData); + CPPUNIT_ASSERT_EQUAL(0, getEmfPlusActionsCount(aNoEmfPlusGraphic)); + CPPUNIT_ASSERT_GREATER(0, getPolygonActionsCount(aNoEmfPlusGraphic)); + } +} + void GraphicTest::testEmfToWmfConversion() { // Load EMF data. diff --git a/vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf b/vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf new file mode 100644 index 000000000000..1e7f75b19809 Binary files /dev/null and b/vcl/qa/cppunit/data/wmf-embedded-emfplus.wmf differ diff --git a/vcl/source/filter/wmf/wmf.cxx b/vcl/source/filter/wmf/wmf.cxx index 17e7634bd756..b729f7a5ec88 100644 --- a/vcl/source/filter/wmf/wmf.cxx +++ b/vcl/source/filter/wmf/wmf.cxx @@ -92,6 +92,8 @@ bool ConvertGraphicToWMF(const Graphic& rGraphic, SvStream& rTargetStream, GfxLink aLink = rGraphic.GetGfxLink(); if (aLink.GetType() == GfxLinkType::NativeWmf && aLink.GetData() && aLink.GetDataSize()) { + if(!aLink.IsEMF()) // If WMF, just write directly. + return rTargetStream.WriteBytes(aLink.GetData(), aLink.GetDataSize()) == aLink.GetDataSize(); // This may be an EMF+ file or WMF file with EMF+ embedded. In EmfReader::ReadEnhWMF() // we normally drop non-EMF commands when reading EMF+, so converting that to WMF // is better done by re-parsing with EMF+ disabled. commit e47ab1464692c5130e19db5a027d694ea5b8c12a Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Fri Jun 11 15:48:32 2021 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Jun 15 17:55:00 2021 +0200 drop EMF+ also when converting WMF, not just EMF A WMF may have EMF with EMF+ actions embedded. When we read that, we drop drawing non-EMF+ actions if we use EMF+. But EMF+ actions are stored as MetaCommentAction in the metafile, and WMF writer (unlike EMF) writer simply ignores comments. So when writing WMF, make sure to read non-EMF actions so that something is written. This is an extension of 295626a0bd39540544b774094a63df23e5376839. Change-Id: I37355f694fe656b661abe54274ea203934e68151 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117062 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> (cherry picked from commit b342a445cd8b115e76d261860088b012b74c0b0e) diff --git a/emfio/inc/wmfreader.hxx b/emfio/inc/wmfreader.hxx index 9e1059d63760..85b7c9f0b604 100644 --- a/emfio/inc/wmfreader.hxx +++ b/emfio/inc/wmfreader.hxx @@ -51,6 +51,8 @@ namespace emfio // eventually handed over external header const WmfExternal* mpExternalHeader; + bool mbEnableEMFPlus = true; + // reads header of the WMF-Datei bool ReadHeader(); @@ -68,6 +70,9 @@ namespace emfio // read WMF file from stream and fill the GDIMetaFile void ReadWMF(); + + // Allows disabling EMF+ if EMF is embedded in this WMF. + void SetEnableEMFPlus(bool bEnableEMFPlus) { mbEnableEMFPlus = bEnableEMFPlus; } }; } diff --git a/emfio/source/emfuno/xemfparser.cxx b/emfio/source/emfuno/xemfparser.cxx index 0fd49da1c097..dd5277a7941c 100644 --- a/emfio/source/emfuno/xemfparser.cxx +++ b/emfio/source/emfuno/xemfparser.cxx @@ -151,7 +151,10 @@ namespace emfio::emfreader } else { - emfio::WmfReader(*pStream, aMtf, bExternalHeaderUsed ? &aExternalHeader : nullptr).ReadWMF(); + emfio::WmfReader aReader(*pStream, aMtf, bExternalHeaderUsed ? &aExternalHeader : nullptr); + if (!bEnableEMFPlus) + aReader.SetEnableEMFPlus(bEnableEMFPlus); + aReader.ReadWMF(); // Need to check for ErrCode at stream to not lose former work. // This may contain important information and will behave the diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index 56349bf0774c..c32ee1e84041 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -735,7 +735,7 @@ namespace emfio bEnableEMFPlus = mbEnableEMFPlus; } - SAL_INFO("emfio", "EMF_PLUS_DISABLE is " << (bEnableEMFPlus ? "enabled" : "disabled")); + SAL_INFO("emfio", "EMF+ reading is " << (bEnableEMFPlus ? "enabled" : "disabled")); while( bStatus && mnRecordCount-- && mpInputStream->good()) { diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx index aa1c2be7a00e..1a505ae46a3f 100644 --- a/emfio/source/reader/wmfreader.cxx +++ b/emfio/source/reader/wmfreader.cxx @@ -1443,6 +1443,7 @@ namespace emfio GDIMetaFile aMeta; mpEMFStream->Seek( 0 ); std::unique_ptr<EmfReader> pEMFReader(std::make_unique<EmfReader>( *mpEMFStream, aMeta )); + pEMFReader->SetEnableEMFPlus(mbEnableEMFPlus); bEMFAvailable = pEMFReader->ReadEnhWMF(); pEMFReader.reset(); // destroy first!!! diff --git a/vcl/source/filter/wmf/wmf.cxx b/vcl/source/filter/wmf/wmf.cxx index 8a04bc1d3025..17e7634bd756 100644 --- a/vcl/source/filter/wmf/wmf.cxx +++ b/vcl/source/filter/wmf/wmf.cxx @@ -90,14 +90,16 @@ bool ConvertGraphicToWMF(const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem const* pConfigItem, bool bPlaceable) { GfxLink aLink = rGraphic.GetGfxLink(); - if (aLink.IsEMF() && aLink.GetData() && aLink.GetDataSize()) + if (aLink.GetType() == GfxLinkType::NativeWmf && aLink.GetData() && aLink.GetDataSize()) { - // This may be an EMF+ file, converting that to WMF is better done by re-parsing EMF+ as EMF - // and converting that to WMF. + // This may be an EMF+ file or WMF file with EMF+ embedded. In EmfReader::ReadEnhWMF() + // we normally drop non-EMF commands when reading EMF+, so converting that to WMF + // is better done by re-parsing with EMF+ disabled. uno::Sequence<sal_Int8> aData(reinterpret_cast<const sal_Int8*>(aLink.GetData()), aLink.GetDataSize()); auto aVectorGraphicData - = std::make_shared<VectorGraphicData>(aData, OUString(), VectorGraphicDataType::Emf); + = std::make_shared<VectorGraphicData>(aData, OUString(), + aLink.IsEMF() ? VectorGraphicDataType::Emf : VectorGraphicDataType::Wmf); aVectorGraphicData->setEnableEMFPlus(false); Graphic aGraphic(aVectorGraphicData); bool bRet = ConvertGDIMetaFileToWMF(aGraphic.GetGDIMetaFile(), rTargetStream, pConfigItem, _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits