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

Reply via email to