[Libreoffice-commits] core.git: emfio/inc emfio/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Sep 17 15:22:22 UTC 2020


 emfio/inc/emfreader.hxx           |    4 +
 emfio/source/reader/emfreader.cxx |   86 ++++++++++++++++++++++++++++++++++----
 2 files changed, 82 insertions(+), 8 deletions(-)

New commits:
commit d75c5b38911557173c54a78f42ff220ab3918573
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Sep 17 13:21:52 2020 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Sep 17 17:21:44 2020 +0200

    tdf#136836 emfio: speed up import of EMF import when the orig PDF is available
    
    The PPTX bugdoc has a 17MB EMF file, which has enough instructions to
    keep Impress busy for minutes during import.
    
    Take advantage of the detail that this EMF has a
    EMR_COMMENT_MULTIFORMATS record that contains the original PDF, which
    can be rendered much faster:
    
    - old cost: 122.153 seconds
    - new cost: 1.952 seconds (1.6% of baseline)
    
    Change-Id: I38efc1c24e21a7622377b9e1c1938ebee826bae9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102918
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx
index 90d8969ae70c..75a77211ea61 100644
--- a/emfio/inc/emfreader.hxx
+++ b/emfio/inc/emfreader.hxx
@@ -32,6 +32,8 @@ namespace emfio
         bool        mbRecordPath : 1;
         bool        mbEMFPlus : 1;
         bool        mbEMFPlusDualMode : 1;
+        /// An other format is read already, can ignore actual EMF data.
+        bool mbReadOtherGraphicFormat = false;
 
         bool        ReadHeader();
         // reads and converts the rectangle
@@ -43,6 +45,8 @@ namespace emfio
 
         bool ReadEnhWMF();
         void ReadGDIComment(sal_uInt32 nCommentId);
+        /// Parses EMR_COMMENT_MULTIFORMATS.
+        void ReadMultiformatsComment();
 
     private:
         template <class T> void ReadAndDrawPolyPolygon(sal_uInt32 nNextPos);
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index 8c128d2965c6..7bb4d408203a 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -24,6 +24,8 @@
 #include <o3tl/safeint.hxx>
 #include <tools/stream.hxx>
 #include <memory>
+#include <vcl/graph.hxx>
+#include <vcl/pdfread.hxx>
 
 #ifdef DBG_UTIL
 #include <vcl/pngwrite.hxx>
@@ -163,6 +165,8 @@ using namespace std;
 #define EMR_SETLINKEDUFIS              119
 #define EMR_SETTEXTJUSTIFICATION       120
 
+#define PDF_SIGNATURE 0x50444620 // "PDF "
+
 namespace
 {
 
@@ -381,16 +385,13 @@ namespace emfio
     {
     }
 
-#if OSL_DEBUG_LEVEL > 0
     const sal_uInt32 EMR_COMMENT_BEGINGROUP = 0x00000002;
     const sal_uInt32 EMR_COMMENT_ENDGROUP = 0x00000003;
     const sal_uInt32 EMR_COMMENT_MULTIFORMATS = 0x40000004;
     const sal_uInt32 EMR_COMMENT_WINDOWS_METAFILE = 0x80000001;
-#endif
 
     void EmfReader::ReadGDIComment(sal_uInt32 nCommentId)
     {
-#if OSL_DEBUG_LEVEL > 0
         sal_uInt32 nPublicCommentIdentifier;
         mpInputStream->ReadUInt32(nPublicCommentIdentifier);
 
@@ -433,7 +434,7 @@ namespace emfio
                 break;
 
             case EMR_COMMENT_MULTIFORMATS:
-                SAL_WARN("emfio", "\t\tEMR_COMMENT_MULTIFORMATS not implemented");
+                ReadMultiformatsComment();
                 break;
 
             case EMR_COMMENT_WINDOWS_METAFILE:
@@ -444,9 +445,78 @@ namespace emfio
                 SAL_WARN("emfio", "\t\tEMR_COMMENT_PUBLIC not implemented, id: 0x" << std::hex << nCommentId << std::dec);
                 break;
         }
-#else
-        (void) nCommentId;
-#endif
+    }
+
+    void EmfReader::ReadMultiformatsComment()
+    {
+        tools::Rectangle aOutputRect = EmfReader::ReadRectangle();
+
+        sal_uInt32 nCountFormats;
+        mpInputStream->ReadUInt32(nCountFormats);
+        if (nCountFormats < 1)
+        {
+            return;
+        }
+
+        // Read the first EmrFormat.
+        sal_uInt32 nSignature;
+        mpInputStream->ReadUInt32(nSignature);
+        if (nSignature != PDF_SIGNATURE)
+        {
+            return;
+        }
+
+        sal_uInt32 nVersion;
+        mpInputStream->ReadUInt32(nVersion);
+        if (nVersion != 1)
+        {
+            return;
+        }
+
+        sal_uInt32 nSizeData;
+        mpInputStream->ReadUInt32(nSizeData);
+        if (!nSizeData || nSizeData > mpInputStream->remainingSize())
+        {
+            return;
+        }
+
+        sal_uInt32 nOffData;
+        mpInputStream->ReadUInt32(nOffData);
+        if (!nOffData)
+        {
+            return;
+        }
+
+        std::vector<char> aPdfData(nSizeData);
+        mpInputStream->ReadBytes(aPdfData.data(), aPdfData.size());
+        if (!mpInputStream->good())
+        {
+            return;
+        }
+
+        SvMemoryStream aPdfStream;
+        aPdfStream.WriteBytes(aPdfData.data(), aPdfData.size());
+        aPdfStream.Seek(0);
+        Graphic aGraphic;
+        if (!vcl::ImportPDF(aPdfStream, aGraphic))
+        {
+            return;
+        }
+
+        maBmpSaveList.emplace_back(new BSaveStruct(aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY));
+        const std::shared_ptr<VectorGraphicData> pVectorGraphicData
+            = aGraphic.getVectorGraphicData();
+        if (!pVectorGraphicData)
+        {
+            return;
+        }
+
+        if (pVectorGraphicData->getVectorGraphicDataType() != VectorGraphicDataType::Pdf)
+        {
+            return;
+        }
+
+        mbReadOtherGraphicFormat = true;
     }
 
     void EmfReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC)
@@ -728,7 +798,7 @@ namespace emfio
 
         SAL_INFO("emfio", "EMF_PLUS_DISABLE is " << (bEnableEMFPlus ? "enabled" : "disabled"));
 
-        while( bStatus && mnRecordCount-- && mpInputStream->good())
+        while (bStatus && mnRecordCount-- && mpInputStream->good() && !mbReadOtherGraphicFormat)
         {
             sal_uInt32  nRecType(0), nRecSize(0);
             mpInputStream->ReadUInt32(nRecType).ReadUInt32(nRecSize);


More information about the Libreoffice-commits mailing list