File bsc1135356.diff of Package libreoffice

From 01d29e668865c54da6e8d5a0620ca5c3f5ea7791 Mon Sep 17 00:00:00 2001
From: Miklos Vajna <vmiklos@collabora.com>
Date: Tue, 22 Sep 2020 10:29:23 +0200
Subject: [PATCH] bsc1135356.diff

This is a combination of 4 commits.

This is the 1st commit message:

emfio: extra logging

For emfio I believe we need more logging, so I am gradually adding this.
I decided to log the EMR_COMMENT_PUBLIC record subtypes
EMR_COMMENT_BEGINGROUP and EMR_COMMENT_ENDGROUP.

I honestly don't know what these actually do, but they are specified in
[MS-EMF] 2.3.3.4.1 and 2.3.3.4.2. Later on, we will need to look into
handling EMR_COMMENT_MULTIFORMATS so we can display things with EPS
data. We should also probably look into handling
EMR_COMMENT_WINDOWS_METAFILE later on also.

(cherry picked from commit debb38c7be8015b4de4aace6f8ac78e4ee2fbfa6)

Conflicts:
	emfio/source/reader/emfreader.cxx

This is the commit message #2:

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)

(cherry picked from commit d75c5b38911557173c54a78f42ff220ab3918573)

This is the commit message #3:

fix constants according to [MS-EMF] 2.1.10

(cherry picked from commit 971c4135b3a11cd74a13ac0eb4e3aaae4e7dfefd)

This is the commit message #4:

[API CHANGE] tdf#136836 emfio: set size hint on inner PDF if used as shape fill

The bugdoc has a shape, its bitmap fill is an EMF, which is actually a
PDF. The PDF is has a height of 5cm, but the shape has a height of 14
cm.

Inform vcl::RenderPDFBitmaps() about the size of the shape, so the
result won't be blurry. This approach makes sure that we don't
unconditionally render at higher resolution, i.e. the "load a PDF of 100
pages into Online" use-case won't use more memory than before.

API CHANGE, because the EMF reader is only available via UNO, though
it's likely that no actual external code would ever invoke it directly.

(cherry picked from commit 01024ee24c6e89044c68051f6fd5f1264905e90c)

Conflicts:
        emfio/qa/cppunit/emf/EmfImportTest.cxx
        include/vcl/pdfread.hxx
        include/vcl/vectorgraphicdata.hxx
        vcl/source/gdi/vectorgraphicdata.cxx

Change-Id: If1d8def0136d408a31a0cc54777a7f26430a0ff3
---
 emfio/inc/emfreader.hxx                       |   7 +
 emfio/source/emfuno/xemfparser.cxx            |  15 +-
 emfio/source/reader/emfreader.cxx             | 327 ++++++++++++++----
 emfio/source/reader/mtftools.cxx              |   6 +-
 include/vcl/pdfread.hxx                       |  11 +-
 include/vcl/vectorgraphicdata.hxx             |  10 +
 offapi/com/sun/star/graphic/XEmfParser.idl    |   8 +
 .../sdr/properties/defaultproperties.cxx      |  16 +
 vcl/source/filter/ipdf/pdfread.cxx            |  41 ++-
 vcl/source/gdi/vectorgraphicdata.cxx          |   6 +
 10 files changed, 363 insertions(+), 84 deletions(-)

diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx
index a54eee1a9c70..c6caa0fb9f26 100644
--- a/emfio/inc/emfreader.hxx
+++ b/emfio/inc/emfreader.hxx
@@ -32,6 +32,9 @@ 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;
+        basegfx::B2DTuple maSizeHint;
 
         bool        ReadHeader();
         // reads and converts the rectangle
@@ -42,6 +45,10 @@ namespace emfio
         ~EmfReader();
 
         bool ReadEnhWMF();
+        void ReadGDIComment(sal_uInt32 nCommentId);
+        /// Parses EMR_COMMENT_MULTIFORMATS.
+        void ReadMultiformatsComment();
+        void SetSizeHint(const basegfx::B2DTuple& rSizeHint) { maSizeHint = rSizeHint; }
 
     private:
         template <class T> void ReadAndDrawPolyPolygon(sal_uInt32 nNextPos);
diff --git a/emfio/source/emfuno/xemfparser.cxx b/emfio/source/emfuno/xemfparser.cxx
index f28633a73446..6e43788fcb83 100644
--- a/emfio/source/emfuno/xemfparser.cxx
+++ b/emfio/source/emfuno/xemfparser.cxx
@@ -37,6 +37,7 @@
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <unotools/ucbstreamhelper.hxx>
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <sal/log.hxx>
 
 #include <wmfreader.hxx>
 #include <emfreader.hxx>
@@ -59,6 +60,7 @@ namespace emfio
         {
         private:
             uno::Reference< uno::XComponentContext > context_;
+            basegfx::B2DTuple maSizeHint;
 
         protected:
         public:
@@ -72,6 +74,7 @@ namespace emfio
                 const uno::Reference< ::io::XInputStream >& xEmfStream,
                 const OUString& aAbsolutePath,
                 const uno::Sequence< ::beans::PropertyValue >& rProperties) override;
+            void SAL_CALL setSizeHint(const geometry::RealPoint2D& rSize) override;
 
             // XServiceInfo
             virtual OUString SAL_CALL getImplementationName() override;
@@ -145,7 +148,9 @@ namespace emfio
                     if (nMetaType == 0x464d4520)
                     {
                         // read and get possible failure/error, ReadEnhWMF returns success
-                        bReadError = !emfio::EmfReader(*pStream, aMtf).ReadEnhWMF();
+                        emfio::EmfReader aReader(*pStream, aMtf);
+                        aReader.SetSizeHint(maSizeHint);
+                        bReadError = !aReader.ReadEnhWMF();
                     }
                     else
                     {
@@ -215,12 +220,18 @@ namespace emfio
             }
             else
             {
-                OSL_ENSURE(false, "Invalid stream (!)");
+                SAL_WARN("emfio", "Invalid stream (!)");
             }
 
             return comphelper::containerToSequence(aRetval);
         }
 
