[Libreoffice-commits] core.git: Branch 'feature/emfplusprimitiveparser' - emfio/inc emfio/Library_emfio.mk emfio/source include/vcl

Armin Le Grand Armin.Le.Grand at cib.de
Thu Jun 15 14:35:40 UTC 2017


 emfio/Library_emfio.mk             |    8 
 emfio/inc/emfreader.hxx            |   55 
 emfio/inc/mtftools.hxx             |  667 ++++++++++
 emfio/inc/wmfreader.hxx            |  106 +
 emfio/source/emfuno/xemfparser.cxx |  101 -
 emfio/source/reader/emfreader.cxx  | 1941 +++++++++++++++++++++++++++++++
 emfio/source/reader/mtftools.cxx   | 2283 +++++++++++++++++++++++++++++++++++++
 emfio/source/reader/wmfreader.cxx  | 1846 +++++++++++++++++++++++++++++
 include/vcl/dibtools.hxx           |    3 
 9 files changed, 6958 insertions(+), 52 deletions(-)

New commits:
commit c81257a117f13195bde5548116bb6d5edfc1a720
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Jun 15 16:35:31 2017 +0200

    emfplus: add rough version of local reader
    
    Complete redevelopent is too expensive, start with
    adding a copy of the existing vcl importer which
    will in the next steps be adapted to import primitives
    instead of MetaFile(Actions). Adapted namespace, made
    compile and added sample code to roughly use it
    
    Change-Id: I79e7ea0d78099fbbe18e2a595457b2ab353f58ea

diff --git a/emfio/Library_emfio.mk b/emfio/Library_emfio.mk
index e9a14249271a..ff209f5da3bf 100644
--- a/emfio/Library_emfio.mk
+++ b/emfio/Library_emfio.mk
@@ -25,6 +25,10 @@ $(eval $(call gb_Library_set_include,emfio,\
     -I$(SRCDIR)/emfio/inc \
 ))
 
+$(eval $(call gb_Library_use_custom_headers,emfio,\
+	officecfg/registry \
+))
+
 $(eval $(call gb_Library_use_external,emfio,boost_headers))
 
 $(eval $(call gb_Library_set_precompiled_header,emfio,$(SRCDIR)/emfio/inc/pch/precompiled_emfio))
