[Libreoffice-commits] core.git: Branch 'distro/vector/vector-7.0' - emfio/inc emfio/source include/vcl sw/source vcl/qa vcl/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Apr 15 15:58:13 UTC 2021


 emfio/inc/emfreader.hxx                   |    2 ++
 emfio/source/emfuno/xemfparser.cxx        |   19 ++++++++++++++++++-
 emfio/source/reader/emfreader.cxx         |    6 ++++++
 include/vcl/vectorgraphicdata.hxx         |    4 ++++
 include/vcl/wmf.hxx                       |    2 ++
 sw/source/filter/html/htmlreqifreader.cxx |    2 +-
 vcl/qa/cppunit/GraphicTest.cxx            |   26 ++++++++++++++++++++++++++
 vcl/source/filter/graphicfilter.cxx       |    2 +-
 vcl/source/filter/wmf/wmf.cxx             |   29 ++++++++++++++++++++++++++++-
 vcl/source/gdi/vectorgraphicdata.cxx      |   11 +++++++++++
 10 files changed, 99 insertions(+), 4 deletions(-)

New commits:
commit 295626a0bd39540544b774094a63df23e5376839
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Dec 9 09:38:48 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Apr 15 17:57:47 2021 +0200

    vcl: improve EMF+ -> WMF conversion
    
    We throw away EMF fallback info when parsing EMF+ data. This means that
    the resulting GDIMetaFile (containing EMF+ data but no EMF fallback) is
    tricky to export to WMF, where EMF+ comments are not allowed.
    
    Improve the conversion result by re-parsing such EMF+ data with EMF+
    disabled, and then converting the GDIMetaFile (containing EMF fallback
    data) to WMF.
    
    (cherry picked from commit ca67839234e78fe6bea21ec39906d1bd71d34d47)
    
    Conflicts:
            emfio/inc/emfreader.hxx
            emfio/source/emfuno/xemfparser.cxx
            include/vcl/vectorgraphicdata.hxx
            vcl/source/gdi/vectorgraphicdata.cxx
    
    Change-Id: Ib2c0388f1344aef7f601ce9be59e4a8924e8085b

diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx
index 90d8969ae70c..6dc9487330cb 100644
--- a/emfio/inc/emfreader.hxx
+++ b/emfio/inc/emfreader.hxx
@@ -32,6 +32,7 @@ namespace emfio
         bool        mbRecordPath : 1;
         bool        mbEMFPlus : 1;
         bool        mbEMFPlusDualMode : 1;
+        bool mbEnableEMFPlus = true;
 
         bool        ReadHeader();
         // reads and converts the rectangle
@@ -43,6 +44,7 @@ namespace emfio
 
         bool ReadEnhWMF();
         void ReadGDIComment(sal_uInt32 nCommentId);
+        void SetEnableEMFPlus(bool bEnableEMFPlus) { mbEnableEMFPlus = bEnableEMFPlus; }
 
     private:
         template <class T> void ReadAndDrawPolyPolygon(sal_uInt32 nNextPos);
diff --git a/emfio/source/emfuno/xemfparser.cxx b/emfio/source/emfuno/xemfparser.cxx
index 3297dea8f30a..0fd49da1c097 100644
--- a/emfio/source/emfuno/xemfparser.cxx
+++ b/emfio/source/emfuno/xemfparser.cxx
@@ -32,6 +32,7 @@
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <unotools/ucbstreamhelper.hxx>
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <comphelper/sequenceashashmap.hxx>
 
 #include <wmfreader.hxx>
 #include <emfreader.hxx>