+        void XEmfParser::setSizeHint(const geometry::RealPoint2D& rSize)
+        {
+            maSizeHint.setX(rSize.X);
+            maSizeHint.setY(rSize.Y);
+        }
+
         OUString SAL_CALL XEmfParser::getImplementationName()
         {
             return XEmfParser_getImplementationName();
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index 6a974085d887..7fa7acabccd4 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -26,6 +26,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>
@@ -165,6 +167,8 @@ using namespace std;
 #define EMR_SETLINKEDUFIS              119
 #define EMR_SETTEXTJUSTIFICATION       120
 
+#define PDF_SIGNATURE 0x50444620 // "PDF "
+
 namespace
 {
 
@@ -375,7 +379,7 @@ namespace emfio
         , mnRecordCount(0)
         , mbRecordPath(false)
         , mbEMFPlus(false)
-        ,mbEMFPlusDualMode(false)
+        , mbEMFPlusDualMode(false)
     {
     }
 
@@ -383,6 +387,128 @@ namespace emfio
     {
     }
 
+    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;
+
+    void EmfReader::ReadGDIComment(sal_uInt32 nCommentId)
+    {
+        sal_uInt32 nPublicCommentIdentifier;
+        mpInputStream->ReadUInt32(nPublicCommentIdentifier);
+
+        SAL_INFO("emfio", "\t\tEMR_COMMENT_PUBLIC, id: 0x" << std::hex << nCommentId << std::dec);
+        switch (nPublicCommentIdentifier)
+        {
+            case EMR_COMMENT_BEGINGROUP:
+            {
+                SAL_INFO("emfio", "\t\t\tEMR_COMMENT_BEGINGROUP");
+                sal_uInt32 left, top, right, bottom;
+                mpInputStream->ReadUInt32(left).ReadUInt32(top).ReadUInt32(right).ReadUInt32(bottom);
+
+                SAL_INFO("emfio", "\t\t\t\tBounding rect");
+                SAL_INFO("emfio", "\t\t\t\t\tLeft: " << left);
+                SAL_INFO("emfio", "\t\t\t\t\tTop: " << top);
+                SAL_INFO("emfio", "\t\t\t\t\tRight: " << right);
+                SAL_INFO("emfio", "\t\t\t\t\tBottom: " << bottom);
+
+                sal_uInt32 nDescChars;
+                mpInputStream->ReadUInt32(nDescChars);
+
+                OUString aDesc;
+                for (sal_uInt32 i=0; i < nDescChars; i++)
+                {
+                    sal_uInt16 cChar(0);
+                    mpInputStream->ReadUInt16(cChar);
+                    if (cChar == '\0')
+                        break;
+
+                    sal_Unicode cUniChar = static_cast<sal_Unicode>(cChar);
+                    aDesc = aDesc.concat(OUString(cUniChar));
+                }
+
+                SAL_INFO("emfio", "\t\tDescription: " << aDesc);
+            }
+            break;
+
+            case EMR_COMMENT_ENDGROUP:
+                SAL_INFO("emfio", "\t\t\tEMR_COMMENT_ENDGROUP");
+                break;
+
+            case EMR_COMMENT_MULTIFORMATS:
+                ReadMultiformatsComment();
+                break;
+
+            case EMR_COMMENT_WINDOWS_METAFILE:
+                SAL_WARN("emfio", "\t\tEMR_COMMENT_WINDOWS_METAFILE not implemented");
+                break;
+
+            default:
+                SAL_WARN("emfio", "\t\tEMR_COMMENT_PUBLIC not implemented, id: 0x" << std::hex << nCommentId << std::dec);
+                break;
+        }
+    }
+
+    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, &maSizeHint))
+        {
+            return;
+        }
+
+        maBmpSaveList.emplace_back(new BSaveStruct(aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY));
+        mbReadOtherGraphicFormat = true;
+    }
+
     void EmfReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC)
     {
         if (!mbEMFPlus)
@@ -425,14 +551,14 @@ namespace emfio
             mpInputStream->ReadUInt16( type ).ReadUInt16( flags ).ReadUInt32( size ).ReadUInt32( dataSize );
             nRemainder -= nRequiredHeaderSize;
 
-            SAL_INFO ("emfio", "\t\tEMF+ record type: " << std::hex << type << std::dec);
+            SAL_INFO("emfio", "\t\tEMF+ record type: 0x" << std::hex << type << std::dec);
 
             // Get Device Context
             // TODO We should use  EmfPlusRecordType::GetDC instead
             if( type == 0x4004 )
             {
                 bHaveDC = true;
-                SAL_INFO ("emfio", "\t\tEMF+ lock DC (device context)");
+                SAL_INFO("emfio", "\t\tEMF+ lock DC (device context)");
             }
 
             // look for the "dual mode" in header
@@ -442,6 +568,7 @@ namespace emfio
             if ( type == 0x4001 && flags & 1 )
             {
                 mbEMFPlusDualMode = true;
+                SAL_INFO ("emfio", "\t\tEMF+ dual mode detected");
             }
 
             // Get the length of the remaining data of this record based
@@ -497,6 +624,8 @@ namespace emfio
     template <class T>
     tools::Polygon EmfReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints, sal_uInt32 nNextPos)
     {
+        SAL_INFO ("emfio", "\t\tPolygon:");
+
         bool bRecordOk = nPoints <= SAL_MAX_UINT16;
         SAL_WARN_IF(!bRecordOk, "emfio", "polygon record has more polygons than we can handle");
         if (!bRecordOk || !nPoints)
@@ -516,6 +645,9 @@ namespace emfio
         {
             T nX, nY;
             *mpInputStream >> nX >> nY;
+
+            SAL_INFO("emfio", "\t\t\tPoint " << i << " of " << nPoints << ": " << nX << ", " << nY);
+
             if (!mpInputStream->good())
             {
                 SAL_WARN("emfio", "short read on polygon, truncating");
@@ -535,11 +667,18 @@ namespace emfio
     template <class T>
     void EmfReader::ReadAndDrawPolyLine(sal_uInt32 nNextPos)
     {
-        sal_uInt32  nPoints;
-        sal_uInt32  i, nNumberOfPolylines( 0 ), nCount( 0 );
+        SAL_INFO("emfio", "\t\tPolyline: ");
+
         mpInputStream->SeekRel( 0x10 ); // TODO Skipping Bounds. A 128-bit WMF RectL object (specifies the bounding rectangle in device units.)
+
+        sal_uInt32 nNumberOfPolylines = 0;
         mpInputStream->ReadUInt32( nNumberOfPolylines );
+        SAL_INFO("emfio", "\t\t\tPolylines: " << nNumberOfPolylines);
+
+        sal_uInt32 nCount = 0;
         mpInputStream->ReadUInt32( nCount ); // total number of points in all polylines
+        SAL_INFO("emfio", "\t\t\tPoints: " << nCount);
+
         const auto nEndPos = std::min(nNextPos, mnEndPos);
         if (mpInputStream->Tell() >= nEndPos)
             return;
@@ -551,13 +690,16 @@ namespace emfio
            )
         {
             std::unique_ptr< sal_uInt32[] > pnPolylinePointCount( new sal_uInt32[ nNumberOfPolylines ] );
-            for ( i = 0; i < nNumberOfPolylines && mpInputStream->good(); i++ )
+            for ( sal_uInt32 i = 0; i < nNumberOfPolylines && mpInputStream->good(); i++ )
             {
+                sal_uInt32 nPoints;
                 mpInputStream->ReadUInt32( nPoints );
+                SAL_INFO("emfio", "\t\t\tPoint " << i << " of " << nNumberOfPolylines << ": " << nPoints);
                 pnPolylinePointCount[ i ] = nPoints;
             }
+
             // Get polyline points:
-            for ( i = 0; ( i < nNumberOfPolylines ) && mpInputStream->good(); i++ )
+            for ( sal_uInt32 i = 0; ( i < nNumberOfPolylines ) && mpInputStream->good(); i++ )
             {
                 tools::Polygon aPolygon = ReadPolygon<T>(0, pnPolylinePointCount[i], nNextPos);
                 DrawPolyLine(aPolygon, false, mbRecordPath);
@@ -572,10 +714,15 @@ namespace emfio
     template <class T>
     void EmfReader::ReadAndDrawPolyPolygon(sal_uInt32 nNextPos)
     {
+        SAL_INFO("emfio", "\t\tPolygon: ");
+        mpInputStream->SeekRel( 0x10 ); // RectL bounds
+
         sal_uInt32 nPoly(0), nGesPoints(0), nReadPoints(0);
-        mpInputStream->SeekRel( 0x10 );
         // Number of polygons
         mpInputStream->ReadUInt32( nPoly ).ReadUInt32( nGesPoints );
+        SAL_INFO("emfio", "\t\t\tPolygons: " << nPoly);
+        SAL_INFO("emfio", "\t\t\tPoints: " << nGesPoints);
+
         const auto nEndPos = std::min(nNextPos, mnEndPos);
         if (mpInputStream->Tell() >= nEndPos)
             return;
@@ -595,8 +742,12 @@ namespace emfio
         {
             sal_uInt32 nPoints(0);
             mpInputStream->ReadUInt32( nPoints );
+
+            SAL_INFO("emfio", "\t\t\t\tPolygon " << i << " points: " << nPoints);
+
             aPoints[i] = static_cast<sal_uInt16>(nPoints);
         }
+
         if ( mpInputStream->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - mpInputStream->Tell() ) )
         {
             // Get polygon points
@@ -635,7 +786,9 @@ namespace emfio
 
         static bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == nullptr );
 
-        while( bStatus && mnRecordCount-- && mpInputStream->good())
+        SAL_INFO("emfio", "EMF_PLUS_DISABLE is " << (bEnableEMFPlus ? "enabled" : "disabled"));
+
+        while (bStatus && mnRecordCount-- && mpInputStream->good() && !mbReadOtherGraphicFormat)
         {
             sal_uInt32  nRecType(0), nRecSize(0);
             mpInputStream->ReadUInt32(nRecType).ReadUInt32(nRecSize);
@@ -672,9 +825,11 @@ namespace emfio
 
             bool bFlag = false;
 
-            SAL_INFO ("emfio", "0x" << std::hex << (nNextPos - nRecSize) <<  "-0x" << nNextPos << " " << record_type_name(nRecType) << " size: " <<  nRecSize << std::dec);
+            SAL_INFO("emfio", "0x" << std::hex << (nNextPos - nRecSize) <<  "-0x" << nNextPos << " " << record_type_name(nRecType) << " size: "
+                                    <<  std::dec << nRecSize);
 
-            if( bEnableEMFPlus && nRecType == EMR_COMMENT ) {
+            if( bEnableEMFPlus && nRecType == EMR_COMMENT )
+            {
                 sal_uInt32 length;
 
                 mpInputStream->ReadUInt32( length );
@@ -686,7 +841,7 @@ namespace emfio
 
                     mpInputStream->ReadUInt32( nCommentId );
 
-                    SAL_INFO ("emfio", "\t\tbegin " << static_cast<char>(nCommentId & 0xff) << static_cast<char>((nCommentId & 0xff00) >> 8) << static_cast<char>((nCommentId & 0xff0000) >> 16) << static_cast<char>((nCommentId & 0xff000000) >> 24) << " id: 0x" << std::hex << nCommentId << std::dec);
+                    SAL_INFO("emfio", "\t\tbegin " << static_cast<char>(nCommentId & 0xff) << static_cast<char>((nCommentId & 0xff00) >> 8) << static_cast<char>((nCommentId & 0xff0000) >> 16) << static_cast<char>((nCommentId & 0xff000000) >> 24) << " id: 0x" << std::hex << nCommentId << std::dec);
 
                     if( nCommentId == EMR_COMMENT_EMFPLUS && nRecSize >= 12 )
                     {
@@ -696,7 +851,7 @@ namespace emfio
                     }
                     else if( nCommentId == EMR_COMMENT_PUBLIC && nRecSize >= 12 )
                     {
-                        // TODO: ReadGDIComment()
+                        ReadGDIComment(nCommentId);
                     }
                     else if( nCommentId == EMR_COMMENT_EMFSPOOL && nRecSize >= 12 )
                     {
@@ -752,6 +907,8 @@ namespace emfio
                     {
                         sal_Int32 w = 0, h = 0;
                         mpInputStream->ReadInt32( w ).ReadInt32( h );
+                        SAL_INFO("emfio", "\t\tWidth: " << w);
+                        SAL_INFO("emfio", "\t\tHeight: " << h);
                         SetWinExt( Size( w, h ), true);
                     }
                     break;
@@ -759,6 +916,7 @@ namespace emfio
                     case EMR_SETWINDOWORGEX :
                     {
                         mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
                         SetWinOrg( Point( nX32, nY32 ), true);
                     }
                     break;
@@ -766,6 +924,9 @@ namespace emfio
                     case EMR_SCALEWINDOWEXTEX :
                     {
                         mpInputStream->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
+                        SAL_INFO("emfio", "\t\tHorizontal scale: " << nNom1 << " / " << nDen1);
+                        SAL_INFO("emfio", "\t\tVertical scale: " << nNom2 << " / " << nDen2);
+
                         if (nDen1 != 0 && nDen2 != 0)
                             ScaleWinExt( static_cast<double>(nNom1) / nDen1, static_cast<double>(nNom2) / nDen2 );
                         else
@@ -776,6 +937,7 @@ namespace emfio
                     case EMR_SETVIEWPORTORGEX :
                     {
                         mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
                         SetDevOrg( Point( nX32, nY32 ) );
                     }
                     break;
@@ -783,6 +945,9 @@ namespace emfio
                     case EMR_SCALEVIEWPORTEXTEX :
                     {
                         mpInputStream->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
+                        SAL_INFO("emfio", "\t\tHorizontal scale: " << nNom1 << " / " << nDen1);
+                        SAL_INFO("emfio", "\t\tVertical scale: " << nNom2 << " / " << nDen2);
+
                         if (nDen1 != 0 && nDen2 != 0)
                             ScaleDevExt( static_cast<double>(nNom1) / nDen1, static_cast<double>(nNom2) / nDen2 );
                         else
@@ -794,6 +959,9 @@ namespace emfio
                     {
                         sal_Int32 w = 0, h = 0;
                         mpInputStream->ReadInt32( w ).ReadInt32( h );
+                        SAL_INFO("emfio", "\t\tWidth: " << w);
+                        SAL_INFO("emfio", "\t\tHeight: " << h);
+
                         SetDevExt( Size( w, h ) );
                     }
                     break;
@@ -805,6 +973,7 @@ namespace emfio
                     case EMR_SETPIXELV :
                     {
                         mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
                         DrawPixel( Point( nX32, nY32 ), ReadColor() );
                     }
                     break;
@@ -813,6 +982,7 @@ namespace emfio
                     {
                         sal_uInt32 nMapMode;
                         mpInputStream->ReadUInt32( nMapMode );
+                        SAL_INFO("emfio", "\t\tMapMode: 0x" << std::hex << nMapMode << std::dec);
                         SetMapMode( nMapMode );
                     }
                     break;
@@ -820,6 +990,7 @@ namespace emfio
                     case EMR_SETBKMODE :
                     {
                         mpInputStream->ReadUInt32( nDat32 );
+                        SAL_INFO("emfio", "\t\tBkMode: 0x" << std::hex << nDat32 << std::dec);
                         SetBkMode( static_cast<BkMode>(nDat32) );
                     }
                     break;
@@ -830,6 +1001,7 @@ namespace emfio
                     case EMR_SETROP2 :
                     {
                         mpInputStream->ReadUInt32( nDat32 );
+                        SAL_INFO("emfio", "\t\tROP2: 0x" << std::hex << nDat32 << std::dec);
                         SetRasterOp( static_cast<WMFRasterOp>(nDat32) );
                     }
                     break;
@@ -837,12 +1009,14 @@ namespace emfio
                     case EMR_SETSTRETCHBLTMODE :
                     {
                         mpInputStream->ReadUInt32( nStretchBltMode );
+                        SAL_INFO("emfio", "\t\tStretchBltMode: 0x" << std::hex << nDat32 << std::dec);
                     }
                     break;
 
                     case EMR_SETTEXTALIGN :
                     {
                         mpInputStream->ReadUInt32( nDat32 );
+                        SAL_INFO("emfio", "\t\tTextAlign: 0x" << std::hex << nDat32 << std::dec);
                         SetTextAlign( nDat32 );
                     }
                     break;
@@ -862,6 +1036,7 @@ namespace emfio
                     case EMR_OFFSETCLIPRGN :
                     {
                         mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
                         MoveClipRegion( Size( nX32, nY32 ) );
                     }
                     break;
@@ -869,6 +1044,7 @@ namespace emfio
                     case EMR_MOVETOEX :
                     {
                         mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
                         MoveTo( Point( nX32, nY32 ), mbRecordPath);
                     }
                     break;
@@ -877,6 +1053,8 @@ namespace emfio
                     {
                         mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
                         IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+                        SAL_INFO("emfio", "\t\tPoint: (" << nX32 << ", " << nY32 << ")");
+                        SAL_INFO("emfio", "\t\tPoint: (" << nx32 << ", " << ny32 << ")");
                     }
                     break;
 
@@ -1587,6 +1765,12 @@ namespace emfio
                         mpInputStream->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom ).ReadInt32( nGfxMode ).ReadInt32( nXScale ).ReadInt32( nYScale )
                            .ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
 
+                        SAL_INFO("emfio", "\t\tBounds: " << nLeft << ", " << nTop << ", " << nRight << ", " << nBottom);
+                        SAL_INFO("emfio", "\t\tiGraphicsMode: 0x" << std::hex << nGfxMode << std::dec);
+                        SAL_INFO("emfio", "\t\texScale: " << nXScale);
+                        SAL_INFO("emfio", "\t\teyScale: " << nYScale);
+                        SAL_INFO("emfio", "\t\tReference: (" << ptlReferenceX << ", " << ptlReferenceY << ")");
+
                         mpInputStream->SeekRel( 0x10 );
                         mpInputStream->ReadUInt32( offDx );
 
@@ -1620,6 +1804,8 @@ namespace emfio
                                 }
                             }
 
+                            SAL_INFO("emfio", "\t\tText: " << aText);
+
                             std::unique_ptr<long[]> pDXAry, pDYAry;
 
                             sal_Int32 nDxSize;
@@ -1765,56 +1951,56 @@ namespace emfio
                     }
                     break;
 
-                    case EMR_MASKBLT :                  SAL_INFO("emfio", "not implemented 'MaskBlt'");                   break;
-                    case EMR_PLGBLT :                   SAL_INFO("emfio", "not implemented 'PlgBlt'");                    break;
-                    case EMR_SETDIBITSTODEVICE :        SAL_INFO("emfio", "not implemented 'SetDIBitsToDevice'");         break;
-                    case EMR_FRAMERGN :                 SAL_INFO("emfio", "not implemented 'FrameRgn'");                  break;
-                    case EMR_INVERTRGN :                SAL_INFO("emfio", "not implemented 'InvertRgn'");                 break;
-                    case EMR_PAINTRGN :                 SAL_INFO("emfio", "not implemented 'PaintRgn'");                  break;
-                    case EMR_FLATTENPATH :              SAL_INFO("emfio", "not implemented 'FlattenPath'");               break;
-                    case EMR_WIDENPATH :                SAL_INFO("emfio", "not implemented 'WidenPath'");                 break;
-                    case EMR_POLYDRAW :                 SAL_INFO("emfio", "not implemented 'Polydraw'");                  break;
-                    case EMR_SETARCDIRECTION :          SAL_INFO("emfio", "not implemented 'SetArcDirection'");           break;
-                    case EMR_SETPALETTEENTRIES :        SAL_INFO("emfio", "not implemented 'SetPaletteEntries'");         break;
-                    case EMR_RESIZEPALETTE :            SAL_INFO("emfio", "not implemented 'ResizePalette'");             break;
-                    case EMR_EXTFLOODFILL :             SAL_INFO("emfio", "not implemented 'ExtFloodFill'");              break;
-                    case EMR_ANGLEARC :                 SAL_INFO("emfio", "not implemented 'AngleArc'");                  break;
-                    case EMR_SETCOLORADJUSTMENT :       SAL_INFO("emfio", "not implemented 'SetColorAdjustment'");        break;
-                    case EMR_POLYDRAW16 :               SAL_INFO("emfio", "not implemented 'PolyDraw16'");                break;
-                    case EMR_POLYTEXTOUTA :             SAL_INFO("emfio", "not implemented 'PolyTextOutA'");              break;
-                    case EMR_POLYTEXTOUTW :             SAL_INFO("emfio", "not implemented 'PolyTextOutW'");              break;
-                    case EMR_CREATECOLORSPACE :         SAL_INFO("emfio", "not implemented 'CreateColorSpace'");          break;
-                    case EMR_SETCOLORSPACE :            SAL_INFO("emfio", "not implemented 'SetColorSpace'");             break;
-                    case EMR_DELETECOLORSPACE :         SAL_INFO("emfio", "not implemented 'DeleteColorSpace'");          break;
-                    case EMR_GLSRECORD :                SAL_INFO("emfio", "not implemented 'GlsRecord'");                 break;
-                    case EMR_GLSBOUNDEDRECORD :         SAL_INFO("emfio", "not implemented 'GlsBoundRecord'");            break;
-                    case EMR_PIXELFORMAT :              SAL_INFO("emfio", "not implemented 'PixelFormat'");               break;
-                    case EMR_DRAWESCAPE :               SAL_INFO("emfio", "not implemented 'DrawEscape'");                break;
-                    case EMR_EXTESCAPE :                SAL_INFO("emfio", "not implemented 'ExtEscape'");                 break;
-                    case EMR_STARTDOC :                 SAL_INFO("emfio", "not implemented 'StartDoc'");                  break;
-                    case EMR_SMALLTEXTOUT :             SAL_INFO("emfio", "not implemented 'SmallTextOut'");              break;
-                    case EMR_FORCEUFIMAPPING :          SAL_INFO("emfio", "not implemented 'ForceUFIMapping'");           break;
-                    case EMR_NAMEDESCAPE :              SAL_INFO("emfio", "not implemented 'NamedEscape'");               break;
-                    case EMR_COLORCORRECTPALETTE :      SAL_INFO("emfio", "not implemented 'ColorCorrectPalette'");       break;
-                    case EMR_SETICMPROFILEA :           SAL_INFO("emfio", "not implemented 'SetICMProfileA'");            break;
-                    case EMR_SETICMPROFILEW :           SAL_INFO("emfio", "not implemented 'SetICMProfileW'");            break;
-                    case EMR_TRANSPARENTBLT :           SAL_INFO("emfio", "not implemented 'TransparenBlt'");             break;
-                    case EMR_TRANSPARENTDIB :           SAL_INFO("emfio", "not implemented 'TransparenDib'");             break;
-                    case EMR_GRADIENTFILL :             SAL_INFO("emfio", "not implemented 'GradientFill'");              break;
-                    case EMR_SETLINKEDUFIS :            SAL_INFO("emfio", "not implemented 'SetLinkedUFIS'");             break;
-
-                    case EMR_SETMAPPERFLAGS :           SAL_INFO("emfio", "not implemented 'SetMapperFlags'");            break;
-                    case EMR_SETICMMODE :               SAL_INFO("emfio", "not implemented 'SetICMMode'");                break;
-                    case EMR_CREATEMONOBRUSH :          SAL_INFO("emfio", "not implemented 'CreateMonoBrush'");           break;
-                    case EMR_SETBRUSHORGEX :            SAL_INFO("emfio", "not implemented 'SetBrushOrgEx'");             break;
-                    case EMR_SETMETARGN :               SAL_INFO("emfio", "not implemented 'SetMetArgn'");                break;
-                    case EMR_SETMITERLIMIT :            SAL_INFO("emfio", "not implemented 'SetMiterLimit'");             break;
-                    case EMR_EXCLUDECLIPRECT :          SAL_INFO("emfio", "not implemented 'ExcludeClipRect'");           break;
-                    case EMR_REALIZEPALETTE :           SAL_INFO("emfio", "not implemented 'RealizePalette'");            break;
-                    case EMR_SELECTPALETTE :            SAL_INFO("emfio", "not implemented 'SelectPalette'");             break;
-                    case EMR_CREATEPALETTE :            SAL_INFO("emfio", "not implemented 'CreatePalette'");             break;
-                    case EMR_ALPHADIBBLEND :            SAL_INFO("emfio", "not implemented 'AlphaDibBlend'");             break;
-                    case EMR_SETTEXTJUSTIFICATION :     SAL_INFO("emfio", "not implemented 'SetTextJustification'");      break;
+                    case EMR_MASKBLT :                  SAL_WARN("emfio", "not implemented 'MaskBlt'");                   break;
+                    case EMR_PLGBLT :                   SAL_WARN("emfio", "not implemented 'PlgBlt'");                    break;
+                    case EMR_SETDIBITSTODEVICE :        SAL_WARN("emfio", "not implemented 'SetDIBitsToDevice'");         break;
+                    case EMR_FRAMERGN :                 SAL_WARN("emfio", "not implemented 'FrameRgn'");                  break;
+                    case EMR_INVERTRGN :                SAL_WARN("emfio", "not implemented 'InvertRgn'");                 break;
+                    case EMR_PAINTRGN :                 SAL_WARN("emfio", "not implemented 'PaintRgn'");                  break;
+                    case EMR_FLATTENPATH :              SAL_WARN("emfio", "not implemented 'FlattenPath'");               break;
+                    case EMR_WIDENPATH :                SAL_WARN("emfio", "not implemented 'WidenPath'");                 break;
+                    case EMR_POLYDRAW :                 SAL_WARN("emfio", "not implemented 'Polydraw'");                  break;
+                    case EMR_SETARCDIRECTION :          SAL_WARN("emfio", "not implemented 'SetArcDirection'");           break;
+                    case EMR_SETPALETTEENTRIES :        SAL_WARN("emfio", "not implemented 'SetPaletteEntries'");         break;
+                    case EMR_RESIZEPALETTE :            SAL_WARN("emfio", "not implemented 'ResizePalette'");             break;
+                    case EMR_EXTFLOODFILL :             SAL_WARN("emfio", "not implemented 'ExtFloodFill'");              break;
+                    case EMR_ANGLEARC :                 SAL_WARN("emfio", "not implemented 'AngleArc'");                  break;
+                    case EMR_SETCOLORADJUSTMENT :       SAL_WARN("emfio", "not implemented 'SetColorAdjustment'");        break;
+                    case EMR_POLYDRAW16 :               SAL_WARN("emfio", "not implemented 'PolyDraw16'");                break;
+                    case EMR_POLYTEXTOUTA :             SAL_WARN("emfio", "not implemented 'PolyTextOutA'");              break;
+                    case EMR_POLYTEXTOUTW :             SAL_WARN("emfio", "not implemented 'PolyTextOutW'");              break;
+                    case EMR_CREATECOLORSPACE :         SAL_WARN("emfio", "not implemented 'CreateColorSpace'");          break;
+                    case EMR_SETCOLORSPACE :            SAL_WARN("emfio", "not implemented 'SetColorSpace'");             break;
+                    case EMR_DELETECOLORSPACE :         SAL_WARN("emfio", "not implemented 'DeleteColorSpace'");          break;
+                    case EMR_GLSRECORD :                SAL_WARN("emfio", "not implemented 'GlsRecord'");                 break;
+                    case EMR_GLSBOUNDEDRECORD :         SAL_WARN("emfio", "not implemented 'GlsBoundRecord'");            break;
+                    case EMR_PIXELFORMAT :              SAL_WARN("emfio", "not implemented 'PixelFormat'");               break;
+                    case EMR_DRAWESCAPE :               SAL_WARN("emfio", "not implemented 'DrawEscape'");                break;
+                    case EMR_EXTESCAPE :                SAL_WARN("emfio", "not implemented 'ExtEscape'");                 break;
+                    case EMR_STARTDOC :                 SAL_WARN("emfio", "not implemented 'StartDoc'");                  break;
+                    case EMR_SMALLTEXTOUT :             SAL_WARN("emfio", "not implemented 'SmallTextOut'");              break;
+                    case EMR_FORCEUFIMAPPING :          SAL_WARN("emfio", "not implemented 'ForceUFIMapping'");           break;
+                    case EMR_NAMEDESCAPE :              SAL_WARN("emfio", "not implemented 'NamedEscape'");               break;
+                    case EMR_COLORCORRECTPALETTE :      SAL_WARN("emfio", "not implemented 'ColorCorrectPalette'");       break;
+                    case EMR_SETICMPROFILEA :           SAL_WARN("emfio", "not implemented 'SetICMProfileA'");            break;
+                    case EMR_SETICMPROFILEW :           SAL_WARN("emfio", "not implemented 'SetICMProfileW'");            break;
+                    case EMR_TRANSPARENTBLT :           SAL_WARN("emfio", "not implemented 'TransparenBlt'");             break;
+                    case EMR_TRANSPARENTDIB :           SAL_WARN("emfio", "not implemented 'TransparenDib'");             break;
+                    case EMR_GRADIENTFILL :             SAL_WARN("emfio", "not implemented 'GradientFill'");              break;
+                    case EMR_SETLINKEDUFIS :            SAL_WARN("emfio", "not implemented 'SetLinkedUFIS'");             break;
+
+                    case EMR_SETMAPPERFLAGS :           SAL_WARN("emfio", "not implemented 'SetMapperFlags'");            break;
+                    case EMR_SETICMMODE :               SAL_WARN("emfio", "not implemented 'SetICMMode'");                break;
+                    case EMR_CREATEMONOBRUSH :          SAL_WARN("emfio", "not implemented 'CreateMonoBrush'");           break;
+                    case EMR_SETBRUSHORGEX :            SAL_WARN("emfio", "not implemented 'SetBrushOrgEx'");             break;
+                    case EMR_SETMETARGN :               SAL_WARN("emfio", "not implemented 'SetMetArgn'");                break;
+                    case EMR_SETMITERLIMIT :            SAL_WARN("emfio", "not implemented 'SetMiterLimit'");             break;
+                    case EMR_EXCLUDECLIPRECT :          SAL_WARN("emfio", "not implemented 'ExcludeClipRect'");           break;
+                    case EMR_REALIZEPALETTE :           SAL_WARN("emfio", "not implemented 'RealizePalette'");            break;
+                    case EMR_SELECTPALETTE :            SAL_WARN("emfio", "not implemented 'SelectPalette'");             break;
+                    case EMR_CREATEPALETTE :            SAL_WARN("emfio", "not implemented 'CreatePalette'");             break;
+                    case EMR_ALPHADIBBLEND :            SAL_WARN("emfio", "not implemented 'AlphaDibBlend'");             break;
+                    case EMR_SETTEXTJUSTIFICATION :     SAL_WARN("emfio", "not implemented 'SetTextJustification'");      break;
 
                     case EMR_COMMENT :
                     case EMR_HEADER :               // has already been read at ReadHeader()
@@ -1840,6 +2026,7 @@ namespace emfio
         // Reading the METAHEADER - EMR_HEADER ([MS-EMF] section 2.3.4.2 EMR_HEADER Record Types)
         sal_uInt32 nType(0), nHeaderSize(0);
         mpInputStream->ReadUInt32(nType).ReadUInt32(nHeaderSize);
+        SAL_INFO ("emfio", "0x0-0x" << std::hex << nHeaderSize << " " << record_type_name(nType) << " size: " << std::dec <<  nHeaderSize);
         if (nType != 0x00000001)
         {
             // per [MS-EMF] 2.3.4.2 EMF Header Record Types, type MUST be 0x00000001
@@ -1850,13 +2037,16 @@ namespace emfio
         // Start reading the EMR_HEADER Header object
 
         // bound size (RectL object, see [MS-WMF] section 2.2.2.19)
+        SAL_INFO("emfio", "\tBounding rectangle");
         tools::Rectangle rclBounds = ReadRectangle(); // rectangle in logical units
 
         // picture frame size (RectL object)
+        SAL_INFO("emfio", "\tPicture frame");
         tools::Rectangle rclFrame = ReadRectangle(); // rectangle in device units 1/100th mm
 
         sal_uInt32 nSignature(0);
         mpInputStream->ReadUInt32(nSignature);
+        SAL_INFO("emfio", "\tSignature: 0x" << std::hex << nSignature << std::dec);
 
         // nSignature MUST be the ASCII characters "FME", see [WS-EMF] 2.2.9 Header Object
         // and 2.1.14 FormatSignature Enumeration
@@ -1869,12 +2059,14 @@ namespace emfio
         sal_uInt32 nVersion(0);
         mpInputStream->ReadUInt32(nVersion);  // according to [WS-EMF] 2.2.9, this SHOULD be 0x0001000, however
                                        // Microsoft note that not even Windows checks this...
+        SAL_INFO("emfio", "\tVersion: 0x" << std::hex << nSignature << std::dec);
         if (nVersion != 0x00010000)
         {
             SAL_WARN("emfio", "EMF\t\tThis really should be 0x00010000, though not absolutely essential...");
         }
 
         mpInputStream->ReadUInt32(mnEndPos); // size of metafile
+        SAL_INFO("emfio", "\tMetafile size: " << mnEndPos);
         mnEndPos += mnStartPos;
 
         sal_uInt32 nStrmPos = mpInputStream->Tell(); // checking if mnEndPos is valid
@@ -1889,6 +2081,7 @@ namespace emfio
         }
 
         mpInputStream->ReadInt32(mnRecordCount);
+        SAL_INFO("emfio", "\tRecords: " << mnRecordCount);
 
         if (mnRecordCount <= 0)
         {
@@ -1901,6 +2094,7 @@ namespace emfio
 
         sal_uInt16 nHandlesCount;
         mpInputStream->ReadUInt16(nHandlesCount);
+        SAL_INFO("emfio", "\tGraphics: " << nHandlesCount);
 
         // the next 2 bytes are reserved, but according to [MS-EMF] section 2.2.9
         // it MUST be 0x000 and MUST be ignored... the thing is, having such a specific
@@ -1908,6 +2102,7 @@ namespace emfio
 
         sal_uInt16 nReserved(0);
         mpInputStream->ReadUInt16(nReserved);
+        SAL_INFO("emfio", "\tReserved: 0x" << std::hex << nReserved << std::dec);
 
         if ( nReserved != 0x0000 )
         {
@@ -1924,11 +2119,14 @@ namespace emfio
 
         sal_uInt32 nPalEntries(0);
         mpInputStream->ReadUInt32(nPalEntries);
+        SAL_INFO("emfio", "\tPalette entries: " << nPalEntries);
         sal_Int32 nPixX(0), nPixY(0), nMillX(0), nMillY(0);
         mpInputStream->ReadInt32(nPixX);
         mpInputStream->ReadInt32(nPixY);
+        SAL_INFO("emfio", "\tRef (pixels): " << nPixX << ", " << nPixY);
         mpInputStream->ReadInt32(nMillX);
         mpInputStream->ReadInt32(nMillY);
+        SAL_INFO("emfio", "\tRef (mm): " << nMillX << ", " << nMillY);
 
         SetrclFrame(rclFrame);
         SetrclBounds(rclBounds);
@@ -1945,6 +2143,9 @@ namespace emfio
         mpInputStream->ReadInt32(nTop);
         mpInputStream->ReadInt32(nRight);
         mpInputStream->ReadInt32(nBottom);
+
+        SAL_INFO("emfio", "\t\tLeft: " << nLeft << ", top: " << nTop << ", right: " << nRight << ", bottom: " << nBottom);
+
         return tools::Rectangle(nLeft, nTop, nRight, nBottom);
     }
 
diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx
index 4de2dd4c1fe2..8cd3ef1e86cf 100644
--- a/emfio/source/reader/mtftools.cxx
+++ b/emfio/source/reader/mtftools.cxx
@@ -305,7 +305,11 @@ namespace emfio
         sal_uInt32 nColor;
 
         mpInputStream->ReadUInt32( nColor );
-        return Color( static_cast<sal_uInt8>(nColor), static_cast<sal_uInt8>( nColor >> 8 ), static_cast<sal_uInt8>( nColor >> 16 ) );
+        Color aColor(static_cast<sal_uInt8>(nColor), static_cast<sal_uInt8>(nColor >> 8), static_cast<sal_uInt8>(nColor >> 16));
+
+        SAL_INFO("emfio", "\t\tColor: " << aColor);
+
+        return aColor;
     };
 
     Point MtfTools::ImplScale(const Point& rPoint) // Hack to set varying defaults for incompletely defined files.
diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx
index d16c951f81cd..e43eb6e394c0 100644
--- a/include/vcl/pdfread.hxx
+++ b/include/vcl/pdfread.hxx
@@ -13,6 +13,7 @@
 #include <vector>
 #include <tools/gen.hxx>
 #include <tools/stream.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
 
 namespace com
 {
@@ -35,18 +36,20 @@ namespace vcl
 /// Fills the rBitmaps vector with rendered pages.
 VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps,
                                       size_t nFirstPage = 0, int nPages = 1,
-                                      double fResolutionDPI = 96.);
+                                      const basegfx::B2DTuple* pSizeHint = nullptr);
 
 /// Imports a PDF stream into rGraphic as a GDIMetaFile.
 VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex,
                              std::vector<sal_Int8>& rPdfData,
                              sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN,
-                             sal_uInt64 nSize = STREAM_SEEK_TO_END, double fResolutionDPI = 96.);
+                             sal_uInt64 nSize = STREAM_SEEK_TO_END,
+                             const basegfx::B2DTuple* pSizeHint = nullptr);
 
-VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic, double fResolutionDPI = 96.);
+VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic,
+                             const basegfx::B2DTuple* pSizeHint = nullptr);
 
 VCL_DLLPUBLIC size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps,
-                               std::vector<sal_Int8>& rPdfData, double fResolutionDPI = 96.);
+                               std::vector<sal_Int8>& rPdfData);
 
 /// Import PDF as Graphic images (1 per page), all unloaded.
 /// Since Graphic is unloaded, we need to return the page size (in pixels) separately.
diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx
index b64e79d8d936..ad2ba7dd87ab 100644
--- a/include/vcl/vectorgraphicdata.hxx
+++ b/include/vcl/vectorgraphicdata.hxx
@@ -69,6 +69,9 @@ private:
     // extra:
     std::unique_ptr<WmfExternal> mpExternalHeader;
 
+    /// Useful for PDF, which is vector-based, but still rendered to a bitmap.
+    basegfx::B2DTuple maSizeHint;
+
     // on demand creators
     void ensureReplacement();
     void ensureSequenceAndRange();
@@ -105,6 +108,13 @@ public:
     const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > >& getPrimitive2DSequence() const;
     const BitmapEx& getReplacement() const;
     BitmapChecksum GetChecksum() const;
+
+    void setSizeHint(const basegfx::B2DTuple& rSizeHint)
+    {
+        maSizeHint = rSizeHint;
+    }
+
+    const basegfx::B2DTuple& getSizeHint() const { return maSizeHint; }
 };
 
 typedef std::shared_ptr< VectorGraphicData > VectorGraphicDataPtr;
diff --git a/offapi/com/sun/star/graphic/XEmfParser.idl b/offapi/com/sun/star/graphic/XEmfParser.idl
index 1c2fd10d7fff..234d70bc1937 100644
--- a/offapi/com/sun/star/graphic/XEmfParser.idl
+++ b/offapi/com/sun/star/graphic/XEmfParser.idl
@@ -20,6 +20,7 @@
 #ifndef __com_sun_star_graphic_XEmfParser_idl__
 #define __com_sun_star_graphic_XEmfParser_idl__
 