@@ -37,6 +41,7 @@ $(eval $(call gb_Library_use_libraries,emfio,\
     cppu \
     cppuhelper \
     sal \
+    comphelper \
     tl \
     sax \
     vcl \
@@ -47,6 +52,9 @@ $(eval $(call gb_Library_use_libraries,emfio,\
 $(eval $(call gb_Library_add_exception_objects,emfio,\
     emfio/source/emfuno/emfuno \
     emfio/source/emfuno/xemfparser \
+    emfio/source/reader/mtftools \
+    emfio/source/reader/wmfreader \
+    emfio/source/reader/emfreader \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx
new file mode 100644
index 000000000000..c4f7e17e574d
--- /dev/null
+++ b/emfio/inc/emfreader.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_EMFIO_INC_EMFREADER_HXX
+#define INCLUDED_EMFIO_INC_EMFREADER_HXX
+
+#include <mtftools.hxx>
+
+namespace emfio
+{
+    class EmfReader : public MtfTools
+    {
+        bool        bRecordPath;
+        sal_Int32   nRecordCount;
+        bool        bEMFPlus;
+
+        bool        ReadHeader();
+        // reads and converts the rectangle
+        static tools::Rectangle ReadRectangle(sal_Int32, sal_Int32, sal_Int32, sal_Int32);
+
+    public:
+        EmfReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile, FilterConfigItem* pConfigItem = nullptr);
+        ~EmfReader();
+
+        bool ReadEnhWMF();
+    private:
+        template <class T> void ReadAndDrawPolyPolygon();
+        template <class T> void ReadAndDrawPolyLine();
+        template <class T> tools::Polygon ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints);
+        template <class T, class Drawer> void ReadAndDrawPolygon(Drawer drawer, const bool skipFirst);
+
+        tools::Rectangle ReadRectangle();
+        void ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC);
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/emfio/inc/mtftools.hxx b/emfio/inc/mtftools.hxx
new file mode 100644
index 000000000000..f20925f5a147
--- /dev/null
+++ b/emfio/inc/mtftools.hxx
@@ -0,0 +1,667 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_EMFIO_INC_MTFTOOLS_HXX
+#define INCLUDED_EMFIO_INC_MTFTOOLS_HXX
+
+#include <memory>
+#include <sal/config.h>
+
+//#include <vcl/graph.hxx>
+#include <basegfx/tools/b2dclipstate.hxx>
+#include <tools/poly.hxx>
+#include <vcl/font.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmapex.hxx>
+//#include <vcl/bitmapaccess.hxx>
+#include <vcl/lineinfo.hxx>
+//#include <vcl/fltcall.hxx>
+#include <o3tl/make_unique.hxx>
+#include <vcl/outdevstate.hxx>
+#include <vcl/FilterConfigItem.hxx>
+
+#define ERROR                   0
+#define NULLREGION              1
+#define COMPLEXREGION           3
+
+#define RGN_AND                 1
+#define RGN_OR                  2
+#define RGN_XOR                 3
+#define RGN_DIFF                4
+#define RGN_COPY                5
+
+namespace emfio
+{
+    enum class BkMode
+    {
+        NONE = 0,
+        Transparent = 1,
+        OPAQUE = 2,
+    };
+}
+
+/* xform stuff */
+#define MWT_IDENTITY            1
+#define MWT_LEFTMULTIPLY        2
+#define MWT_RIGHTMULTIPLY       3
+#define MWT_SET                 4
+
+#define ENHMETA_STOCK_OBJECT    0x80000000
+
+/* Stock Logical Objects */
+#define WHITE_BRUSH             0
+#define LTGRAY_BRUSH            1
+#define GRAY_BRUSH              2
+#define DKGRAY_BRUSH            3
+#define BLACK_BRUSH             4
+#define NULL_BRUSH              5
+#define WHITE_PEN               6
+#define BLACK_PEN               7
+#define NULL_PEN                8
+#define ANSI_FIXED_FONT         11
+#define ANSI_VAR_FONT           12
+#define SYSTEM_FIXED_FONT       16
+
+namespace emfio
+{
+    enum class WMFRasterOp {
+        NONE = 0,
+        Black = 1,
+        Not = 6,
+        XorPen = 7,
+        Nop = 11,
+        CopyPen = 13
+    };
+}
+
+/* Mapping modes */
+#define MM_TEXT                 1
+#define MM_LOMETRIC             2
+#define MM_HIMETRIC             3
+#define MM_LOENGLISH            4
+#define MM_HIENGLISH            5
+#define MM_TWIPS                6
+#define MM_ISOTROPIC            7
+#define MM_ANISOTROPIC          8
+
+/* Graphics modes */
+#define GM_COMPATIBLE           1
+#define GM_ADVANCED             2
+
+/* StretchBlt() modes */
+#define BLACKONWHITE            1
+#define WHITEONBLACK            2
+#define COLORONCOLOR            3
+#define HALFTONE                4
+#define STRETCH_ANDSCANS        BLACKONWHITE
+#define STRETCH_ORSCANS         WHITEONBLACK
+#define STRETCH_DELETESCANS     COLORONCOLOR
+
+#define LF_FACESIZE             32
+
+namespace emfio
+{
+    struct LOGFONTW
+    {
+        sal_Int32       lfHeight;
+        sal_Int32       lfWidth;
+        sal_Int32       lfEscapement;
+        sal_Int32       lfOrientation;
+        sal_Int32       lfWeight;
+        sal_uInt8       lfItalic;
+        sal_uInt8       lfUnderline;
+        sal_uInt8       lfStrikeOut;
+        sal_uInt8       lfCharSet;
+        sal_uInt8       lfOutPrecision;
+        sal_uInt8       lfClipPrecision;
+        sal_uInt8       lfQuality;
+        sal_uInt8       lfPitchAndFamily;
+        OUString        alfFaceName;
+    };
+    struct WMF_EXTERNALHEADER;
+}
+
+#define TA_NOUPDATECP           0x0000
+#define TA_UPDATECP             0x0001
+#define TA_LEFT                 0x0000
+#define TA_RIGHT                0x0002
+#define TA_CENTER               0x0006
+#define TA_RIGHT_CENTER  (TA_RIGHT | TA_CENTER)
+#define TA_TOP                  0x0000
+#define TA_BOTTOM               0x0008
+#define TA_BASELINE             0x0018
+
+#define SRCCOPY                 0x00CC0020L
+#define SRCPAINT                0x00EE0086L
+#define SRCAND                  0x008800C6L
+#define SRCINVERT               0x00660046L
+#define SRCERASE                0x00440328L
+#define PATCOPY                 0x00F00021L
+#define PATINVERT               0x005A0049L
+#define BLACKNESS               0x00000042L
+#define WHITENESS               0x00FF0062L
+
+#define PS_SOLID                0
+#define PS_DASH                 1
+#define PS_DOT                  2
+#define PS_DASHDOT              3
+#define PS_DASHDOTDOT           4
+#define PS_NULL                 5
+#define PS_INSIDEFRAME          6
+#define PS_STYLE_MASK           15
+
+#define PS_ENDCAP_ROUND      0x000
+#define PS_ENDCAP_SQUARE     0x100
+#define PS_ENDCAP_FLAT       0x200
+#define PS_ENDCAP_STYLE_MASK 0xF00
+
+#define PS_JOIN_ROUND       0x0000
+#define PS_JOIN_BEVEL       0x1000
+#define PS_JOIN_MITER       0x2000
+#define PS_JOIN_STYLE_MASK  0xF000
+
+#define ANSI_CHARSET            0
+#define DEFAULT_CHARSET         1
+#define SYMBOL_CHARSET          2
+#define SHIFTJIS_CHARSET        128
+#define HANGEUL_CHARSET         129
+#define GB2312_CHARSET          134
+#define CHINESEBIG5_CHARSET     136
+#define OEM_CHARSET             255
+/*WINVER >= 0x0400*/
+#define JOHAB_CHARSET           130
+#define HEBREW_CHARSET          177
+#define ARABIC_CHARSET          178
+#define GREEK_CHARSET           161
+#define TURKISH_CHARSET         162
+#define VIETNAMESE_CHARSET      163
+#define THAI_CHARSET            222
+#define EASTEUROPE_CHARSET      238
+#define RUSSIAN_CHARSET         204
+#define MAC_CHARSET             77
+#define BALTIC_CHARSET          186
+
+#define ETO_CLIPPED             0x0004
+/*WINVER >= 0x0400*/
+#define ETO_GLYPH_INDEX         0x0010
+#define ETO_RTLREADING          0x0080
+/*_WIN32_WINNT >= 0x0500*/
+#define ETO_PDY                 0x2000
+
+#define DEFAULT_PITCH           0x00
+#define FIXED_PITCH             0x01
+#define VARIABLE_PITCH          0x02
+
+/* Font Families */
+#define FF_DONTCARE             0x00
+#define FF_ROMAN                0x10
+#define FF_SWISS                0x20
+#define FF_MODERN               0x30
+#define FF_SCRIPT               0x40
+#define FF_DECORATIVE           0x50
+
+#define FW_THIN                 100
+#define FW_EXTRALIGHT           200
+#define FW_LIGHT                300
+#define FW_NORMAL               400
+#define FW_MEDIUM               500
+#define FW_SEMIBOLD             600
+#define FW_BOLD                 700
+#define FW_EXTRABOLD            800
+#define FW_ULTRALIGHT           200
+#define FW_ULTRABOLD            800
+#define FW_BLACK                900
+
+#define BS_SOLID                0
+#define BS_NULL                 1
+#define BS_HOLLOW               1
+#define BS_HATCHED              2
+#define BS_PATTERN              3
+#define BS_INDEXED              4
+#define BS_DIBPATTERN           5
+#define BS_DIBPATTERNPT         6
+#define BS_PATTERN8X8           7
+#define BS_DIBPATTERN8X8        8
+#define BS_MONOPATTERN          9
+
+
+#define RDH_RECTANGLES  1
+
+#define W_MFCOMMENT             15
+
+#define PRIVATE_ESCAPE_UNICODE  2
+
+//Scalar constants
+
+#define UNDOCUMENTED_WIN_RCL_RELATION 32
+#define MS_FIXPOINT_BITCOUNT_28_4 4
+#define HUNDREDTH_MILLIMETERS_PER_MILLIINCH 2.54
+#define MILLIINCH_PER_TWIPS   1.44
+
+//============================ WmfReader ==================================
+
+namespace emfio
+{
+    class WinMtfClipPath
+    {
+        basegfx::tools::B2DClipState maClip;
+
+    public:
+        WinMtfClipPath() : maClip() {};
+
+        void        setClipPath(const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode);
+        void        intersectClipRect(const tools::Rectangle& rRect);
+        void        excludeClipRect(const tools::Rectangle& rRect);
+        void        moveClipRegion(const Size& rSize);
+        void        setDefaultClipPath();
+
+        bool        isEmpty() const { return maClip.isCleared(); }
+
+        basegfx::B2DPolyPolygon getClipPath() const;
+
+        bool        operator==(const WinMtfClipPath& rPath) const
+        {
+            return maClip == rPath.maClip;
+        };
+    };
+
+    class WinMtfPathObj : public tools::PolyPolygon
+    {
+        bool    bClosed;
+
+    public:
+
+        WinMtfPathObj() :
+            bClosed(true)
+        {}
+
+        void        Init()
+        {
+            Clear();
+            bClosed = true;
+        }
+
+        void        ClosePath();
+        void        AddPoint(const Point& rPoint);
+        void        AddPolygon(const tools::Polygon& rPoly);
+        void        AddPolyLine(const tools::Polygon& rPoly);
+        void        AddPolyPolygon(const tools::PolyPolygon& rPolyPolygon);
+    };
+
+    struct GDIObj
+    {
+        virtual ~GDIObj() = default; // Polymorphic base class
+    };
+
+    struct WinMtfFontStyle : GDIObj
+    {
+        vcl::Font    aFont;
+
+        explicit WinMtfFontStyle(LOGFONTW& rLogFont);
+    };
+
+    enum class WinMtfFillStyleType
+    {
+        Solid, Pattern
+    };
+
+    struct WinMtfFillStyle : GDIObj
+    {
+        Color               aFillColor;
+        bool                bTransparent;
+        WinMtfFillStyleType aType;
+        Bitmap              aBmp;
+
+        WinMtfFillStyle()
+            : aFillColor(Color(COL_BLACK))
+            , bTransparent(false)
+            , aType(WinMtfFillStyleType::Solid)
+        {}
+
+        WinMtfFillStyle(const Color& rColor, bool bTrans = false)
+            : aFillColor(rColor)
+            , bTransparent(bTrans)
+            , aType(WinMtfFillStyleType::Solid)
+        {}
+
+        explicit WinMtfFillStyle(Bitmap& rBmp)
+            : bTransparent(false)
+            , aType(WinMtfFillStyleType::Pattern)
+            , aBmp(rBmp)
+        {}
+
+        bool operator==(const WinMtfFillStyle& rStyle)
+        {
+            return aFillColor == rStyle.aFillColor
+                && bTransparent == rStyle.bTransparent
+                && aType == rStyle.aType;
+        }
+    };
+
+    struct WinMtfLineStyle : GDIObj
+    {
+        Color       aLineColor;
+        LineInfo    aLineInfo;
+        bool        bTransparent;
+
+        WinMtfLineStyle()
+            : aLineColor(COL_BLACK)
+            , bTransparent(false)
+        {}
+
+        WinMtfLineStyle(const Color& rColor, bool bTrans = false)
+            : aLineColor(rColor)
+            , bTransparent(bTrans)
+        {}
+
+        WinMtfLineStyle(const Color& rColor, const LineInfo& rStyle, bool bTrans)
+            : aLineColor(rColor)
+            , aLineInfo(rStyle)
+            , bTransparent(bTrans)
+        {}
+
+        bool operator==(const WinMtfLineStyle& rStyle)
+        {
+            return aLineColor == rStyle.aLineColor
+                && bTransparent == rStyle.bTransparent
+                && aLineInfo == rStyle.aLineInfo;
+        }
+    };
+
+    struct XForm
+    {
+        float   eM11;
+        float   eM12;
+        float   eM21;
+        float   eM22;
+        float   eDx;
+        float   eDy;
+
+        XForm()
+            : eM11(1.0f)
+            , eM12(0.0f)
+            , eM21(0.0f)
+            , eM22(1.0f)
+            , eDx(0.0f)
+            , eDy(0.0f)
+        {}
+    };
+
+    SvStream& operator >> (SvStream& rInStream, XForm& rXForm);
+
+    struct SaveStruct
+    {
+        BkMode              nBkMode;
+        sal_uInt32          nMapMode, nGfxMode;
+        ComplexTextLayoutFlags nTextLayoutMode;
+        sal_Int32           nWinOrgX, nWinOrgY, nWinExtX, nWinExtY;
+        sal_Int32           nDevOrgX, nDevOrgY, nDevWidth, nDevHeight;
+
+        WinMtfLineStyle     aLineStyle;
+        WinMtfFillStyle     aFillStyle;
+
+        vcl::Font           aFont;
+        Color               aBkColor;
+        Color               aTextColor;
+        sal_uInt32          nTextAlign;
+        RasterOp            eRasterOp;
+
+        Point               aActPos;
+        WinMtfPathObj       aPathObj;
+        WinMtfClipPath      aClipPath;
+        XForm               aXForm;
+
+        bool                bFillStyleSelected;
+    };
+
+    struct BSaveStruct
+    {
+        BitmapEx        aBmpEx;
+        tools::Rectangle       aOutRect;
+        sal_uInt32      nWinRop;
+
+        BSaveStruct(const Bitmap& rBmp, const tools::Rectangle& rOutRect, sal_uInt32 nRop)
+            : aBmpEx(rBmp)
+            , aOutRect(rOutRect)
+            , nWinRop(nRop)
+        {}
+
+        BSaveStruct(const BitmapEx& rBmpEx, const tools::Rectangle& rOutRect, sal_uInt32 nRop)
+            : aBmpEx(rBmpEx)
+            , aOutRect(rOutRect)
+            , nWinRop(nRop)
+        {}
+    };
+
+    class MtfToolsWriter final
+    {
+        WinMtfPathObj       aPathObj;
+        WinMtfClipPath      aClipPath;
+
+        WinMtfLineStyle     maLatestLineStyle;
+        WinMtfLineStyle     maLineStyle;
+        WinMtfLineStyle     m_NopLineStyle;
+        WinMtfFillStyle     maLatestFillStyle;
+        WinMtfFillStyle     maFillStyle;
+        WinMtfFillStyle     m_NopFillStyle;
+        vcl::Font           maLatestFont;
+        vcl::Font           maFont;
+        sal_uInt32          mnLatestTextAlign;
+        sal_uInt32          mnTextAlign;
+        Color               maLatestTextColor;
+        Color               maTextColor;
+        Color               maLatestBkColor;
+        Color               maBkColor;
+        ComplexTextLayoutFlags  mnLatestTextLayoutMode;
+        ComplexTextLayoutFlags  mnTextLayoutMode;
+        BkMode              mnLatestBkMode;
+        BkMode              mnBkMode;
+        RasterOp            meLatestRasterOp;
+        RasterOp            meRasterOp;
+
+        std::vector< std::unique_ptr<GDIObj> > vGDIObj;
+
+        Point               maActPos;
+
+        WMFRasterOp         mnRop;
+        bool            mbNopMode;
+        bool            mbFillStyleSelected;
+        bool            mbClipNeedsUpdate;
+        bool            mbComplexClip;
+
+        std::vector< std::shared_ptr<SaveStruct> > vSaveStack;
+
+        sal_uInt32          mnGfxMode;
+        sal_uInt32          mnMapMode;
+
+        XForm               maXForm;
+        sal_Int32           mnDevOrgX, mnDevOrgY;
+        sal_Int32           mnDevWidth, mnDevHeight;
+        sal_Int32           mnWinOrgX, mnWinOrgY;       // aktuel window origin
+        sal_Int32           mnWinExtX, mnWinExtY;       // aktuel window extend
+        bool            mbIsMapWinSet;
+        bool            mbIsMapDevSet;
+
+        sal_Int32           mnPixX, mnPixY;             // Reference Device in pixel
+        sal_Int32           mnMillX, mnMillY;           // Reference Device in Mill
+        tools::Rectangle           mrclFrame;                  // rectangle in logical units 1/100th mm
+        tools::Rectangle           mrclBounds;
+
+        GDIMetaFile*        mpGDIMetaFile;
+
+        void                UpdateLineStyle();
+        void                UpdateFillStyle();
+
+        Point               ImplMap(const Point& rPt);
+        Point               ImplScale(const Point& rPt);
+        Size                ImplMap(const Size& rSize, bool bDoWorldTransform = true);
+        tools::Rectangle           ImplMap(const tools::Rectangle& rRectangle);
+        void                ImplMap(vcl::Font& rFont);
+        tools::Polygon&     ImplMap(tools::Polygon& rPolygon);
+        tools::PolyPolygon& ImplMap(tools::PolyPolygon& rPolyPolygon);
+        void                ImplScale(tools::Polygon& rPolygon);
+        tools::PolyPolygon& ImplScale(tools::PolyPolygon& rPolyPolygon);
+        void                ImplResizeObjectArry(sal_uInt32 nNewEntry);
+        void                ImplSetNonPersistentLineColorTransparenz();
+        void                ImplDrawClippedPolyPolygon(const tools::PolyPolygon& rPolyPoly);
+        void                ImplDrawBitmap(const Point& rPos, const Size& rSize, const BitmapEx& rBitmap);
+
+    public:
+
+        void                SetDevByWin(); //Hack to set varying defaults for incompletely defined files.
+        void                SetDevOrg(const Point& rPoint);
+        void                SetDevOrgOffset(sal_Int32 nXAdd, sal_Int32 nYAdd);
+        void                SetDevExt(const Size& rSize, bool regular = true);
+        void                ScaleDevExt(double fX, double fY);
+
+        void                SetWinOrg(const Point& rPoint, bool bIsEMF = false);
+        void                SetWinOrgOffset(sal_Int32 nX, sal_Int32 nY);
+        void                SetWinExt(const Size& rSize, bool bIsEMF = false);
+        void                ScaleWinExt(double fX, double fY);
+
+        void                SetrclBounds(const tools::Rectangle& rRect);
+        void                SetrclFrame(const tools::Rectangle& rRect);
+        void                SetRefPix(const Size& rSize);
+        void                SetRefMill(const Size& rSize);
+
+        void                SetMapMode(sal_uInt32 mnMapMode);
+        void                SetWorldTransform(const XForm& rXForm);
+        void                ModifyWorldTransform(const XForm& rXForm, sal_uInt32 nMode);
+
+        void                Push();
+        void                Pop();
+
+        WMFRasterOp         SetRasterOp(WMFRasterOp nRasterOp);
+        void                StrokeAndFillPath(bool bStroke, bool bFill);
+
+        void                SetGfxMode(sal_Int32 nGfxMode) { mnGfxMode = nGfxMode; };
+        sal_Int32           GetGfxMode() const { return mnGfxMode; };
+        void                SetBkMode(BkMode nMode);
+        void                SetBkColor(const Color& rColor);
+        void                SetTextColor(const Color& rColor);
+        void                SetTextAlign(sal_uInt32 nAlign);
+
+        void                CreateObject(std::unique_ptr<GDIObj> pObject);
+        void                CreateObjectIndexed(sal_Int32 nIndex, std::unique_ptr<GDIObj> pObject);
+
+        void                CreateObject()
+        {
+            CreateObject(o3tl::make_unique<GDIObj>());
+        }
+
+        void                DeleteObject(sal_Int32 nIndex);
+        void                SelectObject(sal_Int32 nIndex);
+        rtl_TextEncoding    GetCharSet() { return maFont.GetCharSet(); };
+        const vcl::Font&    GetFont() const { return maFont; }
+        void                SetTextLayoutMode(ComplexTextLayoutFlags nLayoutMode);
+
+        void                ClearPath() { aPathObj.Init(); };
+        void                ClosePath() { aPathObj.ClosePath(); };
+        const tools::PolyPolygon& GetPathObj() { return aPathObj; };
+
+        void                MoveTo(const Point& rPoint, bool bRecordPath = false);
+        void                LineTo(const Point& rPoint, bool bRecordPath = false);
+        void                DrawPixel(const Point& rSource, const Color& rColor);
+        void                DrawRect(const tools::Rectangle& rRect, bool bEdge = true);
+        void                DrawRoundRect(const tools::Rectangle& rRect, const Size& rSize);
+        void                DrawEllipse(const tools::Rectangle& rRect);
+        void                DrawArc(
+            const tools::Rectangle& rRect,
+            const Point& rStartAngle,
+            const Point& rEndAngle,
+            bool bDrawTo = false
+        );
+        void                DrawPie(
+            const tools::Rectangle& rRect,
+            const Point& rStartAngle,
+            const Point& rEndAngle
+        );
+        void                DrawChord(
+            const tools::Rectangle& rRect,
+            const Point& rStartAngle,
+            const Point& rEndAngle
+        );
+        void                DrawPolygon(tools::Polygon& rPolygon, bool bRecordPath);
+        void                DrawPolyPolygon(tools::PolyPolygon& rPolyPolygon, bool bRecordPath = false);
+        void                DrawPolyLine(tools::Polygon& rPolygon,
+            bool bDrawTo = false,
+            bool bRecordPath = false
+        );
+        void                DrawPolyBezier(tools::Polygon& rPolygin,
+            bool bDrawTo,
+            bool bRecordPath
+        );
+        void                DrawText(Point& rPosition,
+            OUString& rString,
+            long* pDXArry = nullptr,
+            long* pDYArry = nullptr,
+            bool bRecordPath = false,
+            sal_Int32 nGraphicsMode = GM_COMPATIBLE);
+
+        void                ResolveBitmapActions(std::vector<std::unique_ptr<BSaveStruct>>& rSaveList);
+
+        void                IntersectClipRect(const tools::Rectangle& rRect);
+        void                ExcludeClipRect(const tools::Rectangle& rRect);
+        void                MoveClipRegion(const Size& rSize);
+        void                SetClipPath(
+            const tools::PolyPolygon& rPolyPoly,
+            sal_Int32 nClippingMode,
+            bool bIsMapped
+        );
+        void                SetDefaultClipPath();
+        void                UpdateClipRegion();
+        void                AddFromGDIMetaFile(GDIMetaFile& rGDIMetaFile);
+
+        void                PassEMFPlus(void* pBuffer, sal_uInt32 nLength);
+        void                PassEMFPlusHeaderInfo();
+
+        explicit            MtfToolsWriter(GDIMetaFile& rGDIMetaFile);
+        ~MtfToolsWriter();
+    };
+
+    class MtfTools
+    {
+    protected:
+        std::unique_ptr<MtfToolsWriter> pOut;
+        SvStream*               pWMF;               // the WMF/EMF file to be read
+
+        sal_uInt32              nStartPos, nEndPos;
+        std::vector<std::unique_ptr<BSaveStruct>>    aBmpSaveList;
+
+        FilterConfigItem*   pFilterConfigItem;
+
+        css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator;
+
+        // assures aSampledBrush is the actual brush of the GDIMetaFile
+
+        Color               ReadColor();
+        void                Callback(sal_uInt16 nPercent);
+
+        MtfTools(
+            GDIMetaFile& rGDIMetaFile,
+            SvStream& rStreamWMF,
+            FilterConfigItem* pConfigItem
+        );
+        ~MtfTools();
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/emfio/inc/wmfreader.hxx b/emfio/inc/wmfreader.hxx
new file mode 100644
index 000000000000..734becbb5886
--- /dev/null
+++ b/emfio/inc/wmfreader.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_EMFIO_INC_WMFREADER_HXX
+#define INCLUDED_EMFIO_INC_WMFREADER_HXX
+
+#include <mtftools.hxx>
+#include <tools/stream.hxx>
+
+namespace emfio
+{
+    struct WMF_EXTERNALHEADER
+    {
+        sal_uInt16 xExt;
+        sal_uInt16 yExt;
+
+        /** One of the following values:
+        <ul>
+        <li>MM_TEXT</li>
+        <li>MM_LOMETRIC</li>
+        <li>MM_HIMETRIC</li>
+        <li>MM_LOENGLISH</li>
+        <li>MM_HIENGLISH</li>
+        <li>MM_TWIPS</li>
+        <li>MM_ISOTROPIC</li>
+        <li>MM_ANISOTROPIC</li>
+        </ul>
+        If this value is 0, then no external mapmode has been defined,
+        the internal one should then be used.
+        */
+        sal_uInt16 mapMode;
+
+        WMF_EXTERNALHEADER() :
+            xExt(0),
+            yExt(0),
+            mapMode(0)
+        {
+        }
+    };
+
+    class WmfReader : public MtfTools
+    {
+    private:
+
+        sal_uInt16      nUnitsPerInch;
+        sal_uInt32      nRecSize;
+
+        // embedded EMF data
+        std::unique_ptr<SvMemoryStream> pEMFStream;
+
+        // total number of comment records containing EMF data
+        sal_uInt32      nEMFRecCount;
+
+        // number of EMF records read
+        sal_uInt32      nEMFRec;
+
+        // total size of embedded EMF data
+        sal_uInt32      nEMFSize;
+
+        sal_uInt32      nSkipActions;
+        sal_uInt32      nCurrentAction;
+
+        WMF_EXTERNALHEADER* pExternalHeader;
+
+        // reads header of the WMF-Datei
+        bool        ReadHeader();
+
+        // reads parameters of the record with the functionnumber nFunction.
+        void            ReadRecordParams(sal_uInt16 nFunction);
+
+        Point           ReadPoint();                // reads and converts a point (first X then Y)
+        Point           ReadYX();                   // reads and converts a point (first Y then X)
+        tools::Rectangle       ReadRectangle();            // reads and converts a rectangle
+        Size            ReadYXExt();
+        void            GetPlaceableBound(tools::Rectangle& rSize, SvStream* pStrm);
+
+    public:
+
+        WmfReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile,
+            FilterConfigItem* pConfigItem,
+            WMF_EXTERNALHEADER* pExtHeader = nullptr);
+
+        // read WMF file from stream and fill the GDIMetaFile
+        void ReadWMF();
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/emfio/source/emfuno/xemfparser.cxx b/emfio/source/emfuno/xemfparser.cxx
index 3b6e9ad731fa..e532d903e047 100644
--- a/emfio/source/emfuno/xemfparser.cxx
+++ b/emfio/source/emfuno/xemfparser.cxx
@@ -37,6 +37,9 @@
 #include <unotools/ucbstreamhelper.hxx>
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
 
+#include <wmfreader.hxx>
+#include <emfreader.hxx>
+
 //#include <com/sun/star/xml/sax/XParser.hpp>
 //#include <com/sun/star/xml/sax/Parser.hpp>
 //#include <com/sun/star/xml/sax/InputSource.hpp>
@@ -116,7 +119,7 @@ namespace emfio
 
             if (xEmfStream.is())
             {
-                static bool bTestCode(true);
+                static bool bTestCode(false);
 
                 if (bTestCode)
                 {
@@ -168,59 +171,55 @@ namespace emfio
                     // new parser here
                     bool bBla = true;
 
+                    // rouch check - import and conv to primitive
+                    GDIMetaFile aMtf;
+                    std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream(xEmfStream));
+                    sal_uInt32 nMetaType(0);
+                    sal_uInt32 nOrgPos = pStream->Tell();
+
+                    SvStreamEndian nOrigNumberFormat = pStream->GetEndian();
+                    pStream->SetEndian(SvStreamEndian::LITTLE);
+
+                    pStream->Seek(0x28);
+                    pStream->ReadUInt32(nMetaType);
+                    pStream->Seek(nOrgPos);
+
+                    if (nMetaType == 0x464d4520)
+                    {
+                        emfio::EmfReader(*pStream, aMtf, nullptr).ReadEnhWMF();
+                    }
+                    else
+                    {
+                        emfio::WmfReader(*pStream, aMtf, nullptr).ReadWMF();
+                    }
+
+                    pStream->SetEndian(nOrigNumberFormat);
+                    Size aSize(aMtf.GetPrefSize());
+
+                    if (aMtf.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
+                    {
+                        aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, MapUnit::Map100thMM);
+                    }
+                    else
+                    {
+                        aSize = OutputDevice::LogicToLogic(aSize, aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
+                    }
+
+                    const basegfx::B2DHomMatrix aMetafileTransform(
+                        basegfx::tools::createScaleB2DHomMatrix(
+                            aSize.Width(),
+                            aSize.Height()));
+
+                    // force to use decomposition directly to get rid of the metafile
+                    const css::uno::Sequence< css::beans::PropertyValue > aViewParameters;
+                    drawinglayer::primitive2d::MetafilePrimitive2D aMetafilePrimitive2D(
+                        aMetafileTransform,
+                        aMtf);
+                    aRetval.append(aMetafilePrimitive2D.getDecomposition(aViewParameters));
+
 
 
 
-                    //                // local document handler
-                    //                SvgDocHdl* pSvgDocHdl = new SvgDocHdl(aAbsolutePath);
-                    //                uno::Reference< xml::sax::XDocumentHandler > xSvgDocHdl(pSvgDocHdl);
-                    //
-                    //                try
-                    //                {
-                    //                    // prepare ParserInputSrouce
-                    //                    xml::sax::InputSource myInputSource;
-                    //                    myInputSource.aInputStream = xEmfStream;
-                    //
-                    //                    // get parser
-                    //                    uno::Reference< xml::sax::XParser > xParser(
-                    //                        xml::sax::Parser::create(context_));
-                    //                    // fdo#60471 need to enable internal entities because
-                    //                    // certain ... popular proprietary products write SVG files
-                    //                    // that use entities to define XML namespaces.
-                    //                    uno::Reference<lang::XInitialization> const xInit(xParser,
-                    //                            uno::UNO_QUERY_THROW);
-                    //                    uno::Sequence<uno::Any> args(1);
-                    //                    args[0] <<= OUString("DoSmeplease");
-                    //                    xInit->initialize(args);
-                    //
-                    //                    // connect parser and filter
-                    //                    xParser->setDocumentHandler(xSvgDocHdl);
-                    //
-                    //                    // finally, parse the stream to a hierarchy of
-                    //                    // SVGGraphicPrimitive2D which will be embedded to the
-                    //                    // primitive sequence. Their decompositions will in the
-                    //                    // end create local low-level primitives, thus SVG will
-                    //                    // be processable from all our processors
-                    //                    xParser->parseStream(myInputSource);
-                    //                }
-                    //                catch(const uno::Exception& e)
-                    //                {
-                    //                    SAL_WARN( "svg", "Parse error! : " << e.Message);
-                    //                }
-                    //
-                    //                // decompose to primitives
-                    //                const SvgNodeVector& rResults = pSvgDocHdl->getSvgDocument().getSvgNodeVector();
-                    //                const sal_uInt32 nCount(rResults.size());
-                    //
-                    //                for(sal_uInt32 a(0); a < nCount; a++)
-                    //                {
-                    //                    SvgNode* pCandidate = rResults[a];
-                    //
-                    //                    if(Display_none != pCandidate->getDisplay())
-                    //                    {
-                    //                        pCandidate->decomposeSvgNode(aRetval, false);
-                    //                    }
-                    //                }
                 }
             }
             else
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
new file mode 100644
index 000000000000..48c98db4c5fb
--- /dev/null
+++ b/emfio/source/reader/emfreader.cxx
@@ -0,0 +1,1941 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <emfreader.hxx>
+
+#include <osl/endian.h>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <vcl/dibtools.hxx>
+#include <o3tl/make_unique.hxx>
+
+#include <memory>
+
+#ifdef DBG_UTIL
+#include <tools/stream.hxx>
+#include <vcl/pngwrite.hxx>
+#endif
+
+using namespace std;
+
+// GDI-Array
+
+#define EMR_HEADER                      1
+#define EMR_POLYBEZIER                  2
+#define EMR_POLYGON                     3
+#define EMR_POLYLINE                    4
+#define EMR_POLYBEZIERTO                5
+#define EMR_POLYLINETO                  6
+#define EMR_POLYPOLYLINE                7
+#define EMR_POLYPOLYGON                 8
+#define EMR_SETWINDOWEXTEX              9
+#define EMR_SETWINDOWORGEX              10
+#define EMR_SETVIEWPORTEXTEX            11
+#define EMR_SETVIEWPORTORGEX            12
+#define EMR_SETBRUSHORGEX               13
+#define EMR_EOF                         14
+#define EMR_SETPIXELV                   15
+#define EMR_SETMAPPERFLAGS              16
+#define EMR_SETMAPMODE                  17
+#define EMR_SETBKMODE                   18
+#define EMR_SETPOLYFILLMODE             19
+#define EMR_SETROP2                     20
+#define EMR_SETSTRETCHBLTMODE           21
+#define EMR_SETTEXTALIGN                22
+#define EMR_SETCOLORADJUSTMENT          23
+#define EMR_SETTEXTCOLOR                24
+#define EMR_SETBKCOLOR                  25
+#define EMR_OFFSETCLIPRGN               26
+#define EMR_MOVETOEX                    27
+#define EMR_SETMETARGN                  28
+#define EMR_EXCLUDECLIPRECT             29
+#define EMR_INTERSECTCLIPRECT           30
+#define EMR_SCALEVIEWPORTEXTEX          31
+#define EMR_SCALEWINDOWEXTEX            32
+#define EMR_SAVEDC                      33
+#define EMR_RESTOREDC                   34
+#define EMR_SETWORLDTRANSFORM           35
+#define EMR_MODIFYWORLDTRANSFORM        36
+#define EMR_SELECTOBJECT                37
+#define EMR_CREATEPEN                   38
+#define EMR_CREATEBRUSHINDIRECT         39
+#define EMR_DELETEOBJECT                40
+#define EMR_ANGLEARC                    41
+#define EMR_ELLIPSE                     42
+#define EMR_RECTANGLE                   43
+#define EMR_ROUNDRECT                   44
+#define EMR_ARC                         45
+#define EMR_CHORD                       46
+#define EMR_PIE                         47
+#define EMR_SELECTPALETTE               48
+#define EMR_CREATEPALETTE               49
+#define EMR_SETPALETTEENTRIES           50
+#define EMR_RESIZEPALETTE               51
+#define EMR_REALIZEPALETTE              52
+#define EMR_EXTFLOODFILL                53
+#define EMR_LINETO                      54
+#define EMR_ARCTO                       55
+#define EMR_POLYDRAW                    56
+#define EMR_SETARCDIRECTION             57
+#define EMR_SETMITERLIMIT               58
+#define EMR_BEGINPATH                   59
+#define EMR_ENDPATH                     60
+#define EMR_CLOSEFIGURE                 61
+#define EMR_FILLPATH                    62
+#define EMR_STROKEANDFILLPATH           63
+#define EMR_STROKEPATH                  64
+#define EMR_FLATTENPATH                 65
+#define EMR_WIDENPATH                   66
+#define EMR_SELECTCLIPPATH              67
+#define EMR_ABORTPATH                   68
+
+#define EMR_COMMENT                     70          // Contains arbitrary private data.
+// Comment Identifiers:
+#define EMR_COMMENT_EMFPLUS             0x2B464D45  // Contains embedded EMF+ records.
+#define EMR_COMMENT_EMFSPOOL            0x00000000  // Contains embedded EMFSPOOL records.
+#define EMR_COMMENT_PUBLIC              0x43494447  // Specify extensions to EMF processing.
+
+#define EMR_FILLRGN                     71
+#define EMR_FRAMERGN                    72
+#define EMR_INVERTRGN                   73
+#define EMR_PAINTRGN                    74
+#define EMR_EXTSELECTCLIPRGN            75
+#define EMR_BITBLT                      76
+#define EMR_STRETCHBLT                  77
+#define EMR_MASKBLT                     78
+#define EMR_PLGBLT                      79
+#define EMR_SETDIBITSTODEVICE           80
+#define EMR_STRETCHDIBITS               81
+#define EMR_EXTCREATEFONTINDIRECTW      82
+#define EMR_EXTTEXTOUTA                 83
+#define EMR_EXTTEXTOUTW                 84
+#define EMR_POLYBEZIER16                85
+#define EMR_POLYGON16                   86
+#define EMR_POLYLINE16                  87
+#define EMR_POLYBEZIERTO16              88
+#define EMR_POLYLINETO16                89
+#define EMR_POLYPOLYLINE16              90
+#define EMR_POLYPOLYGON16               91
+#define EMR_POLYDRAW16                  92
+#define EMR_CREATEMONOBRUSH             93
+#define EMR_CREATEDIBPATTERNBRUSHPT     94
+#define EMR_EXTCREATEPEN                95
+#define EMR_POLYTEXTOUTA                96
+#define EMR_POLYTEXTOUTW                97
+
+// WINDOWS VERSION >= 0x400
+#define EMR_SETICMMODE                  98
+#define EMR_CREATECOLORSPACE            99
+#define EMR_SETCOLORSPACE              100
+#define EMR_DELETECOLORSPACE           101
+#define EMR_GLSRECORD                  102
+#define EMR_GLSBOUNDEDRECORD           103
+#define EMR_PIXELFORMAT                104
+
+// WINDOWS VERSION >= 0x500
+#define EMR_DRAWESCAPE                 105
+#define EMR_EXTESCAPE                  106
+#define EMR_STARTDOC                   107
+#define EMR_SMALLTEXTOUT               108
+#define EMR_FORCEUFIMAPPING            109
+#define EMR_NAMEDESCAPE                110
+#define EMR_COLORCORRECTPALETTE        111
+#define EMR_SETICMPROFILEA             112
+#define EMR_SETICMPROFILEW             113
+#define EMR_ALPHABLEND                 114
+#define EMR_ALPHADIBBLEND              115
+#define EMR_TRANSPARENTBLT             116
+#define EMR_TRANSPARENTDIB             117
+#define EMR_GRADIENTFILL               118
+#define EMR_SETLINKEDUFIS              119
+#define EMR_SETTEXTJUSTIFICATION       120
+
+namespace
+{
+
+const char *
+record_type_name(sal_uInt32 nRecType)
+{
+#ifndef SAL_LOG_INFO
+    (void) nRecType;
+    return "";
+#else
+    switch( nRecType )
+    {
+    case EMR_HEADER: return "HEADER";
+    case EMR_POLYBEZIER: return "POLYBEZIER";
+    case EMR_POLYGON: return "POLYGON";
+    case EMR_POLYLINE: return "POLYLINE";
+    case EMR_POLYBEZIERTO: return "POLYBEZIERTO";
+    case EMR_POLYLINETO: return "POLYLINETO";
+    case EMR_POLYPOLYLINE: return "POLYPOLYLINE";
+    case EMR_POLYPOLYGON: return "POLYPOLYGON";
+    case EMR_SETWINDOWEXTEX: return "SETWINDOWEXTEX";
+    case EMR_SETWINDOWORGEX: return "SETWINDOWORGEX";
+    case EMR_SETVIEWPORTEXTEX: return "SETVIEWPORTEXTEX";
+    case EMR_SETVIEWPORTORGEX: return "SETVIEWPORTORGEX";
+    case EMR_SETBRUSHORGEX: return "SETBRUSHORGEX";
+    case EMR_EOF: return "EOF";
+    case EMR_SETPIXELV: return "SETPIXELV";
+    case EMR_SETMAPPERFLAGS: return "SETMAPPERFLAGS";
+    case EMR_SETMAPMODE: return "SETMAPMODE";
+    case EMR_SETBKMODE: return "SETBKMODE";
+    case EMR_SETPOLYFILLMODE: return "SETPOLYFILLMODE";
+    case EMR_SETROP2: return "SETROP2";
+    case EMR_SETSTRETCHBLTMODE: return "SETSTRETCHBLTMODE";
+    case EMR_SETTEXTALIGN: return "SETTEXTALIGN";
+    case EMR_SETCOLORADJUSTMENT: return "SETCOLORADJUSTMENT";
+    case EMR_SETTEXTCOLOR: return "SETTEXTCOLOR";
+    case EMR_SETBKCOLOR: return "SETBKCOLOR";
+    case EMR_OFFSETCLIPRGN: return "OFFSETCLIPRGN";
+    case EMR_MOVETOEX: return "MOVETOEX";
+    case EMR_SETMETARGN: return "SETMETARGN";
+    case EMR_EXCLUDECLIPRECT: return "EXCLUDECLIPRECT";
+    case EMR_INTERSECTCLIPRECT: return "INTERSECTCLIPRECT";
+    case EMR_SCALEVIEWPORTEXTEX: return "SCALEVIEWPORTEXTEX";
+    case EMR_SCALEWINDOWEXTEX: return "SCALEWINDOWEXTEX";
+    case EMR_SAVEDC: return "SAVEDC";
+    case EMR_RESTOREDC: return "RESTOREDC";
+    case EMR_SETWORLDTRANSFORM: return "SETWORLDTRANSFORM";
+    case EMR_MODIFYWORLDTRANSFORM: return "MODIFYWORLDTRANSFORM";
+    case EMR_SELECTOBJECT: return "SELECTOBJECT";
+    case EMR_CREATEPEN: return "CREATEPEN";
+    case EMR_CREATEBRUSHINDIRECT: return "CREATEBRUSHINDIRECT";
+    case EMR_DELETEOBJECT: return "DELETEOBJECT";
+    case EMR_ANGLEARC: return "ANGLEARC";
+    case EMR_ELLIPSE: return "ELLIPSE";
+    case EMR_RECTANGLE: return "RECTANGLE";
+    case EMR_ROUNDRECT: return "ROUNDRECT";
+    case EMR_ARC: return "ARC";
+    case EMR_CHORD: return "CHORD";
+    case EMR_PIE: return "PIE";
+    case EMR_SELECTPALETTE: return "SELECTPALETTE";
+    case EMR_CREATEPALETTE: return "CREATEPALETTE";
+    case EMR_SETPALETTEENTRIES: return "SETPALETTEENTRIES";
+    case EMR_RESIZEPALETTE: return "RESIZEPALETTE";
+    case EMR_REALIZEPALETTE: return "REALIZEPALETTE";
+    case EMR_EXTFLOODFILL: return "EXTFLOODFILL";
+    case EMR_LINETO: return "LINETO";
+    case EMR_ARCTO: return "ARCTO";
+    case EMR_POLYDRAW: return "POLYDRAW";
+    case EMR_SETARCDIRECTION: return "SETARCDIRECTION";
+    case EMR_SETMITERLIMIT: return "SETMITERLIMIT";
+    case EMR_BEGINPATH: return "BEGINPATH";
+    case EMR_ENDPATH: return "ENDPATH";
+    case EMR_CLOSEFIGURE: return "CLOSEFIGURE";
+    case EMR_FILLPATH: return "FILLPATH";
+    case EMR_STROKEANDFILLPATH: return "STROKEANDFILLPATH";
+    case EMR_STROKEPATH: return "STROKEPATH";
+    case EMR_FLATTENPATH: return "FLATTENPATH";
+    case EMR_WIDENPATH: return "WIDENPATH";
+    case EMR_SELECTCLIPPATH: return "SELECTCLIPPATH";
+    case EMR_ABORTPATH: return "ABORTPATH";
+    case EMR_COMMENT: return "COMMENT";
+    case EMR_FILLRGN: return "FILLRGN";
+    case EMR_FRAMERGN: return "FRAMERGN";
+    case EMR_INVERTRGN: return "INVERTRGN";
+    case EMR_PAINTRGN: return "PAINTRGN";
+    case EMR_EXTSELECTCLIPRGN: return "EXTSELECTCLIPRGN";
+    case EMR_BITBLT: return "BITBLT";
+    case EMR_STRETCHBLT: return "STRETCHBLT";
+    case EMR_MASKBLT: return "MASKBLT";
+    case EMR_PLGBLT: return "PLGBLT";
+    case EMR_SETDIBITSTODEVICE: return "SETDIBITSTODEVICE";
+    case EMR_STRETCHDIBITS: return "STRETCHDIBITS";
+    case EMR_EXTCREATEFONTINDIRECTW: return "EXTCREATEFONTINDIRECTW";
+    case EMR_EXTTEXTOUTA: return "EXTTEXTOUTA";
+    case EMR_EXTTEXTOUTW: return "EXTTEXTOUTW";
+    case EMR_POLYBEZIER16: return "POLYBEZIER16";
+    case EMR_POLYGON16: return "POLYGON16";
+    case EMR_POLYLINE16: return "POLYLINE16";
+    case EMR_POLYBEZIERTO16: return "POLYBEZIERTO16";
+    case EMR_POLYLINETO16: return "POLYLINETO16";
+    case EMR_POLYPOLYLINE16: return "POLYPOLYLINE16";
+    case EMR_POLYPOLYGON16: return "POLYPOLYGON16";
+    case EMR_POLYDRAW16: return "POLYDRAW16";
+    case EMR_CREATEMONOBRUSH: return "CREATEMONOBRUSH";
+    case EMR_CREATEDIBPATTERNBRUSHPT: return "CREATEDIBPATTERNBRUSHPT";
+    case EMR_EXTCREATEPEN: return "EXTCREATEPEN";
+    case EMR_POLYTEXTOUTA: return "POLYTEXTOUTA";
+    case EMR_POLYTEXTOUTW: return "POLYTEXTOUTW";
+    case EMR_SETICMMODE: return "SETICMMODE";
+    case EMR_CREATECOLORSPACE: return "CREATECOLORSPACE";
+    case EMR_SETCOLORSPACE: return "SETCOLORSPACE";
+    case EMR_DELETECOLORSPACE: return "DELETECOLORSPACE";
+    case EMR_GLSRECORD: return "GLSRECORD";
+    case EMR_GLSBOUNDEDRECORD: return "GLSBOUNDEDRECORD";
+    case EMR_PIXELFORMAT: return "PIXELFORMAT";
+    case EMR_DRAWESCAPE: return "DRAWESCAPE";
+    case EMR_EXTESCAPE: return "EXTESCAPE";
+    case EMR_STARTDOC: return "STARTDOC";
+    case EMR_SMALLTEXTOUT: return "SMALLTEXTOUT";
+    case EMR_FORCEUFIMAPPING: return "FORCEUFIMAPPING";
+    case EMR_NAMEDESCAPE: return "NAMEDESCAPE";
+    case EMR_COLORCORRECTPALETTE: return "COLORCORRECTPALETTE";
+    case EMR_SETICMPROFILEA: return "SETICMPROFILEA";
+    case EMR_SETICMPROFILEW: return "SETICMPROFILEW";
+    case EMR_ALPHABLEND: return "ALPHABLEND";
+    case EMR_ALPHADIBBLEND: return "ALPHADIBBLEND";
+    case EMR_TRANSPARENTBLT: return "TRANSPARENTBLT";
+    case EMR_TRANSPARENTDIB: return "TRANSPARENTDIB";
+    case EMR_GRADIENTFILL: return "GRADIENTFILL";
+    case EMR_SETLINKEDUFIS: return "SETLINKEDUFIS";
+    case EMR_SETTEXTJUSTIFICATION: return "SETTEXTJUSTIFICATION";
+    default:
+        // Yes, return a pointer to a static buffer. This is a very
+        // local debugging output function, so no big deal.
+        static char buffer[11];
+        sprintf(buffer, "0x%08" SAL_PRIxUINT32, nRecType);
+        return buffer;
+    }
+#endif
+}
+
+#ifdef OSL_BIGENDIAN
+// little endian <-> big endian switch
+static float GetSwapFloat(SvStream& rStream)
+{
+    float fTmp;
+    sal_Int8* pPtr = (sal_Int8*)&fTmp;
+    rStream.ReadSChar(pPtr[3]);
+    rStream.ReadSChar(pPtr[2]);
+    rStream.ReadSChar(pPtr[1]);
+    rStream.ReadSChar(pPtr[0]);
+    return fTmp;
+}
+#endif
+
+struct BLENDFUNCTION
+{
+    unsigned char aBlendOperation;
+    unsigned char aBlendFlags;
+    unsigned char aSrcConstantAlpha;
+    unsigned char aAlphaFormat;
+
+    friend SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun);
+};
+
+SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun)
+{
+    rInStream.ReadUChar(rBlendFun.aBlendOperation);
+    rInStream.ReadUChar(rBlendFun.aBlendFlags);
+    rInStream.ReadUChar(rBlendFun.aSrcConstantAlpha);
+    rInStream.ReadUChar(rBlendFun.aAlphaFormat);
+    return rInStream;
+}
+
+bool ImplReadRegion( tools::PolyPolygon& rPolyPoly, SvStream& rStream, sal_uInt32 nLen )
+{
+    if (nLen == 0)
+        return false;
+
+    sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
+    rStream.ReadUInt32(nHdSize);
+    rStream.ReadUInt32(nType);
+    rStream.ReadUInt32(nCount);
+    rStream.ReadUInt32(nRgnSize);
+
+    if (   nCount > 0
+        && nType == RDH_RECTANGLES
+        && nLen >= ((nCount << 4) + (nHdSize - 16)))
+    {
+        sal_Int32 nx1, ny1, nx2, ny2;
+
+        for (i = 0; i < nCount; i++)
+        {
+            rStream.ReadInt32(nx1);
+            rStream.ReadInt32(ny1);
+            rStream.ReadInt32(nx2);
+            rStream.ReadInt32(ny2);
+
+            tools::Rectangle aRectangle(Point(nx1, ny1), Point(nx2, ny2));
+
+            tools::Polygon aPolygon(aRectangle);
+            tools::PolyPolygon aPolyPolyOr1(aPolygon);
+            tools::PolyPolygon aPolyPolyOr2(rPolyPoly);
+            rPolyPoly.GetUnion(aPolyPolyOr1, aPolyPolyOr2);
+            rPolyPoly = aPolyPolyOr2;
+        }
+        return true;
+    }
+    return false;
+}
+
+} // anonymous namespace
+
+namespace emfio
+{
+    EmfReader::EmfReader(SvStream& rStream,GDIMetaFile& rGDIMetaFile,FilterConfigItem* pConfigItem)
+        : MtfTools(rGDIMetaFile, rStream , pConfigItem)
+        , bRecordPath(false)
+        , nRecordCount(0)
+        , bEMFPlus(false)
+    {}
+
+    EmfReader::~EmfReader()
+    {}
+
+    void EmfReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC)
+    {
+        if (!bEMFPlus) {
+            pOut->PassEMFPlusHeaderInfo();
+
+    #if OSL_DEBUG_LEVEL > 1
+            // debug code - write the stream to debug file /tmp/emf-stream.emf
+            sal_uInt64 const pos = pWMF->Tell();
+            pWMF->Seek(0);
+            SvFileStream file( OUString( "/tmp/emf-stream.emf" ), StreamMode::WRITE | StreamMode::TRUNC );
+
+            pWMF->WriteStream(file);
+            file.Flush();
+            file.Close();
+
+            pWMF->Seek( pos );
+    #endif
+
+        }
+        bEMFPlus = true;
+
+        sal_uInt64 const pos = pWMF->Tell();
+        void *buffer = malloc( length );
+        pOut->PassEMFPlus( buffer, pWMF->ReadBytes(buffer, length) );
+        free( buffer );
+        pWMF->Seek( pos );
+
+        bHaveDC = false;
+
+        // skip in SeekRel if impossibly unavailable
+        sal_uInt32 nRemainder = length;
+
+        const size_t nRequiredHeaderSize = 12;
+        while (nRemainder >= nRequiredHeaderSize)
+        {
+            sal_uInt16 type(0), flags(0);
+            sal_uInt32 size(0), dataSize(0);
+
+            pWMF->ReadUInt16( type ).ReadUInt16( flags ).ReadUInt32( size ).ReadUInt32( dataSize );
+            nRemainder -= nRequiredHeaderSize;
+
+            SAL_INFO ("vcl.emf", "\t\tEMF+ record type: " << std::hex << type << std::dec);
+
+            // Get Device Context
+            // TODO We should use  EmfPlusRecordType::GetDC instead
+            if( type == 0x4004 )
+            {
+                bHaveDC = true;
+                SAL_INFO ("vcl.emf", "\t\tEMF+ lock DC (device context)");
+            }
+
+            // Get the length of the remaining data of this record based
+            // on the alleged size
+            sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
+                size-nRequiredHeaderSize : 0;
+            // clip to available size
+            nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
+            pWMF->SeekRel(nRemainingRecordData);
+            nRemainder -= nRemainingRecordData;
+        }
+        pWMF->SeekRel(nRemainder);
+    }
+
+    /**
+     * Reads polygons from the stream.
+     * The \<class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
+     * The \<class Drawer> parameter is a c++11 lambda for the method that will draw the polygon.
+     * skipFirst: if the first point read is the 0th point or the 1st point in the array.
+     * */
+    template <class T, class Drawer>
+    void EmfReader::ReadAndDrawPolygon(Drawer drawer, const bool skipFirst)
+    {
+        sal_uInt32 nPoints(0), nStartIndex(0);
+        pWMF->SeekRel( 16 );
+        pWMF->ReadUInt32( nPoints );
+        if (skipFirst)
+        {
+            nPoints ++;
+            nStartIndex ++;
+        }
+
+        tools::Polygon aPolygon = ReadPolygon<T>(nStartIndex, nPoints);
+        drawer(pOut, aPolygon, skipFirst, bRecordPath);
+    }
+
+    /**
+     * Reads polygons from the stream.
+     * The \<class T> parameter is for the type of the points
+     * nStartIndex: which is the starting index in the polygon of the first point read
+     * nPoints: number of points
+     * pWMF: the stream containing the polygons
+     * */
+    template <class T>
+    tools::Polygon EmfReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints)
+    {
+        bool bRecordOk = nPoints <= SAL_MAX_UINT16;
+        SAL_WARN_IF(!bRecordOk, "vcl.emf", "polygon record has more polygons than we can handle");
+        if (!bRecordOk)
+            return tools::Polygon();
+
+        tools::Polygon aPolygon(nPoints);
+        for (sal_uInt32 i = nStartIndex ; i < nPoints && pWMF->good(); i++ )
+        {
+            T nX, nY;
+            *pWMF >> nX >> nY;
+            if (!pWMF->good())
+            {
+                SAL_WARN("vcl.emf", "short read on polygon, truncating");
+                aPolygon.SetSize(i);
+                break;
+            }
+            aPolygon[ i ] = Point( nX, nY );
+        }
+
+        return aPolygon;
+    }
+
+    /**
+     * Reads a polyline from the WMF file and draws it
+     * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+     * */
+    template <class T>
+    void EmfReader::ReadAndDrawPolyLine()
+    {
+        sal_uInt32  nPoints;
+        sal_uInt32  i, nNumberOfPolylines( 0 ), nCount( 0 );
+        pWMF->SeekRel( 0x10 ); // TODO Skipping Bounds. A 128-bit WMF RectL object (specifies the bounding rectangle in device units.)
+        pWMF->ReadUInt32( nNumberOfPolylines );
+        pWMF->ReadUInt32( nCount ); // total number of points in all polylines
+        if (pWMF->Tell() >= nEndPos)
+            return;
+
+        // taking the amount of points of each polygon, retrieving the total number of points
+        if ( pWMF->good() &&
+             ( nNumberOfPolylines < SAL_MAX_UINT32 / sizeof( sal_uInt16 ) ) &&
+             ( nNumberOfPolylines * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() )
+           )
+        {
+            std::unique_ptr< sal_uInt32[] > pnPolylinePointCount( new sal_uInt32[ nNumberOfPolylines ] );
+            for ( i = 0; i < nNumberOfPolylines && pWMF->good(); i++ )
+            {
+                pWMF->ReadUInt32( nPoints );
+                pnPolylinePointCount[ i ] = nPoints;
+            }
+            // Get polyline points:
+            for ( i = 0; ( i < nNumberOfPolylines ) && pWMF->good(); i++ )
+            {
+                tools::Polygon aPolygon = ReadPolygon< T >( 0, pnPolylinePointCount[ i ] );
+                pOut->DrawPolyLine( aPolygon, false, bRecordPath );
+            }
+        }
+    }
+
+    // these are referenced from inside the templates
+
+    SvStream& operator>>(SvStream& rStream, sal_Int16 &n)
+    {
+        return rStream.ReadInt16(n);
+    }
+
+    SvStream& operator>>(SvStream& rStream, sal_Int32 &n)
+    {
+        return rStream.ReadInt32(n);
+    }
+
+    /**
+     * Reads a poly polygon from the WMF file and draws it.
+     * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+     * */
+    template <class T>
+    void EmfReader::ReadAndDrawPolyPolygon()
+    {
+        sal_uInt32 nPoly(0), nGesPoints(0), nReadPoints(0);
+        pWMF->SeekRel( 0x10 );
+        // Number of polygons
+        pWMF->ReadUInt32( nPoly ).ReadUInt32( nGesPoints );
+        if (pWMF->Tell() >= nEndPos)
+            return;
+        if (!pWMF->good())
+            return;
+        //check against numeric overflowing
+        if (nGesPoints >= SAL_MAX_UINT32 / sizeof(Point))
+            return;
+        if (nPoly >= SAL_MAX_UINT32 / sizeof(sal_uInt16))
+            return;
+        if (nPoly * sizeof(sal_uInt16) > nEndPos - pWMF->Tell())
+            return;
+
+        // Get number of points in each polygon
+        std::vector<sal_uInt16> aPoints(nPoly);
+        for (sal_uInt32 i = 0; i < nPoly && pWMF->good(); ++i)
+        {
+            sal_uInt32 nPoints(0);
+            pWMF->ReadUInt32( nPoints );
+            aPoints[i] = (sal_uInt16)nPoints;
+        }
+        if ( pWMF->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - pWMF->Tell() ) )
+        {
+            // Get polygon points
+            tools::PolyPolygon aPolyPoly(nPoly, nPoly);
+            for (sal_uInt32 i = 0; i < nPoly && pWMF->good(); ++i)
+            {
+                const sal_uInt16 nPointCount(aPoints[i]);
+                std::vector<Point> aPtAry(nPointCount);
+                for (sal_uInt16 j = 0; j < nPointCount && pWMF->good(); ++j)
+                {
+                    T nX(0), nY(0);
+                    *pWMF >> nX >> nY;
+                    aPtAry[j] = Point( nX, nY );
+                    ++nReadPoints;
+                }
+
+                aPolyPoly.Insert(tools::Polygon(aPtAry.size(), aPtAry.data()));
+            }
+
+            pOut->DrawPolyPolygon(aPolyPoly, bRecordPath);
+        }
+
+        OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
+    }
+
+    bool EmfReader::ReadEnhWMF()
+    {
+        sal_uInt32  nStretchBltMode = 0;
+        sal_uInt32  nNextPos(0),
+                    nW(0), nH(0), nColor(0), nIndex(0),
+                    nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
+        sal_Int32   nX32(0), nY32(0), nx32(0), ny32(0);
+
+        bool    bStatus = ReadHeader();
+        bool    bHaveDC = false;
+
+        static bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == nullptr );
+
+        while( bStatus && nRecordCount-- && pWMF->good())
+        {
+            sal_uInt32  nRecType(0), nRecSize(0);
+            pWMF->ReadUInt32(nRecType).ReadUInt32(nRecSize);
+
+            if ( !pWMF->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) )     // Parameters are always divisible by 4
+            {
+                bStatus = false;
+                break;
+            }
+
+            auto nCurPos = pWMF->Tell();
+
+            if (nEndPos < nCurPos - 8)
+            {
+                bStatus = false;
+                break;
+            }
+
+            const sal_uInt32 nMaxPossibleRecSize = nEndPos - (nCurPos - 8);
+            if (nRecSize > nMaxPossibleRecSize)
+            {
+                bStatus = false;
+                break;
+            }
+
+            nNextPos = nCurPos + (nRecSize - 8);
+
+            if(  !aBmpSaveList.empty()
+              && ( nRecType != EMR_STRETCHBLT )
+              && ( nRecType != EMR_STRETCHDIBITS )
+              ) {
+                pOut->ResolveBitmapActions( aBmpSaveList );
+            }
+
+            bool bFlag = false;
+
+            SAL_INFO ("vcl.emf", "0x" << std::hex << (nNextPos - nRecSize) <<  "-0x" << nNextPos << " " << record_type_name(nRecType) << " size: " <<  nRecSize << std::dec);
+
+            if( bEnableEMFPlus && nRecType == EMR_COMMENT ) {
+                sal_uInt32 length;
+
+                pWMF->ReadUInt32( length );
+
+                SAL_INFO("vcl.emf", "\tGDI comment, length: " << length);
+
+                if( pWMF->good() && length >= 4 && length <= pWMF->remainingSize() ) {
+                    sal_uInt32 nCommentId;
+
+                    pWMF->ReadUInt32( nCommentId );
+
+                    SAL_INFO ("vcl.emf", "\t\tbegin " << (char)(nCommentId & 0xff) << (char)((nCommentId & 0xff00) >> 8) << (char)((nCommentId & 0xff0000) >> 16) << (char)((nCommentId & 0xff000000) >> 24) << " id: 0x" << std::hex << nCommentId << std::dec);
+
+                    if( nCommentId == EMR_COMMENT_EMFPLUS && nRecSize >= 12 )
+                    {
+                        // [MS-EMF] 2.3.3: DataSize includes both CommentIdentifier and CommentRecordParm fields.
+                        // We have already read 4-byte CommentIdentifier, so reduce length appropriately
+                        ReadEMFPlusComment( length-4, bHaveDC );
+                    }
+                    else if( nCommentId == EMR_COMMENT_PUBLIC && nRecSize >= 12 )
+                    {
+                        // TODO: ReadGDIComment()
+                    }
+                    else if( nCommentId == EMR_COMMENT_EMFSPOOL && nRecSize >= 12 )
+                    {
+                        // TODO Implement reading EMFSPOOL comment
+
+                    }
+                    else
+                    {
+                        SAL_INFO ("vcl.emf", "\t\tunknown id: 0x" << std::hex << nCommentId << std::dec);
+                    }
+                }
+            }
+            else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
+            {
+                switch( nRecType )
+                {
+                    case EMR_POLYBEZIERTO :
+                        ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+                                                       { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, true );
+                    break;
+                    case EMR_POLYBEZIER :
+                        ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+                                                       { pWinMtfOutput->DrawPolyBezier( rPolygon, aTo, aRecordPath ); }, false );
+                    break;
+
+                    case EMR_POLYGON :
+                        ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool /*aTo*/, bool aRecordPath )
+                                                       { pWinMtfOutput->DrawPolygon( rPolygon, aRecordPath ); }, false );
+                    break;
+
+                    case EMR_POLYLINETO :
+                        ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+                                                       { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, true );
+                    break;
+
+                    case EMR_POLYLINE :
+                        ReadAndDrawPolygon<sal_Int32>( [] ( std::unique_ptr<MtfToolsWriter> &pWinMtfOutput, tools::Polygon& rPolygon, bool aTo, bool aRecordPath )
+                                                       { pWinMtfOutput->DrawPolyLine( rPolygon, aTo, aRecordPath ); }, false );
+                    break;
+
+                    case EMR_POLYPOLYLINE :
+                        ReadAndDrawPolyLine<sal_Int32>();
+                    break;
+
+                    case EMR_POLYPOLYGON :
+                        ReadAndDrawPolyPolygon<sal_Int32>();
+                    break;
+
+                    case EMR_SETWINDOWEXTEX :
+                    {
+                        pWMF->ReadUInt32( nW ).ReadUInt32( nH );
+                        pOut->SetWinExt( Size( nW, nH ), true);
+                    }
+                    break;
+
+                    case EMR_SETWINDOWORGEX :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        pOut->SetWinOrg( Point( nX32, nY32 ), true);
+                    }
+                    break;
+
+                    case EMR_SCALEWINDOWEXTEX :
+                    {
+                        pWMF->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
+                        pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+                    }
+                    break;
+
+                    case EMR_SETVIEWPORTORGEX :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        pOut->SetDevOrg( Point( nX32, nY32 ) );
+                    }
+                    break;
+
+                    case EMR_SCALEVIEWPORTEXTEX :
+                    {
+                        pWMF->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
+                        pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+                    }
+                    break;
+
+                    case EMR_SETVIEWPORTEXTEX :
+                    {
+                        pWMF->ReadUInt32( nW ).ReadUInt32( nH );
+                        pOut->SetDevExt( Size( nW, nH ) );
+                    }
+                    break;
+
+                    case EMR_EOF :
+                        nRecordCount = 0;
+                    break;
+
+                    case EMR_SETPIXELV :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
+                    }
+                    break;
+
+                    case EMR_SETMAPMODE :
+                    {
+                        sal_uInt32 nMapMode;
+                        pWMF->ReadUInt32( nMapMode );
+                        pOut->SetMapMode( nMapMode );
+                    }
+                    break;
+
+                    case EMR_SETBKMODE :
+                    {
+                        pWMF->ReadUInt32( nDat32 );
+                        pOut->SetBkMode( static_cast<BkMode>(nDat32) );
+                    }
+                    break;
+
+                    case EMR_SETPOLYFILLMODE :
+                    break;
+
+                    case EMR_SETROP2 :
+                    {
+                        pWMF->ReadUInt32( nDat32 );
+                        pOut->SetRasterOp( (WMFRasterOp)nDat32 );
+                    }
+                    break;
+
+                    case EMR_SETSTRETCHBLTMODE :
+                    {
+                        pWMF->ReadUInt32( nStretchBltMode );
+                    }
+                    break;
+
+                    case EMR_SETTEXTALIGN :
+                    {
+                        pWMF->ReadUInt32( nDat32 );
+                        pOut->SetTextAlign( nDat32 );
+                    }
+                    break;
+
+                    case EMR_SETTEXTCOLOR :
+                    {
+                        pOut->SetTextColor( ReadColor() );
+                    }
+                    break;
+
+                    case EMR_SETBKCOLOR :
+                    {
+                        pOut->SetBkColor( ReadColor() );
+                    }
+                    break;
+
+                    case EMR_OFFSETCLIPRGN :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        pOut->MoveClipRegion( Size( nX32, nY32 ) );
+                    }
+                    break;
+
+                    case EMR_MOVETOEX :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
+                    }
+                    break;
+
+                    case EMR_INTERSECTCLIPRECT :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
+                        pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+                    }
+                    break;
+
+                    case EMR_SAVEDC :
+                    {
+                        pOut->Push();
+                    }
+                    break;
+
+                    case EMR_RESTOREDC :
+                    {
+                        pOut->Pop();
+                    }
+                    break;
+
+                    case EMR_SETWORLDTRANSFORM :
+                    {
+                        XForm aTempXForm;
+                        *pWMF >> aTempXForm;
+                        pOut->SetWorldTransform( aTempXForm );
+                    }
+                    break;
+
+                    case EMR_MODIFYWORLDTRANSFORM :
+                    {
+                        sal_uInt32  nMode;
+                        XForm   aTempXForm;
+                        *pWMF >> aTempXForm;
+                        pWMF->ReadUInt32( nMode );
+                        pOut->ModifyWorldTransform( aTempXForm, nMode );
+                    }
+                    break;
+
+                    case EMR_SELECTOBJECT :
+                    {
+                        pWMF->ReadUInt32( nIndex );
+                        pOut->SelectObject( nIndex );
+                    }
+                    break;
+
+                    case EMR_CREATEPEN :
+                    {
+                        pWMF->ReadUInt32( nIndex );
+                        if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+                        {
+
+                            LineInfo    aLineInfo;
+                            sal_uInt32      nStyle;
+                            Size        aSize;
+                            // #fdo39428 Remove SvStream operator>>(long&)
+                            sal_Int32 nTmpW(0), nTmpH(0);
+
+                            pWMF->ReadUInt32( nStyle ).ReadInt32( nTmpW ).ReadInt32( nTmpH );
+                            aSize.Width() = nTmpW;
+                            aSize.Height() = nTmpH;
+
+                            if ( aSize.Width() )
+                                aLineInfo.SetWidth( aSize.Width() );
+
+                            bool bTransparent = false;
+                            switch( nStyle & PS_STYLE_MASK )
+                            {
+                                case PS_DASHDOTDOT :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 1 );
+                                    aLineInfo.SetDotCount( 2 );
+                                break;
+                                case PS_DASHDOT :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 1 );
+                                    aLineInfo.SetDotCount( 1 );
+                                break;
+                                case PS_DOT :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 0 );
+                                    aLineInfo.SetDotCount( 1 );
+                                break;
+                                case PS_DASH :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 1 );
+                                    aLineInfo.SetDotCount( 0 );
+                                break;
+                                case PS_NULL :
+                                    bTransparent = true;
+                                    aLineInfo.SetStyle( LineStyle::NONE );
+                                break;
+                                case PS_INSIDEFRAME :
+                                case PS_SOLID :
+                                default :
+                                    aLineInfo.SetStyle( LineStyle::Solid );
+                            }
+                            switch( nStyle & PS_ENDCAP_STYLE_MASK )
+                            {
+                                case PS_ENDCAP_ROUND :
+                                    if ( aSize.Width() )
+                                    {
+                                        aLineInfo.SetLineCap( css::drawing::LineCap_ROUND );
+                                        break;
+                                    }
+                                    SAL_FALLTHROUGH;
+                                case PS_ENDCAP_SQUARE :
+                                    if ( aSize.Width() )
+                                    {
+                                        aLineInfo.SetLineCap( css::drawing::LineCap_SQUARE );
+                                        break;
+                                    }
+                                    SAL_FALLTHROUGH;
+                                case PS_ENDCAP_FLAT :
+                                default :
+                                    aLineInfo.SetLineCap( css::drawing::LineCap_BUTT );
+                            }
+                            switch( nStyle & PS_JOIN_STYLE_MASK )
+                            {
+                                case PS_JOIN_ROUND :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Round );
+                                break;
+                                case PS_JOIN_MITER :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Miter );
+                                break;
+                                case PS_JOIN_BEVEL :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Bevel );
+                                break;
+                                default :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::NONE );
+                            }
+                            pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfLineStyle>( ReadColor(), aLineInfo, bTransparent ));
+                        }
+                    }
+                    break;
+
+                    case EMR_EXTCREATEPEN :
+                    {
+                        sal_Int32   elpHatch;
+                        sal_uInt32  offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
+                        Color       aColorRef;
+
+                        pWMF->ReadUInt32( nIndex );
+                        if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+                        {
+                            pWMF->ReadUInt32( offBmi ).ReadUInt32( cbBmi ).ReadUInt32( offBits ).ReadUInt32( cbBits ). ReadUInt32( nStyle ).ReadUInt32( nWidth ).ReadUInt32( nBrushStyle );
+                             aColorRef = ReadColor();
+                             pWMF->ReadInt32( elpHatch ).ReadUInt32( elpNumEntries );
+
+                            LineInfo    aLineInfo;
+                            if ( nWidth )
+                                aLineInfo.SetWidth( nWidth );
+
+                            bool bTransparent = false;
+
+                            switch( nStyle & PS_STYLE_MASK )
+                            {
+                                case PS_DASHDOTDOT :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 1 );
+                                    aLineInfo.SetDotCount( 2 );
+                                break;
+                                case PS_DASHDOT :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 1 );
+                                    aLineInfo.SetDotCount( 1 );
+                                break;
+                                case PS_DOT :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 0 );
+                                    aLineInfo.SetDotCount( 1 );
+                                break;
+                                case PS_DASH :
+                                    aLineInfo.SetStyle( LineStyle::Dash );
+                                    aLineInfo.SetDashCount( 1 );
+                                    aLineInfo.SetDotCount( 0 );
+                                break;
+                                case PS_NULL :
+                                    bTransparent = true;
+                                    aLineInfo.SetStyle( LineStyle::NONE );
+                                break;
+
+                                case PS_INSIDEFRAME :
+                                case PS_SOLID :
+                                default :
+                                    aLineInfo.SetStyle( LineStyle::Solid );
+                            }
+                            switch( nStyle & PS_ENDCAP_STYLE_MASK )
+                            {
+                                case PS_ENDCAP_ROUND :
+                                    if ( aLineInfo.GetWidth() )
+                                    {
+                                        aLineInfo.SetLineCap( css::drawing::LineCap_ROUND );
+                                        break;
+                                    }
+                                    SAL_FALLTHROUGH;
+                                case PS_ENDCAP_SQUARE :
+                                    if ( aLineInfo.GetWidth() )
+                                    {
+                                        aLineInfo.SetLineCap( css::drawing::LineCap_SQUARE );
+                                        break;
+                                    }
+                                    SAL_FALLTHROUGH;
+                                case PS_ENDCAP_FLAT :
+                                default :
+                                    aLineInfo.SetLineCap( css::drawing::LineCap_BUTT );
+                            }
+                            switch( nStyle & PS_JOIN_STYLE_MASK )
+                            {
+                                case PS_JOIN_ROUND :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Round );
+                                break;
+                                case PS_JOIN_MITER :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Miter );
+                                break;
+                                case PS_JOIN_BEVEL :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Bevel );
+                                break;
+                                default :
+                                    aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::NONE );
+                            }
+                            pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfLineStyle>( aColorRef, aLineInfo, bTransparent ));
+                        }
+                    }
+                    break;
+
+                    case EMR_CREATEBRUSHINDIRECT :
+                    {
+                        sal_uInt32  nStyle;
+                        pWMF->ReadUInt32( nIndex );
+                        if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+                        {
+                            pWMF->ReadUInt32( nStyle );
+                            pOut->CreateObjectIndexed(nIndex, o3tl::make_unique<WinMtfFillStyle>( ReadColor(), ( nStyle == BS_HOLLOW ) ));
+                        }
+                    }
+                    break;
+
+                    case EMR_DELETEOBJECT :
+                    {
+                        pWMF->ReadUInt32( nIndex );
+                        if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+                            pOut->DeleteObject( nIndex );
+                    }
+                    break;
+
+                    case EMR_ELLIPSE :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
+                        pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+                    }
+                    break;
+
+                    case EMR_RECTANGLE :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
+                        pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+                    }
+                    break;
+
+                    case EMR_ROUNDRECT :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nW ).ReadUInt32( nH );
+                        Size aSize( Size( nW, nH ) );
+                        pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
+                    }
+                    break;
+
+                    case EMR_ARC :
+                    {
+                        sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+                        pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+                    }
+                    break;
+
+                    case EMR_CHORD :
+                    {
+                        sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+                        pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+                    }
+                    break;
+
+                    case EMR_PIE :
+                    {
+                        sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+                        const tools::Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
+
+                        // #i73608# OutputDevice deviates from WMF
+                        // semantics. start==end means full ellipse here.
+                        if( nStartX == nEndX && nStartY == nEndY )
+                            pOut->DrawEllipse( aRect );
+                        else
+                            pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+                    }
+                    break;
+
+                    case EMR_LINETO :
+                    {
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
+                        pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
+                    }
+                    break;
+
+                    case EMR_ARCTO :
+                    {
+                        sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+                        pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
+                        pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), true );
+                    }
+                    break;
+
+                    case EMR_BEGINPATH :
+                    {
+                        pOut->ClearPath();
+                        bRecordPath = true;
+                    }
+                    break;
+
+                    case EMR_ABORTPATH :
+                        pOut->ClearPath();
+                        SAL_FALLTHROUGH;
+                    case EMR_ENDPATH :
+                        bRecordPath = false;
+                    break;
+
+                    case EMR_CLOSEFIGURE :
+                        pOut->ClosePath();
+                    break;
+
+                    case EMR_FILLPATH :
+                        pOut->StrokeAndFillPath( false, true );
+                    break;
+
+                    case EMR_STROKEANDFILLPATH :
+                        pOut->StrokeAndFillPath( true, true );
+                    break;
+
+                    case EMR_STROKEPATH :
+                        pOut->StrokeAndFillPath( true, false );
+                    break;
+
+                    case EMR_SELECTCLIPPATH :
+                    {
+                        sal_Int32 nClippingMode;
+                        pWMF->ReadInt32(nClippingMode);
+                        pOut->SetClipPath(pOut->GetPathObj(), nClippingMode, true);
+                    }
+                    break;
+
+                    case EMR_EXTSELECTCLIPRGN :
+                    {
+                        sal_Int32 nClippingMode, cbRgnData;
+                        pWMF->ReadInt32(cbRgnData);
+                        pWMF->ReadInt32(nClippingMode);
+
+                        // This record's region data should be ignored if mode
+                        // is RGN_COPY - see EMF spec section 2.3.2.2
+                        if (nClippingMode == RGN_COPY)
+                        {
+                            pOut->SetDefaultClipPath();
+                        }
+                        else
+                        {
+                            tools::PolyPolygon aPolyPoly;
+                            if (cbRgnData)
+                                ImplReadRegion(aPolyPoly, *pWMF, nRecSize);
+                            pOut->SetClipPath(aPolyPoly, nClippingMode, false);
+                        }
+
+                    }
+                    break;
+
+                    case EMR_ALPHABLEND:
+                    {
+                        sal_Int32 xDest(0), yDest(0), cxDest(0), cyDest(0);
+
+                        BLENDFUNCTION aFunc;
+                        sal_Int32 xSrc(0), ySrc(0), cxSrc(0), cySrc(0);
+                        XForm xformSrc;
+                        sal_uInt32 BkColorSrc(0), iUsageSrc(0), offBmiSrc(0);
+                        sal_uInt32 cbBmiSrc(0), offBitsSrc(0), cbBitsSrc(0);
+
+                        sal_uInt32   nStart = pWMF->Tell() - 8;
+                        pWMF->SeekRel( 0x10 );
+
+                        pWMF->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest );
+                        *pWMF >> aFunc;
+                        pWMF->ReadInt32( xSrc ).ReadInt32( ySrc );
+                        *pWMF >> xformSrc;
+                        pWMF->ReadUInt32( BkColorSrc ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
+                                   .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc ).ReadInt32( cxSrc ).ReadInt32( cySrc ) ;
+
+                        sal_uInt32  dwRop = SRCAND|SRCINVERT;
+                        tools::Rectangle   aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
+
+                        if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
+                            bStatus = false;
+                        else
+                        {
+                            const sal_uInt32 nSourceSize = cbBmiSrc + cbBitsSrc + 14;
+                            bool bSafeRead = nSourceSize <= (nEndPos - nStartPos);
+                            sal_uInt32 nDeltaToDIB5HeaderSize(0);
+                            const bool bReadAlpha(0x01 == aFunc.aAlphaFormat);
+                            if (bSafeRead && bReadAlpha)
+                            {
+                                // we need to read alpha channel data if AlphaFormat of BLENDFUNCTION is
+                                // AC_SRC_ALPHA (==0x01). To read it, create a temp DIB-File which is ready
+                                // for DIB-5 format
+                                const sal_uInt32 nHeaderSize = getDIBV5HeaderSize();
+                                if (cbBmiSrc > nHeaderSize)
+                                    bSafeRead = false;
+                                else
+                                    nDeltaToDIB5HeaderSize = nHeaderSize - cbBmiSrc;
+                            }
+                            if (bSafeRead)
+                            {
+                                const sal_uInt32 nTargetSize(cbBmiSrc + nDeltaToDIB5HeaderSize + cbBitsSrc + 14);
+                                char* pBuf = new char[ nTargetSize ];
+                                SvMemoryStream aTmp( pBuf, nTargetSize, StreamMode::READ | StreamMode::WRITE );
+
+                                aTmp.ObjectOwnsMemory( true );
+
+                                // write BM-Header (14 bytes)
+                                aTmp.WriteUChar( 'B' )
+                                    .WriteUChar( 'M' )
+                                    .WriteUInt32( cbBitsSrc )
+                                    .WriteUInt16( 0 )
+                                    .WriteUInt16( 0 )
+                                    .WriteUInt32( cbBmiSrc + nDeltaToDIB5HeaderSize + 14 );
+
+                                // copy DIBInfoHeader from source (cbBmiSrc bytes)
+                                pWMF->Seek( nStart + offBmiSrc );
+                                pWMF->ReadBytes(pBuf + 14, cbBmiSrc);
+
+                                if (bReadAlpha)
+                                {
+                                    // need to add values for all stuff that DIBV5Header is bigger
+                                    // than DIBInfoHeader, all values are correctly initialized to zero,
+                                    // so we can use memset here
+                                    memset(pBuf + cbBmiSrc + 14, 0, nDeltaToDIB5HeaderSize);
+                                }
+
+                                // copy bitmap data from source (offBitsSrc bytes)
+                                pWMF->Seek( nStart + offBitsSrc );
+                                pWMF->ReadBytes(pBuf + 14 + nDeltaToDIB5HeaderSize + cbBmiSrc, cbBitsSrc);
+                                aTmp.Seek( 0 );
+
+                                // prepare to read and fill BitmapEx
+                                BitmapEx aBitmapEx;
+
+                                if(bReadAlpha)
+                                {
+                                    Bitmap aBitmap;
+                                    AlphaMask aAlpha;
+
+                                    if(ReadDIBV5(aBitmap, aAlpha, aTmp))
+                                    {
+                                        aBitmapEx = BitmapEx(aBitmap, aAlpha);
+                                    }
+                                }
+                                else
+                                {
+                                    Bitmap aBitmap;
+
+                                    if(ReadDIB(aBitmap, aTmp, true))
+                                    {
+                                        if(0xff != aFunc.aSrcConstantAlpha)
+                                        {
+                                            // add const alpha channel
+                                            aBitmapEx = BitmapEx(
+                                                aBitmap,
+                                                AlphaMask(aBitmap.GetSizePixel(), &aFunc.aSrcConstantAlpha));
+                                        }
+                                        else
+                                        {
+                                            // just use Bitmap
+                                            aBitmapEx = BitmapEx(aBitmap);
+                                        }
+                                    }
+                                }
+
+                                if(!aBitmapEx.IsEmpty())
+                                {
+                                    // test if it is sensible to crop
+                                    if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+                                        ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+                                            ( xSrc + cxSrc < aBitmapEx.GetSizePixel().Width() ) &&
+                                                ( ySrc + cySrc < aBitmapEx.GetSizePixel().Height() ) )
+                                    {
+                                        const tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+
+                                        aBitmapEx.Crop( aCropRect );
+                                    }
+
+    #ifdef DBG_UTIL
+                                    static bool bDoSaveForVisualControl(false);
+
+                                    if(bDoSaveForVisualControl)
+                                    {
+                                        SvFileStream aNew("c:\\metafile_content.png", StreamMode::WRITE|StreamMode::TRUNC);
+                                        vcl::PNGWriter aPNGWriter(aBitmapEx);
+                                        aPNGWriter.Write(aNew);
+                                    }
+    #endif
+                                    aBmpSaveList.emplace_back(new BSaveStruct(aBitmapEx, aRect, dwRop));
+                                }
+                            }
+                        }
+                    }
+                    break;
+
+                    case EMR_BITBLT :   // PASSTHROUGH INTENDED
+                    case EMR_STRETCHBLT :
+                    {
+                        sal_Int32   xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
+                        sal_uInt32  dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
+                        XForm   xformSrc;
+
+                        sal_uInt32  nStart = pWMF->Tell() - 8;
+
+                        pWMF->SeekRel( 0x10 );
+                        pWMF->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest ).ReadUInt32( dwRop ).ReadInt32( xSrc ).ReadInt32( ySrc )
+                                >> xformSrc;
+                        pWMF->ReadUInt32( nColor ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
+                                   .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc );
+
+                        if ( nRecType == EMR_STRETCHBLT )
+                            pWMF->ReadInt32( cxSrc ).ReadInt32( cySrc );
+                        else
+                            cxSrc = cySrc = 0;
+
+                        Bitmap      aBitmap;
+                        tools::Rectangle   aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
+
+                        if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
+                            bStatus = false;
+                        else
+                        {
+                            sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
+                            if ( nSize <= ( nEndPos - nStartPos ) )
+                            {
+                                char* pBuf = new char[ nSize ];
+                                SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
+                                aTmp.ObjectOwnsMemory( true );
+                                aTmp.WriteUChar( 'B' )
+                                    .WriteUChar( 'M' )
+                                    .WriteUInt32( cbBitsSrc )
+                                    .WriteUInt16( 0 )
+                                    .WriteUInt16( 0 )
+                                    .WriteUInt32( cbBmiSrc + 14 );
+                                pWMF->Seek( nStart + offBmiSrc );
+                                pWMF->ReadBytes(pBuf + 14, cbBmiSrc);
+                                pWMF->Seek( nStart + offBitsSrc );
+                                pWMF->ReadBytes(pBuf + 14 + cbBmiSrc, cbBitsSrc);
+                                aTmp.Seek( 0 );
+                                ReadDIB(aBitmap, aTmp, true);
+
+                                // test if it is sensible to crop
+                                if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+                                    ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+                                        ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
+                                            ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
+                                {
+                                    tools::Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+                                    aBitmap.Crop( aCropRect );
+                                }
+                                aBmpSaveList.emplace_back(new BSaveStruct(aBitmap, aRect, dwRop));
+                            }
+                        }
+                    }
+                    break;
+
+                    case EMR_STRETCHDIBITS :
+                    {
+                        sal_Int32   xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
+                        sal_uInt32  offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list