@@ -109,6 +110,17 @@ namespace emfio::emfreader
             {
                 WmfExternal aExternalHeader;
                 const bool bExternalHeaderUsed(aExternalHeader.setSequence(rProperties));
+                bool bEnableEMFPlus = true;
+                comphelper::SequenceAsHashMap aMap(rProperties);
+                auto it = aMap.find("EMFPlusEnable");
+                if (it != aMap.end())
+                {
+                    bool bValue;
+                    if (it->second >>= bValue)
+                    {
+                        bEnableEMFPlus = bValue;
+                    }
+                }
 
                 // rough check - import and conv to primitive
                 GDIMetaFile aMtf;
@@ -130,7 +142,12 @@ namespace emfio::emfreader
                     if (nMetaType == 0x464d4520)
                     {
                         // read and get possible failure/error, ReadEnhWMF returns success
-                        bReadError = !emfio::EmfReader(*pStream, aMtf).ReadEnhWMF();
+                        emfio::EmfReader aReader(*pStream, aMtf);
+                        if (!bEnableEMFPlus)
+                        {
+                            aReader.SetEnableEMFPlus(bEnableEMFPlus);
+                        }
+                        bReadError = !aReader.ReadEnhWMF();
                     }
                     else
                     {
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index c9dd15bc1879..56349bf0774c 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -728,6 +728,12 @@ namespace emfio
         OUString aEMFPlusDisable;
         rtl::Bootstrap::get("EMF_PLUS_DISABLE", aEMFPlusDisable);
         bool bEnableEMFPlus = aEMFPlusDisable.isEmpty();
+        if (!mbEnableEMFPlus)
+        {
+            // EMF+ is enabled if neither the bootstrap variable, not the member variable disables
+            // it.
+            bEnableEMFPlus = mbEnableEMFPlus;
+        }
 
         SAL_INFO("emfio", "EMF_PLUS_DISABLE is " << (bEnableEMFPlus ? "enabled" : "disabled"));
 
diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx
index 8fce6666e6e8..9151a3425197 100644
--- a/include/vcl/vectorgraphicdata.hxx
+++ b/include/vcl/vectorgraphicdata.hxx
@@ -74,6 +74,8 @@ private:
     // If the vector format has more pages this denotes which page to render
     sal_Int32 mnPageIndex;
 
+    bool mbEnableEMFPlus = true;
+
     // on demand creators
     void ensurePdfReplacement();
     void ensureReplacement();
@@ -113,6 +115,8 @@ public:
 
     sal_Int32 getPageIndex() const { return std::max(sal_Int32(0), mnPageIndex); }
 
+    void setEnableEMFPlus(bool bEnableEMFPlus) { mbEnableEMFPlus = bEnableEMFPlus; }
+
     bool isPrimitiveSequenceCreated() const { return mbSequenceCreated; }
 };
 
diff --git a/include/vcl/wmf.hxx b/include/vcl/wmf.hxx
index 26a1c734425d..4acc21465723 100644
--- a/include/vcl/wmf.hxx
+++ b/include/vcl/wmf.hxx
@@ -25,10 +25,12 @@
 class FilterConfigItem;
 class GDIMetaFile;
 class SvStream;
+class Graphic;
 
 VCL_DLLPUBLIC bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF );
 
 VCL_DLLPUBLIC bool ConvertGDIMetaFileToWMF( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem const * pConfigItem, bool bPlaceable = true );
+VCL_DLLPUBLIC bool ConvertGraphicToWMF( const Graphic & rGraphic, SvStream & rTargetStream, FilterConfigItem const * pConfigItem, bool bPlaceable = true );
 
 bool ConvertGDIMetaFileToEMF(const GDIMetaFile & rMTF, SvStream & rTargetStream);
 
diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx
index 6488f32ad578..3aa3de435b11 100644
--- a/sw/source/filter/html/htmlreqifreader.cxx
+++ b/sw/source/filter/html/htmlreqifreader.cxx
@@ -448,7 +448,7 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode)
         uno::Sequence<beans::PropertyValue> aFilterData
             = { comphelper::makePropertyValue("EmbedEMF", false) };
         FilterConfigItem aConfigItem(&aFilterData);