+#include <com/sun/star/geometry/RealPoint2D.idl>
 #include <com/sun/star/uno/XInterface.idl>
 #include <com/sun/star/io/XInputStream.idl>
 
@@ -51,6 +52,13 @@ interface XEmfParser : ::com::sun::star::uno::XInterface
         [in] io::XInputStream xEmfStream,
         [in] string aAbsolutePath,
         [in] ::com::sun::star::beans::PropertyValues Properties);
+
+    /** Sets a size hint on this object.
+
+        @param Size
+            the size in 100/th mm
+     */
+    void setSizeHint([in] com::sun::star::geometry::RealPoint2D Size);
 };
 
 }; }; }; };
diff --git a/svx/source/sdr/properties/defaultproperties.cxx b/svx/source/sdr/properties/defaultproperties.cxx
index f9461f796b53..3431411a2c98 100644
--- a/svx/source/sdr/properties/defaultproperties.cxx
+++ b/svx/source/sdr/properties/defaultproperties.cxx
@@ -32,6 +32,7 @@
 #include <libxml/xmlwriter.h>
 #include <svx/svdmodel.hxx>
 #include <svx/svdtrans.hxx>
+#include <svx/xbtmpit.hxx>
 
 namespace sdr
 {
@@ -159,6 +160,21 @@ namespace sdr
 
         void DefaultProperties::SetObjectItemSet(const SfxItemSet& rSet)
         {
+            if (rSet.HasItem(XATTR_FILLBITMAP))
+            {
+                const XFillBitmapItem* pItem = rSet.GetItem(XATTR_FILLBITMAP);
+                const std::shared_ptr<VectorGraphicData>& pVectorData
+                    = pItem->GetGraphicObject().GetGraphic().getVectorGraphicData();
+                if (pVectorData)
+                {
+                    // Shape is filled by a vector graphic: tell it our size as a hint.
+                    basegfx::B2DTuple aSizeHint;
+                    aSizeHint.setX(GetSdrObject().GetSnapRect().getWidth());
+                    aSizeHint.setY(GetSdrObject().GetSnapRect().getHeight());
+                    pVectorData->setSizeHint(aSizeHint);
+                }
+            }
+
             SfxWhichIter aWhichIter(rSet);
             sal_uInt16 nWhich(aWhichIter.FirstWhich());
             const SfxPoolItem *pPoolItem;
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index 5401bf3734a3..4f9722c4a9aa 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -20,6 +20,7 @@
 #include <vcl/graph.hxx>
 #include <bitmapwriteaccess.hxx>
 #include <unotools/ucbstreamhelper.hxx>
+#include <sal/log.hxx>
 
 #include <vcl/filter/PDFiumLibrary.hxx>
 
@@ -51,7 +52,7 @@ inline double pointToPixel(const double fPoint, const double fResolutionDPI)
 /// Does PDF to bitmap conversion using pdfium.
 size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, sal_uInt64 nPos,
                        sal_uInt64 nSize, const size_t nFirstPage = 0, int nPages = 1,
-                       const double fResolutionDPI = 96.)
+                       const basegfx::B2DTuple* pSizeHint = nullptr)
 {
     // Read input into a buffer.
     SvMemoryStream aInBuffer;
@@ -59,7 +60,7 @@ size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, sal_uIn
     aInBuffer.WriteStream(rStream, nSize);
 
     return vcl::RenderPDFBitmaps(aInBuffer.GetData(), aInBuffer.GetSize(), rBitmaps, nFirstPage,
-                                 nPages, fResolutionDPI);
+                                 nPages, pSizeHint);
 }
 
 /// Decide if PDF data is old enough to be compatible.
