vcl/source/filter/graphicfilter2.cxx |   64 ++++++++++++++++++++++++++++++++---
 1 file changed, 60 insertions(+), 4 deletions(-)

New commits:
commit 063d641f023ac90f49116de105e32e38be72a1af
Author:     offtkp <parisop...@gmail.com>
AuthorDate: Sat May 21 11:23:01 2022 +0300
Commit:     Bartosz Kosiorek <gan...@poczta.onet.pl>
CommitDate: Tue May 24 08:19:41 2022 +0200

    tdf#149206 Set size correctly when loading EMF
    
    Regression fixed, rolled back ImpDetectEMF function
    to version before https://gerrit.libreoffice.org/c/core/+/132456,
    changed type detection from extension checking back to
    magic number checking. Also added a small uncompression
    at the start to keep EMZ support.
    
    Change-Id: Id4489da399a571c4c72ce137f841614f5c0d7bdc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134703
    Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl>
    Tested-by: Jenkins

diff --git a/vcl/source/filter/graphicfilter2.cxx 
b/vcl/source/filter/graphicfilter2.cxx
index eaef61b1d1e1..c02e9d557c44 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -21,6 +21,7 @@
 #include <tools/stream.hxx>
 #include <tools/fract.hxx>
 #include <tools/urlobj.hxx>
+#include <tools/zcodec.hxx>
 #include <vcl/TypeSerializer.hxx>
 #include <vcl/outdev.hxx>
 #include <vcl/graphicfilter.hxx>
@@ -29,6 +30,9 @@
 #include "graphicfilter_internal.hxx"
 
 #define DATA_SIZE           640
+constexpr sal_uInt32 EMF_CHECK_SIZE    = 44;
+constexpr sal_uInt32 EMR_HEADER        = 0x00000001;
+constexpr sal_uInt32 ENHMETA_SIGNATURE = 0x464d4520;
 
 GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
     pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( 
INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ).release() ),
@@ -1086,12 +1090,64 @@ bool GraphicDescriptor::ImpDetectWMF( SvStream&, bool )
     return bRet;
 }
 
-bool GraphicDescriptor::ImpDetectEMF( SvStream&, bool )
+bool GraphicDescriptor::ImpDetectEMF(SvStream& rStm, bool bExtendedInfo)
 {
-    bool bRet = aPathExt.startsWith( "emf" ) || aPathExt.startsWith( "emz" );
-    if (bRet)
-        nFormat = GraphicFileFormat::EMF;
+    SvStream* aNewStream = &rStm;
+    SvMemoryStream aMemStream;
+    sal_uInt8 aUncompressedBuffer[EMF_CHECK_SIZE];
+    if (ZCodec::IsZCompressed(rStm))
+    {
+        ZCodec aCodec;
+        aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/ true);
+        auto nDecompressLength = aCodec.Read(rStm, aUncompressedBuffer, 
EMF_CHECK_SIZE);
+        aCodec.EndCompression();
+        if (nDecompressLength != EMF_CHECK_SIZE)
+            return false;
+        aMemStream.SetBuffer(aUncompressedBuffer, EMF_CHECK_SIZE, 
EMF_CHECK_SIZE);
+        aNewStream = &aMemStream;
+    }
+
+    sal_uInt32 nRecordType = 0;
+    bool bRet = false;
+    sal_Int32 nStmPos = aNewStream->Tell();
+    aNewStream->SetEndian(SvStreamEndian::LITTLE);
+    aNewStream->ReadUInt32(nRecordType);
+    if (nRecordType == EMR_HEADER)
+    {
+        sal_Int32 nBoundLeft = 0, nBoundTop = 0, nBoundRight = 0, nBoundBottom 
= 0;
+        sal_Int32 nFrameLeft = 0, nFrameTop = 0, nFrameRight = 0, nFrameBottom 
= 0;
+        sal_uInt32 nSignature = 0;
+
+        aNewStream->SeekRel(4);
+        aNewStream->ReadInt32(nBoundLeft);
+        aNewStream->ReadInt32(nBoundTop);
+        aNewStream->ReadInt32(nBoundRight);
+        aNewStream->ReadInt32(nBoundBottom);
+        aNewStream->ReadInt32(nFrameLeft);
+        aNewStream->ReadInt32(nFrameTop);
+        aNewStream->ReadInt32(nFrameRight);
+        aNewStream->ReadInt32(nFrameBottom);
+        aNewStream->ReadUInt32(nSignature);
+
+        if (nSignature == ENHMETA_SIGNATURE)
+        {
+            nFormat = GraphicFileFormat::EMF;
+            bRet = true;
+
+            if (bExtendedInfo)
+            {
+                // size in pixels
+                aPixSize.setWidth(nBoundRight - nBoundLeft + 1);
+                aPixSize.setHeight(nBoundBottom - nBoundTop + 1);
+
+                // size in 0.01mm units
+                aLogSize.setWidth(nFrameRight - nFrameLeft + 1);
+                aLogSize.setHeight(nFrameBottom - nFrameTop + 1);
+            }
+        }
+    }
 
+    rStm.Seek(nStmPos);
     return bRet;
 }
 

Reply via email to