-        if (ConvertGDIMetaFileToWMF(pGraphic->GetGDIMetaFile(), aGraphicStream, &aConfigItem))
+        if (ConvertGraphicToWMF(*pGraphic, aGraphicStream, &aConfigItem))
         {
             pPresentationData = static_cast<const sal_uInt8*>(aGraphicStream.GetData());
             nPresentationData = aGraphicStream.TellEnd();
diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx
index 4c082a10d21c..acabc316bc4b 100644
--- a/vcl/qa/cppunit/GraphicTest.cxx
+++ b/vcl/qa/cppunit/GraphicTest.cxx
@@ -26,6 +26,7 @@
 #include <unotools/ucbstreamhelper.hxx>
 #include <unotools/tempfile.hxx>
 #include <vcl/cvtgrf.hxx>
+#include <vcl/metaact.hxx>
 
 #include <impgraph.hxx>
 #include <graphic/GraphicFormatDetector.hxx>
@@ -332,6 +333,31 @@ void GraphicTest::testEmfToWmfConversion()
     // - Actual  : EMF
     // i.e. EMF data was requested to be converted to WMF, but the output was still EMF.
     CPPUNIT_ASSERT_EQUAL(OUString("WMF"), aDetector.msDetectedFormat);
+
+    // Import the WMF result and check for traces of EMF+ in it.
+    Graphic aWmfGraphic;
+    aGraphicStream.Seek(0);
+    CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, aGraphicFilter.ImportGraphic(aWmfGraphic, OUString(),
+                                                                    aGraphicStream, nFormat));
+    int nCommentCount = 0;
+    for (size_t i = 0; i < aWmfGraphic.GetGDIMetaFile().GetActionSize(); ++i)
+    {
+        MetaAction* pAction = aWmfGraphic.GetGDIMetaFile().GetAction(i);
+        if (pAction->GetType() == MetaActionType::COMMENT)
+        {
+            auto pComment = static_cast<MetaCommentAction*>(pAction);
+            if (pComment->GetComment().startsWith("EMF_PLUS"))
+            {
+                ++nCommentCount;
+            }
+        }
+    }
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected less or equal than: 4
+    // - Actual  : 8
+    // i.e. even more EMF+ comments were left in the WMF output. The ideal would be to get this down
+    // to 0, though.
+    CPPUNIT_ASSERT_LESSEQUAL(4, nCommentCount);
 }
 
 void GraphicTest::testSwapping()
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index b4763831105b..a95bfff363c3 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -1951,7 +1951,7 @@ ErrCode GraphicFilter::ExportGraphic( const Graphic& rGraphic, const OUString& r
                 if (!bDone)
                 {
                     // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
-                    if (!ConvertGDIMetaFileToWMF(aGraphic.GetGDIMetaFile(), rOStm, &aConfigItem))
+                    if (!ConvertGraphicToWMF(aGraphic, rOStm, &aConfigItem))
                         nStatus = ERRCODE_GRFILTER_FORMATERROR;
 
                     if (rOStm.GetError())
diff --git a/vcl/source/filter/wmf/wmf.cxx b/vcl/source/filter/wmf/wmf.cxx
index 7818309ed6d1..8a04bc1d3025 100644
--- a/vcl/source/filter/wmf/wmf.cxx
+++ b/vcl/source/filter/wmf/wmf.cxx
@@ -23,6 +23,8 @@
 #include <vcl/gdimetafiletools.hxx>
 #include <vcl/graph.hxx>
 
+using namespace com::sun::star;
+
 bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF )
 {
     // tdf#111484 Use new method to import Metafile. Take current StreamPos
@@ -80,7 +82,32 @@ bool ConvertGDIMetaFileToWMF( const GDIMetaFile & rMTF, SvStream & rTargetStream
         clipMetafileContentAgainstOwnRegions(aGdiMetaFile);
     }
 
-    return aWMFWriter.WriteWMF( aGdiMetaFile, rTargetStream, pConfigItem, bPlaceable );
+    bool bRet = aWMFWriter.WriteWMF(aGdiMetaFile, rTargetStream, pConfigItem, bPlaceable);
+    return bRet;
+}
+
+bool ConvertGraphicToWMF(const Graphic& rGraphic, SvStream& rTargetStream,
+                         FilterConfigItem const* pConfigItem, bool bPlaceable)
+{
+    GfxLink aLink = rGraphic.GetGfxLink();
+    if (aLink.IsEMF() && 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.
+        uno::Sequence<sal_Int8> aData(reinterpret_cast<const sal_Int8*>(aLink.GetData()),
+                                      aLink.GetDataSize());
+        auto aVectorGraphicData
+            = std::make_shared<VectorGraphicData>(aData, OUString(), VectorGraphicDataType::Emf);
+        aVectorGraphicData->setEnableEMFPlus(false);
+        Graphic aGraphic(aVectorGraphicData);
+        bool bRet = ConvertGDIMetaFileToWMF(aGraphic.GetGDIMetaFile(), rTargetStream, pConfigItem,
+                                            bPlaceable);
+        return bRet;
+    }
+
+    bool bRet = ConvertGDIMetaFileToWMF(rGraphic.GetGDIMetaFile(), rTargetStream, pConfigItem,
+                                        bPlaceable);
+    return bRet;
 }
 
 bool ConvertGDIMetaFileToEMF(const GDIMetaFile & rMTF, SvStream & rTargetStream)
diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx
index 99e51f65cc71..fe9ca5535e6e 100644
--- a/vcl/source/gdi/vectorgraphicdata.cxx
+++ b/vcl/source/gdi/vectorgraphicdata.cxx
@@ -34,6 +34,7 @@
 #include <comphelper/seqstream.hxx>
 #include <comphelper/sequence.hxx>
 #include <comphelper/propertysequence.hxx>
+#include <comphelper/propertyvalue.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/outdev.hxx>
 #include <vcl/wmfexternal.hxx>
@@ -209,6 +210,16 @@ void VectorGraphicData::ensureSequenceAndRange()
                     aSequence = mpExternalHeader->getSequence();
                 }
 
+                if (!mbEnableEMFPlus)
+                {
+                    auto aVector
+                        = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>(
+                            aSequence);
+                    aVector.push_back(
+                        comphelper::makePropertyValue("EMFPlusEnable", uno::makeAny(false)));
+                    aSequence = comphelper::containerToSequence(aVector);
+                }
+
                 if (myInputStream.is())
                     maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence));
 


More information about the Libreoffice-commits mailing list