@@ -145,9 +146,10 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 n
 namespace vcl
 {
 size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps,
-                        const size_t nFirstPage, int nPages, const double fResolutionDPI)
+                        const size_t nFirstPage, int nPages, const basegfx::B2DTuple* pSizeHint)
 {
 #if HAVE_FEATURE_PDFIUM
+    const double fResolutionDPI = 96;
     auto pPdfium = vcl::pdf::PDFiumLibrary::get();
 
     // Load the buffer using pdfium.
@@ -166,9 +168,19 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi
         if (!pPdfPage)
             break;
 
+        // Calculate the bitmap size in points.
+        size_t nPageWidthPoints = FPDF_GetPageWidth(pPdfPage);
+        size_t nPageHeightPoints = FPDF_GetPageHeight(pPdfPage);
+        if (pSizeHint && pSizeHint->getX() && pSizeHint->getY())
+        {
+            // Have a size hint, prefer that over the logic size from the PDF.
+            nPageWidthPoints = convertMm100ToTwip(pSizeHint->getX()) / 20;
+            nPageHeightPoints = convertMm100ToTwip(pSizeHint->getY()) / 20;
+        }
+
         // Returned unit is points, convert that to pixel.
-        const size_t nPageWidth = pointToPixel(FPDF_GetPageWidth(pPdfPage), fResolutionDPI);
-        const size_t nPageHeight = pointToPixel(FPDF_GetPageHeight(pPdfPage), fResolutionDPI);
+        const size_t nPageWidth = pointToPixel(nPageWidthPoints, fResolutionDPI);
+        const size_t nPageHeight = pointToPixel(nPageHeightPoints, fResolutionDPI);
         FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1);
         if (!pPdfBitmap)
             break;
@@ -206,20 +218,23 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi
     (void)rBitmaps;
     (void)nFirstPage;
     (void)nPages;
-    (void)fResolutionDPI;
+    (void)pSizeHint;
     return 0;
 #endif // HAVE_FEATURE_PDFIUM
 }
 
 bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex,
                std::vector<sal_Int8>& rPdfData, sal_uInt64 nPos, sal_uInt64 nSize,
-               const double fResolutionDPI)
+               const basegfx::B2DTuple* pSizeHint)
 {
     // Get the preview of the first page.
     std::vector<Bitmap> aBitmaps;
-    if (generatePreview(rStream, aBitmaps, nPos, nSize, nPageIndex, 1, fResolutionDPI) != 1
+    if (generatePreview(rStream, aBitmaps, nPos, nSize, nPageIndex, 1, pSizeHint) != 1
         || aBitmaps.empty())
+    {
+        SAL_WARN("vcl.filter", "ImportPDF: empty PDF data array");
         return false;
+    }
 
     rBitmap = aBitmaps[0];
 
@@ -235,12 +250,12 @@ bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex,
     return true;
 }
 
-bool ImportPDF(SvStream& rStream, Graphic& rGraphic, const double fResolutionDPI)
+bool ImportPDF(SvStream& rStream, Graphic& rGraphic, const basegfx::B2DTuple* pSizeHint)
 {
     std::vector<sal_Int8> aPdfData;
     Bitmap aBitmap;
     const bool bRet = ImportPDF(rStream, aBitmap, 0, aPdfData, STREAM_SEEK_TO_BEGIN,
-                                STREAM_SEEK_TO_END, fResolutionDPI);
+                                STREAM_SEEK_TO_END, pSizeHint);
     rGraphic = aBitmap;
     rGraphic.setPdfData(std::make_shared<std::vector<sal_Int8>>(aPdfData));
     rGraphic.setPageNumber(0); // We currently import only the first page.
@@ -248,14 +263,12 @@ bool ImportPDF(SvStream& rStream, Graphic& rGraphic, const double fResolutionDPI
 }
 
 size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps,
-                 std::vector<sal_Int8>& rPdfData, const double fResolutionDPI)
+                 std::vector<sal_Int8>& rPdfData)
 {
     std::unique_ptr<SvStream> xStream(
         ::utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ | StreamMode::SHARE_DENYNONE));
 
-    if (generatePreview(*xStream, rBitmaps, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END, 0, -1,
-                        fResolutionDPI)
-        == 0)
+    if (generatePreview(*xStream, rBitmaps, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END, 0, -1) == 0)
         return 0;
 
     // Save the original PDF stream for later use.
diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx
index 09e1d45974c5..90d66482fd20 100644
--- a/vcl/source/gdi/vectorgraphicdata.cxx
+++ b/vcl/source/gdi/vectorgraphicdata.cxx
@@ -169,6 +169,12 @@ void VectorGraphicData::ensureSequenceAndRange()
                     aSequence = mpExternalHeader->getSequence();
                 }
 
+                // Pass the size hint of the graphic to the EMF parser.
+                geometry::RealPoint2D aSizeHint;
+                aSizeHint.X = maSizeHint.getX();
+                aSizeHint.Y = maSizeHint.getY();
+                xEmfParser->setSizeHint(aSizeHint);
+
                 maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence));
             }
             else
-- 
2.26.2

openSUSE Build Service is sponsored by