[Libreoffice-commits] core.git: cppcanvas/Library_cppcanvas.mk cppcanvas/source

Mark Page aptitude at btconnect.com
Mon Jan 23 11:46:00 UTC 2017


 cppcanvas/Library_cppcanvas.mk                     |    7 
 cppcanvas/source/mtfrenderer/emfpbrush.cxx         |  313 ++++++
 cppcanvas/source/mtfrenderer/emfpbrush.hxx         |  122 ++
 cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx |  163 +++
 cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx |   47 
 cppcanvas/source/mtfrenderer/emfpfont.cxx          |   74 +
 cppcanvas/source/mtfrenderer/emfpfont.hxx          |   42 
 cppcanvas/source/mtfrenderer/emfpimage.cxx         |  100 ++
 cppcanvas/source/mtfrenderer/emfpimage.hxx         |   44 
 cppcanvas/source/mtfrenderer/emfplus.cxx           | 1047 ---------------------
 cppcanvas/source/mtfrenderer/emfppath.cxx          |  189 +++
 cppcanvas/source/mtfrenderer/emfppath.hxx          |   48 
 cppcanvas/source/mtfrenderer/emfppen.cxx           |  284 +++++
 cppcanvas/source/mtfrenderer/emfppen.hxx           |   80 +
 cppcanvas/source/mtfrenderer/emfpregion.cxx        |   94 +
 cppcanvas/source/mtfrenderer/emfpregion.hxx        |   43 
 16 files changed, 1664 insertions(+), 1033 deletions(-)

New commits:
commit f671121525b854b6776d7e0ae1ad04d50d7373dc
Author: Mark Page <aptitude at btconnect.com>
Date:   Thu Nov 24 11:33:23 2016 +0000

    Split emfplus.cxx into multiple files
    
    This helps make emfplus.cxx more readable.
    No source code was changed, only moved except these
    renamed to avoid inheritance warnings::
    EMFPBrush::transformation renamed to brush_transformation
    EMFPPen::transformation renamed to pen_transformation
    Change-Id: I6952d6300c9c459833c2dda2b715d851b9e80de7
    Reviewed-on: https://gerrit.libreoffice.org/31165
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: jan iversen <jani at documentfoundation.org>

diff --git a/cppcanvas/Library_cppcanvas.mk b/cppcanvas/Library_cppcanvas.mk
index 893918d..13841d2 100644
--- a/cppcanvas/Library_cppcanvas.mk
+++ b/cppcanvas/Library_cppcanvas.mk
@@ -50,7 +50,14 @@ $(eval $(call gb_Library_use_libraries,cppcanvas,\
 $(eval $(call gb_Library_add_exception_objects,cppcanvas,\
 	cppcanvas/source/mtfrenderer/bitmapaction \
 	cppcanvas/source/mtfrenderer/cachedprimitivebase \
+	cppcanvas/source/mtfrenderer/emfpbrush \
+	cppcanvas/source/mtfrenderer/emfpcustomlinecap \
+	cppcanvas/source/mtfrenderer/emfpfont \
+	cppcanvas/source/mtfrenderer/emfpimage \
 	cppcanvas/source/mtfrenderer/emfplus \
+	cppcanvas/source/mtfrenderer/emfppen \
+	cppcanvas/source/mtfrenderer/emfppath \
+	cppcanvas/source/mtfrenderer/emfpregion \
 	cppcanvas/source/mtfrenderer/implrenderer \
 	cppcanvas/source/mtfrenderer/lineaction \
 	cppcanvas/source/mtfrenderer/mtftools \
diff --git a/cppcanvas/source/mtfrenderer/emfpbrush.cxx b/cppcanvas/source/mtfrenderer/emfpbrush.cxx
new file mode 100755
index 0000000..9de0f4c
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpbrush.cxx
@@ -0,0 +1,313 @@
+/* -*- 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 <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfpbrush.hxx>
+#include <emfppath.hxx>
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        EMFPBrush::EMFPBrush()
+            : type(0)
+            , additionalFlags(0)
+            , wrapMode(0)
+            , areaX(0.0)
+            , areaY(0.0)
+            , areaWidth(0.0)
+            , areaHeight(0.0)
+            , hasTransformation(false)
+            , blendPoints(0)
+            , blendPositions(nullptr)
+            , blendFactors(nullptr)
+            , colorblendPoints(0)
+            , colorblendPositions(nullptr)
+            , colorblendColors(nullptr)
+            , surroundColorsNumber(0)
+            , surroundColors(nullptr)
+            , path(nullptr)
+            , hatchStyle(HatchStyleHorizontal)
+        {
+        }
+
+        EMFPBrush::~EMFPBrush()
+        {
+            if (blendPositions != nullptr) {
+                delete[] blendPositions;
+                blendPositions = nullptr;
+            }
+            if (colorblendPositions != nullptr) {
+                delete[] colorblendPositions;
+                colorblendPositions = nullptr;
+            }
+            if (colorblendColors != nullptr) {
+                delete[] colorblendColors;
+                colorblendColors = nullptr;
+            }
+            if (surroundColors != nullptr) {
+                delete[] surroundColors;
+                surroundColors = nullptr;
+            }
+            if (path) {
+                delete path;
+                path = nullptr;
+            }
+        }
+
+        void EMFPBrush::Read(SvStream& s, ImplRenderer& rR)
+        {
+            sal_uInt32 header;
+
+            s.ReadUInt32(header).ReadUInt32(type);
+
+            SAL_INFO("cppcanvas.emf", "EMF+\tbrush");
+            SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+            switch (type) {
+            case 0:
+            {
+                sal_uInt32 color;
+
+                s.ReadUInt32(color);
+                solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                SAL_INFO("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec);
+                break;
+            }
+            case 1:
+            {
+                sal_uInt32 style;
+                sal_uInt32 foregroundColor;
+                sal_uInt32 backgroundColor;
+                s.ReadUInt32(style);
+                s.ReadUInt32(foregroundColor);
+                s.ReadUInt32(backgroundColor);
+
+                hatchStyle = static_cast<EmfPlusHatchStyle>(style);
+                solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
+                secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
+                SAL_INFO("cppcanvas.emf", "EMF+\thatch style " << style << " foregroundcolor: 0x" << solidColor.AsRGBHexString() << " background 0x" << secondColor.AsRGBHexString());
+                break;
+            }
+            // path gradient
+            case 3:
+            {
+                s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
+
+                SAL_INFO("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
+
+                sal_uInt32 color;
+
+                s.ReadUInt32(color);
+                solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec);
+
+                s.ReadFloat(areaX).ReadFloat(areaY);
+                SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
+
+                s.ReadInt32(surroundColorsNumber);
+                SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
+
+                if (surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color))
+                    surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color);
+
+                surroundColors = new ::Color[surroundColorsNumber];
+                for (int i = 0; i < surroundColorsNumber; i++) {
+                    s.ReadUInt32(color);
+                    surroundColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                    if (i == 0)
+                        secondColor = surroundColors[0];
+                    SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec);
+                }
+
+                if (additionalFlags & 0x01) {
+                    sal_Int32 pathLength;
+
+                    s.ReadInt32(pathLength);
+                    SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength);
+
+                    sal_uInt64 const pos = s.Tell();
+
+                    sal_uInt32 pathHeader;
+                    sal_Int32 pathPoints, pathFlags;
+                    s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
+
+                    SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)");
+                    SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec);
+
+                    path = new EMFPPath(pathPoints);
+                    path->Read(s, pathFlags, rR);
+
+                    s.Seek(pos + pathLength);
+
+                    const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false)));
+                    areaWidth = aBounds.getWidth();
+                    areaHeight = aBounds.getHeight();
+
+                    SAL_INFO("cppcanvas.emf", "EMF+\tpolygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight());
+
+
+                    if (additionalFlags & 0x02) {
+                        SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
+                        ReadXForm(s, brush_transformation);
+                        hasTransformation = true;
+                        SAL_INFO("cppcanvas.emf",
+                            "EMF+\tm11: " << brush_transformation.eM11 << " m12: " << brush_transformation.eM12 <<
+                            "\nEMF+\tm21: " << brush_transformation.eM21 << " m22: " << brush_transformation.eM22 <<
+                            "\nEMF+\tdx: " << brush_transformation.eDx << " dy: " << brush_transformation.eDy);
+
+                    }
+                    if (additionalFlags & 0x08) {
+                        s.ReadInt32(blendPoints);
+                        SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
+                        if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
+                            blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+                        blendPositions = new float[2 * blendPoints];
+                        blendFactors = blendPositions + blendPoints;
+                        for (int i = 0; i < blendPoints; i++) {
+                            s.ReadFloat(blendPositions[i]);
+                            SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]);
+                        }
+                        for (int i = 0; i < blendPoints; i++) {
+                            s.ReadFloat(blendFactors[i]);
+                            SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]);
+                        }
+                    }
+
+                    if (additionalFlags & 0x04) {
+                        s.ReadInt32(colorblendPoints);
+                        SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
+                        if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
+                            colorblendPoints = SAL_MAX_INT32 / sizeof(float);
+                        if (sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(::Color))
+                            colorblendPoints = SAL_MAX_INT32 / sizeof(::Color);
+                        colorblendPositions = new float[colorblendPoints];
+                        colorblendColors = new ::Color[colorblendPoints];
+                        for (int i = 0; i < colorblendPoints; i++) {
+                            s.ReadFloat(colorblendPositions[i]);
+                            SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
+                        }
+                        for (int i = 0; i < colorblendPoints; i++) {
+                            s.ReadUInt32(color);
+                            colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                            SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
+                        }
+                    }
+                }
+                break;
+            }
+            // linear gradient
+            case 4:
+            {
+                s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
+
+                SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
+
+                s.ReadFloat(areaX).ReadFloat(areaY).ReadFloat(areaWidth).ReadFloat(areaHeight);
+
+                SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight);
+
+                sal_uInt32 color;
+
+                s.ReadUInt32(color);
+                solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec);
+
+                s.ReadUInt32(color);
+                secondColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec);
+
+                // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
+                s.ReadUInt32(color);
+                s.ReadUInt32(color);
+
+                if (additionalFlags & 0x02) {
+                    SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
+                    ReadXForm(s, brush_transformation);
+                    hasTransformation = true;
+                    SAL_INFO("cppcanvas.emf",
+                        "EMF+\tm11: " << brush_transformation.eM11 << " m12: " << brush_transformation.eM12 <<
+                        "\nEMF+\tm21: " << brush_transformation.eM21 << " m22: " << brush_transformation.eM22 <<
+                        "\nEMF+\tdx: " << brush_transformation.eDx << " dy: " << brush_transformation.eDy);
+                }
+                if (additionalFlags & 0x08) {
+                    s.ReadInt32(blendPoints);
+                    SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
+                    if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float)))
+                        blendPoints = SAL_MAX_INT32 / (2 * sizeof(float));
+                    blendPositions = new float[2 * blendPoints];
+                    blendFactors = blendPositions + blendPoints;
+                    for (int i = 0; i < blendPoints; i++) {
+                        s.ReadFloat(blendPositions[i]);
+                        SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]);
+                    }
+                    for (int i = 0; i < blendPoints; i++) {
+                        s.ReadFloat(blendFactors[i]);
+                        SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]);
+                    }
+                }
+
+                if (additionalFlags & 0x04) {
+                    s.ReadInt32(colorblendPoints);
+                    SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
+                    if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float))
+                        colorblendPoints = SAL_MAX_INT32 / sizeof(float);
+                    if (sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(::Color))
+                        colorblendPoints = sal_uInt32(SAL_MAX_INT32) / sizeof(::Color);
+                    colorblendPositions = new float[colorblendPoints];
+                    colorblendColors = new ::Color[colorblendPoints];
+                    for (int i = 0; i < colorblendPoints; i++) {
+                        s.ReadFloat(colorblendPositions[i]);
+                        SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]);
+                    }
+                    for (int i = 0; i < colorblendPoints; i++) {
+                        s.ReadUInt32(color);
+                        colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
+                        SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
+                    }
+                }
+
+                break;
+            }
+            default:
+                SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
+            }
+        }
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpbrush.hxx b/cppcanvas/source/mtfrenderer/emfpbrush.hxx
new file mode 100755
index 0000000..88fe7b8
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpbrush.hxx
@@ -0,0 +1,122 @@
+/* -*- 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_CPPCANVAS_SOURCE_MTFRENDERER_EMFPBRUSH_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPBRUSH_HXX
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        enum EmfPlusHatchStyle
+        {
+            HatchStyleHorizontal = 0x00000000,
+            HatchStyleVertical = 0x00000001,
+            HatchStyleForwardDiagonal = 0x00000002,
+            HatchStyleBackwardDiagonal = 0x00000003,
+            HatchStyleLargeGrid = 0x00000004,
+            HatchStyleDiagonalCross = 0x00000005,
+            HatchStyle05Percent = 0x00000006,
+            HatchStyle10Percent = 0x00000007,
+            HatchStyle20Percent = 0x00000008,
+            HatchStyle25Percent = 0x00000009,
+            HatchStyle30Percent = 0x0000000A,
+            HatchStyle40Percent = 0x0000000B,
+            HatchStyle50Percent = 0x0000000C,
+            HatchStyle60Percent = 0x0000000D,
+            HatchStyle70Percent = 0x0000000E,
+            HatchStyle75Percent = 0x0000000F,
+            HatchStyle80Percent = 0x00000010,
+            HatchStyle90Percent = 0x00000011,
+            HatchStyleLightDownwardDiagonal = 0x00000012,
+            HatchStyleLightUpwardDiagonal = 0x00000013,
+            HatchStyleDarkDownwardDiagonal = 0x00000014,
+            HatchStyleDarkUpwardDiagonal = 0x00000015,
+            HatchStyleWideDownwardDiagonal = 0x00000016,
+            HatchStyleWideUpwardDiagonal = 0x00000017,
+            HatchStyleLightVertical = 0x00000018,
+            HatchStyleLightHorizontal = 0x00000019,
+            HatchStyleNarrowVertical = 0x0000001A,
+            HatchStyleNarrowHorizontal = 0x0000001B,
+            HatchStyleDarkVertical = 0x0000001C,
+            HatchStyleDarkHorizontal = 0x0000001D,
+            HatchStyleDashedDownwardDiagonal = 0x0000001E,
+            HatchStyleDashedUpwardDiagonal = 0x0000001F,
+            HatchStyleDashedHorizontal = 0x00000020,
+            HatchStyleDashedVertical = 0x00000021,
+            HatchStyleSmallConfetti = 0x00000022,
+            HatchStyleLargeConfetti = 0x00000023,
+            HatchStyleZigZag = 0x00000024,
+            HatchStyleWave = 0x00000025,
+            HatchStyleDiagonalBrick = 0x00000026,
+            HatchStyleHorizontalBrick = 0x00000027,
+            HatchStyleWeave = 0x00000028,
+            HatchStylePlaid = 0x00000029,
+            HatchStyleDivot = 0x0000002A,
+            HatchStyleDottedGrid = 0x0000002B,
+            HatchStyleDottedDiamond = 0x0000002C,
+            HatchStyleShingle = 0x0000002D,
+            HatchStyleTrellis = 0x0000002E,
+            HatchStyleSphere = 0x0000002F,
+            HatchStyleSmallGrid = 0x00000030,
+            HatchStyleSmallCheckerBoard = 0x00000031,
+            HatchStyleLargeCheckerBoard = 0x00000032,
+            HatchStyleOutlinedDiamond = 0x00000033,
+            HatchStyleSolidDiamond = 0x00000034
+        };
+
+        struct EMFPPath;
+
+        struct EMFPBrush : public EMFPObject
+        {
+            ::Color solidColor;
+            sal_uInt32 type;
+            sal_uInt32 additionalFlags;
+
+            /* linear gradient */
+            sal_Int32 wrapMode;
+            float areaX, areaY, areaWidth, areaHeight;
+            ::Color secondColor; // first color is stored in solidColor;
+            XForm brush_transformation;
+            bool hasTransformation;
+            sal_Int32 blendPoints;
+            float* blendPositions;
+            float* blendFactors;
+            sal_Int32 colorblendPoints;
+            float* colorblendPositions;
+            ::Color* colorblendColors;
+            sal_Int32 surroundColorsNumber;
+            ::Color* surroundColors;
+            EMFPPath *path;
+            EmfPlusHatchStyle hatchStyle;
+
+            EMFPBrush();
+            virtual ~EMFPBrush() override;
+
+            sal_uInt32 GetType() const { return type; }
+            const ::Color& GetColor() const { return solidColor; }
+
+            void Read(SvStream& s, ImplRenderer& rR);
+        };
+    }
+}
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPBRUSH_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx
new file mode 100755
index 0000000..9ef4717
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.cxx
@@ -0,0 +1,163 @@
+/* -*- 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 <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+
+#include <emfpcustomlinecap.hxx>
+#include <emfppath.hxx>
+#include <emfppen.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000;
+        const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
+
+        const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
+        const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
+
+        EMFPCustomLineCap::EMFPCustomLineCap()
+            : EMFPObject()
+            , type(0)
+            , strokeStartCap(0)
+            , strokeEndCap(0)
+            , strokeJoin(0)
+            , miterLimit(0.0)
+            , mbIsFilled(false)
+        {
+        }
+
+        void EMFPCustomLineCap::SetAttributes(rendering::StrokeAttributes& aAttributes)
+        {
+            aAttributes.StartCapType = EMFPPen::lcl_convertStrokeCap(strokeStartCap);
+            aAttributes.EndCapType = EMFPPen::lcl_convertStrokeCap(strokeEndCap);
+            aAttributes.JoinType = EMFPPen::lcl_convertLineJoinType(strokeJoin);
+
+            aAttributes.MiterLimit = miterLimit;
+        }
+
+        void EMFPCustomLineCap::ReadPath(SvStream& s, ImplRenderer& rR, bool bFill)
+        {
+            sal_Int32 pathLength;
+            s.ReadInt32(pathLength);
+            SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
+
+            sal_uInt32 pathHeader;
+            sal_Int32 pathPoints, pathFlags;
+            s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
+
+            SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
+            SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec);
+
+            EMFPPath path(pathPoints);
+            path.Read(s, pathFlags, rR);
+
+            polygon = path.GetPolygon(rR, false);
+            mbIsFilled = bFill;
+
+            // transformation to convert the path to what LibreOffice
+            // expects
+            B2DHomMatrix aMatrix;
+            aMatrix.scale(1.0, -1.0);
+
+            polygon.transform(aMatrix);
+        };
+
+        void EMFPCustomLineCap::Read(SvStream& s, ImplRenderer& rR)
+        {
+            sal_uInt32 header;
+
+            s.ReadUInt32(header).ReadUInt32(type);
+
+            SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap");
+            SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+            if (type == EmfPlusCustomLineCapDataTypeDefault)
+            {
+                sal_uInt32 customLineCapDataFlags, baseCap;
+                float baseInset;
+                float widthScale;
+                float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
+
+                s.ReadUInt32(customLineCapDataFlags).ReadUInt32(baseCap).ReadFloat(baseInset)
+                    .ReadUInt32(strokeStartCap).ReadUInt32(strokeEndCap).ReadUInt32(strokeJoin)
+                    .ReadFloat(miterLimit).ReadFloat(widthScale)
+                    .ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(strokeHotSpotX).ReadFloat(strokeHotSpotY);
+
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
+
+                if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
+                {
+                    ReadPath(s, rR, true);
+                }
+
+                if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
+                {
+                    ReadPath(s, rR, false);
+                }
+            }
+            else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
+            {
+                // TODO only reads the data, does not use them [I've had
+                // no test document to be able to implement it]
+
+                sal_Int32 width, height, middleInset, fillState, lineStartCap;
+                sal_Int32 lineEndCap, lineJoin, widthScale;
+                float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
+
+                s.ReadInt32(width).ReadInt32(height).ReadInt32(middleInset).ReadInt32(fillState).ReadInt32(lineStartCap)
+                    .ReadInt32(lineEndCap).ReadInt32(lineJoin).ReadFloat(miterLimit).ReadInt32(widthScale)
+                    .ReadFloat(fillHotSpotX).ReadFloat(fillHotSpotY).ReadFloat(lineHotSpotX).ReadFloat(lineHotSpotY);
+
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
+            }
+        }
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx
new file mode 100755
index 0000000..c5b96a1
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpcustomlinecap.hxx
@@ -0,0 +1,47 @@
+/* -*- 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_CPPCANVAS_SOURCE_MTFRENDERER_EMFPCUSTOMLINECAP_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPCUSTOMLINECAP_HXX
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        struct EMFPCustomLineCap : public EMFPObject
+        {
+            sal_uInt32 type;
+            sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
+            float miterLimit;
+            basegfx::B2DPolyPolygon polygon;
+            bool mbIsFilled;
+
+            EMFPCustomLineCap();
+
+            void SetAttributes(com::sun::star::rendering::StrokeAttributes& aAttributes);
+            void ReadPath(SvStream& s, ImplRenderer& rR, bool bFill);
+            void Read(SvStream& s, ImplRenderer& rR);
+        };
+    }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPCUSTOMLINECAP_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpfont.cxx b/cppcanvas/source/mtfrenderer/emfpfont.cxx
new file mode 100755
index 0000000..2df7981
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpfont.cxx
@@ -0,0 +1,74 @@
+/* -*- 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 <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfpfont.hxx>
+
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        void EMFPFont::Read(SvMemoryStream &s)
+        {
+            sal_uInt32 header;
+            sal_uInt32 reserved;
+            sal_uInt32 length;
+
+            s.ReadUInt32(header).ReadFloat(emSize).ReadUInt32(sizeUnit).ReadInt32(fontFlags).ReadUInt32(reserved).ReadUInt32(length);
+
+            OSL_ASSERT((header >> 12) == 0xdbc01);
+
+            SAL_INFO("cppcanvas.emf", "EMF+\tfont\nEMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec);
+            SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec);
+
+            if (length > 0 && length < 0x4000)
+            {
+                rtl_uString *pStr = rtl_uString_alloc(length);
+                sal_Unicode *chars = pStr->buffer;
+
+                for (sal_uInt32 i = 0; i < length; ++i)
+                    s.ReadUtf16(chars[i]);
+
+                family = OUString(pStr, SAL_NO_ACQUIRE);
+                SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << family);
+            }
+        }
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpfont.hxx b/cppcanvas/source/mtfrenderer/emfpfont.hxx
new file mode 100755
index 0000000..aa9d0c4
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpfont.hxx
@@ -0,0 +1,42 @@
+/* -*- 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_CPPCANVAS_SOURCE_MTFRENDERER_EMFPFONT_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPFONT_HXX
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        struct EMFPFont : public EMFPObject
+        {
+            float emSize;
+            sal_uInt32 sizeUnit;
+            sal_Int32 fontFlags;
+            OUString family;
+
+            void Read(SvMemoryStream &s);
+        };
+    }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPFONT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpimage.cxx b/cppcanvas/source/mtfrenderer/emfpimage.cxx
new file mode 100755
index 0000000..c9c5176
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpimage.cxx
@@ -0,0 +1,100 @@
+/* -*- 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 <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <emfpimage.hxx>
+
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        void EMFPImage::Read(SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream)
+        {
+            sal_uInt32 header, bitmapType;
+
+            s.ReadUInt32(header).ReadUInt32(type);
+
+            SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+            if (type == 1) { // bitmap
+                s.ReadInt32(width).ReadInt32(height).ReadInt32(stride).ReadInt32(pixelFormat).ReadUInt32(bitmapType);
+                SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << std::dec);
+                if ((bitmapType != 0) || (width == 0)) { // non native formats
+                    GraphicFilter filter;
+
+                    filter.ImportGraphic(graphic, OUString(), s);
+                    SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height());
+                }
+
+            }
+            else if (type == 2) { // metafile
+                sal_Int32 mfType, mfSize;
+
+                s.ReadInt32(mfType).ReadInt32(mfSize);
+                if (bUseWholeStream)
+                    dataSize = s.remainingSize();
+                else
+                    dataSize -= 16;
+                SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize);
+
+                GraphicFilter filter;
+                // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
+                SvMemoryStream mfStream(const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), dataSize, StreamMode::READ);
+
+                filter.ImportGraphic(graphic, OUString(), mfStream);
+
+                // debug code - write the stream to debug file /tmp/emf-stream.emf
+#if OSL_DEBUG_LEVEL > 1
+                mfStream.Seek(0);
+                static sal_Int32 emfp_debug_stream_number = 0;
+                OUString emfp_debug_filename = "/tmp/emf-embedded-stream" +
+                    OUString::number(emfp_debug_stream_number++) + ".emf";
+
+                SvFileStream file(emfp_debug_filename, StreamMode::WRITE | StreamMode::TRUNC);
+
+                mfStream.WriteStream(file);
+                file.Flush();
+                file.Close();
+#endif
+            }
+        }
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfpimage.hxx b/cppcanvas/source/mtfrenderer/emfpimage.hxx
new file mode 100755
index 0000000..a30c73e
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfpimage.hxx
@@ -0,0 +1,44 @@
+/* -*- 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_CPPCANVAS_SOURCE_MTFRENDERER_EMFPIMAGE_HXX
+#define INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPIMAGE_HXX
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        struct EMFPImage : public EMFPObject
+        {
+            sal_uInt32 type;
+            sal_Int32 width;
+            sal_Int32 height;
+            sal_Int32 stride;
+            sal_Int32 pixelFormat;
+            Graphic graphic;
+
+            void Read(SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream);
+        };
+    }
+}
+
+
+#endif // INCLUDED_CPPCANVAS_SOURCE_MTFRENDERER_EMFPIMAGE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index b1c02f1..11dbf62 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -47,6 +47,14 @@
 #include <polypolyaction.hxx>
 #include <textaction.hxx>
 
+#include <emfpbrush.hxx>
+#include <emfpcustomlinecap.hxx>
+#include <emfpfont.hxx>
+#include <emfpimage.hxx>
+#include <emfppath.hxx>
+#include <emfppen.hxx>
+#include <emfpregion.hxx>
+
 namespace
 {
 
@@ -96,27 +104,6 @@ namespace
 
 #define EmfPlusRegionInitialStateInfinite 0x10000003
 
-const sal_Int32 EmfPlusLineStyleSolid = 0x00000000;
-const sal_Int32 EmfPlusLineStyleDash = 0x00000001;
-const sal_Int32 EmfPlusLineStyleDot = 0x00000002;
-const sal_Int32 EmfPlusLineStyleDashDot = 0x00000003;
-const sal_Int32 EmfPlusLineStyleDashDotDot = 0x00000004;
-const sal_Int32 EmfPlusLineStyleCustom = 0x00000005;
-
-const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000;
-const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
-
-const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
-const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
-
-const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
-const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
-
-const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
-const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
-const sal_uInt32 EmfPlusLineJoinTypeRound = 0x00000002;
-const sal_uInt32 EmfPlusLineJoinTypeMiterClipped = 0x00000003;
-
 enum EmfPlusCombineMode
 {
     EmfPlusCombineModeReplace = 0x00000000,
@@ -127,63 +114,6 @@ enum EmfPlusCombineMode
     EmfPlusCombineModeComplement = 0x00000005
 };
 
-enum EmfPlusHatchStyle
-{
-    HatchStyleHorizontal = 0x00000000,
-    HatchStyleVertical = 0x00000001,
-    HatchStyleForwardDiagonal = 0x00000002,
-    HatchStyleBackwardDiagonal = 0x00000003,
-    HatchStyleLargeGrid = 0x00000004,
-    HatchStyleDiagonalCross = 0x00000005,
-    HatchStyle05Percent = 0x00000006,
-    HatchStyle10Percent = 0x00000007,
-    HatchStyle20Percent = 0x00000008,
-    HatchStyle25Percent = 0x00000009,
-    HatchStyle30Percent = 0x0000000A,
-    HatchStyle40Percent = 0x0000000B,
-    HatchStyle50Percent = 0x0000000C,
-    HatchStyle60Percent = 0x0000000D,
-    HatchStyle70Percent = 0x0000000E,
-    HatchStyle75Percent = 0x0000000F,
-    HatchStyle80Percent = 0x00000010,
-    HatchStyle90Percent = 0x00000011,
-    HatchStyleLightDownwardDiagonal = 0x00000012,
-    HatchStyleLightUpwardDiagonal = 0x00000013,
-    HatchStyleDarkDownwardDiagonal = 0x00000014,
-    HatchStyleDarkUpwardDiagonal = 0x00000015,
-    HatchStyleWideDownwardDiagonal = 0x00000016,
-    HatchStyleWideUpwardDiagonal = 0x00000017,
-    HatchStyleLightVertical = 0x00000018,
-    HatchStyleLightHorizontal = 0x00000019,
-    HatchStyleNarrowVertical = 0x0000001A,
-    HatchStyleNarrowHorizontal = 0x0000001B,
-    HatchStyleDarkVertical = 0x0000001C,
-    HatchStyleDarkHorizontal = 0x0000001D,
-    HatchStyleDashedDownwardDiagonal = 0x0000001E,
-    HatchStyleDashedUpwardDiagonal = 0x0000001F,
-    HatchStyleDashedHorizontal = 0x00000020,
-    HatchStyleDashedVertical = 0x00000021,
-    HatchStyleSmallConfetti = 0x00000022,
-    HatchStyleLargeConfetti = 0x00000023,
-    HatchStyleZigZag = 0x00000024,
-    HatchStyleWave = 0x00000025,
-    HatchStyleDiagonalBrick = 0x00000026,
-    HatchStyleHorizontalBrick = 0x00000027,
-    HatchStyleWeave = 0x00000028,
-    HatchStylePlaid = 0x00000029,
-    HatchStyleDivot = 0x0000002A,
-    HatchStyleDottedGrid = 0x0000002B,
-    HatchStyleDottedDiamond = 0x0000002C,
-    HatchStyleShingle = 0x0000002D,
-    HatchStyleTrellis = 0x0000002E,
-    HatchStyleSphere = 0x0000002F,
-    HatchStyleSmallGrid = 0x00000030,
-    HatchStyleSmallCheckerBoard = 0x00000031,
-    HatchStyleLargeCheckerBoard = 0x00000032,
-    HatchStyleOutlinedDiamond = 0x00000033,
-    HatchStyleSolidDiamond = 0x00000034
-};
-
 const char* emfTypeToName(sal_uInt16 type)
 {
     switch(type)
@@ -234,955 +164,6 @@ namespace cppcanvas
 {
     namespace internal
     {
-        struct EMFPPath : public EMFPObject
-        {
-            ::basegfx::B2DPolyPolygon    aPolygon;
-            sal_Int32                    nPoints;
-            float*                       pPoints;
-            sal_uInt8*                   pPointTypes;
-
-        public:
-            EMFPPath (sal_Int32 _nPoints, bool bLines = false)
-            {
-                if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
-                    _nPoints = SAL_MAX_INT32/(2*sizeof(float));
-                nPoints = _nPoints;
-                pPoints = new float [nPoints*2];
-                if (!bLines)
-                    pPointTypes = new sal_uInt8 [_nPoints];
-                else
-                    pPointTypes = nullptr;
-            }
-
-            virtual ~EMFPPath () override
-            {
-                delete [] pPoints;
-                delete [] pPointTypes;
-            }
-
-            // TODO: remove rR argument when debug code is not longer needed
-            void Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
-            {
-                for (int i = 0; i < nPoints; i ++) {
-                    if (pathFlags & 0x4000) {
-                        // EMFPlusPoint: stored in signed short 16bit integer format
-                        sal_Int16 x, y;
-
-                        s.ReadInt16( x ).ReadInt16( y );
-                        SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPoint [x,y]: " << x << "," << y);
-                        pPoints [i*2] = x;
-                        pPoints [i*2 + 1] = y;
-                    } else if (!(pathFlags & 0xC000)) {
-                        // EMFPlusPointF: stored in Single (float) format
-                        s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] );
-                        SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPointF [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
-                    } else { //if (pathFlags & 0x8000)
-                        // EMFPlusPointR: points are stored in EMFPlusInteger7 or
-                        // EMFPlusInteger15 objects, see section 2.2.2.21/22
-                        SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - parse EMFPlusPointR object (section 2.2.1.6)");
-                    }
-
-                }
-
-                if (pPointTypes)
-                    for (int i = 0; i < nPoints; i ++) {
-                        s.ReadUChar( pPointTypes [i] );
-                        SAL_INFO ("cppcanvas.emf", "EMF+\tpoint type: " << (int)pPointTypes [i]);
-                    }
-
-                aPolygon.clear ();
-
-#if OSL_DEBUG_LEVEL > 1
-                const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
-
-                SAL_INFO ("cppcanvas.emf",
-                          "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << aBounds.getWidth () << "x" << aBounds.getHeight () << " (mapped)");
-#else
-                (void) rR; // avoid warnings
-#endif
-            }
-
-            ::basegfx::B2DPolyPolygon& GetPolygon (ImplRenderer& rR, bool bMapIt = true)
-            {
-                ::basegfx::B2DPolygon polygon;
-
-                aPolygon.clear ();
-
-                int last_normal = 0, p = 0;
-                ::basegfx::B2DPoint prev, mapped;
-                bool hasPrev = false;
-                for (int i = 0; i < nPoints; i ++) {
-                    if (p && pPointTypes && (pPointTypes [i] == 0)) {
-                        aPolygon.append (polygon);
-                        last_normal = i;
-                        p = 0;
-                        polygon.clear ();
-                    }
-
-                    if (bMapIt)
-                        mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
-                    else
-                        mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
-                    if (pPointTypes) {
-                        if ((pPointTypes [i] & 0x07) == 3) {
-                            if (((i - last_normal )% 3) == 1) {
-                                polygon.setNextControlPoint (p - 1, mapped);
-                                SAL_INFO ("cppcanvas.emf", "polygon append  next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
-                                continue;
-                            } else if (((i - last_normal) % 3) == 2) {
-                                prev = mapped;
-                                hasPrev = true;
-                                continue;
-                            }
-                        } else
-                            last_normal = i;
-                    }
-                    polygon.append (mapped);
-                    SAL_INFO ("cppcanvas.emf", "polygon append point: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ());
-                    if (hasPrev) {
-                        polygon.setPrevControlPoint (p, prev);
-                        SAL_INFO ("cppcanvas.emf", "polygon append  prev: " << p << " mapped: " << prev.getX () << "," << prev.getY ());
-                        hasPrev = false;
-                    }
-                    p ++;
-                    if (pPointTypes && (pPointTypes [i] & 0x80)) { // closed polygon
-                        polygon.setClosed (true);
-                        aPolygon.append (polygon);
-                        SAL_INFO ("cppcanvas.emf", "close polygon");
-                        last_normal = i + 1;
-                        p = 0;
-                        polygon.clear ();
-                    }
-                }
-
-                if (polygon.count ()) {
-                    aPolygon.append (polygon);
-
-#if OSL_DEBUG_LEVEL > 1
-                    for (unsigned int i=0; i<aPolygon.count(); i++) {
-                        polygon = aPolygon.getB2DPolygon(i);
-                        SAL_INFO ("cppcanvas.emf", "polygon: " << i);
-                        for (unsigned int j=0; j<polygon.count(); j++) {
-                            ::basegfx::B2DPoint point = polygon.getB2DPoint(j);
-                            SAL_INFO ("cppcanvas.emf", "point: " << point.getX() << "," << point.getY());
-                            if (polygon.isPrevControlPointUsed(j)) {
-                                point = polygon.getPrevControlPoint(j);
-                                SAL_INFO ("cppcanvas.emf", "prev: " << point.getX() << "," << point.getY());
-                            }
-                            if (polygon.isNextControlPointUsed(j)) {
-                                point = polygon.getNextControlPoint(j);
-                                SAL_INFO ("cppcanvas.emf", "next: " << point.getX() << "," << point.getY());
-                            }
-                        }
-                    }
-#endif
-                }
-
-                return aPolygon;
-            }
-        };
-
-        struct EMFPRegion : public EMFPObject
-        {
-            sal_Int32 parts;
-            sal_Int32 *combineMode;
-            sal_Int32 initialState;
-            float ix, iy, iw, ih;
-
-            EMFPRegion ()
-                : parts(0)
-                , combineMode(nullptr)
-                , initialState(0)
-                , ix(0.0)
-                , iy(0.0)
-                , iw(0.0)
-                , ih(0.0)
-            {
-            }
-
-            virtual ~EMFPRegion () override
-            {
-                if (combineMode) {
-                    delete [] combineMode;
-                    combineMode = nullptr;
-                }
-            }
-
-            void Read (SvStream& s)
-            {
-                sal_uInt32 header;
-
-                s.ReadUInt32( header ).ReadInt32( parts );
-
-                SAL_INFO ("cppcanvas.emf", "EMF+\tregion");
-                SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " parts: " << parts << std::dec );
-
-                if (parts) {
-                    if( parts<0 || sal_uInt32(parts)>SAL_MAX_INT32/sizeof(sal_Int32) )
-                        parts = SAL_MAX_INT32/sizeof(sal_Int32);
-
-                    combineMode = new sal_Int32 [parts];
-
-                    for (int i = 0; i < parts; i ++) {
-                        s.ReadInt32( combineMode [i] );
-                        SAL_INFO ("cppcanvas.emf", "EMF+\tcombine mode [" << i << "]: 0x" << std::hex << combineMode [i] << std::dec);
-                    }
-                }
-
-                s.ReadInt32( initialState );
-                SAL_INFO ("cppcanvas.emf", "EMF+\tinitial state: 0x" << std::hex << initialState << std::dec);
-            }
-        };
-
-        struct EMFPBrush : public EMFPObject
-        {
-            ::Color solidColor;
-            sal_uInt32 type;
-            sal_uInt32 additionalFlags;
-
-            /* linear gradient */
-            sal_Int32 wrapMode;
-            float areaX, areaY, areaWidth, areaHeight;
-            ::Color secondColor; // first color is stored in solidColor;
-            XForm transformation;
-            bool hasTransformation;
-            sal_Int32 blendPoints;
-            float* blendPositions;
-            float* blendFactors;
-            sal_Int32 colorblendPoints;
-            float* colorblendPositions;
-            ::Color* colorblendColors;
-            sal_Int32 surroundColorsNumber;
-            ::Color* surroundColors;
-            EMFPPath *path;
-            EmfPlusHatchStyle hatchStyle;
-
-        public:
-            EMFPBrush ()
-                : type(0)
-                , additionalFlags(0)
-                , wrapMode(0)
-                , areaX(0.0)
-                , areaY(0.0)
-                , areaWidth(0.0)
-                , areaHeight(0.0)
-                , hasTransformation(false)
-                , blendPoints(0)
-                , blendPositions(nullptr)
-                , blendFactors(nullptr)
-                , colorblendPoints(0)
-                , colorblendPositions(nullptr)
-                , colorblendColors(nullptr)
-                , surroundColorsNumber(0)
-                , surroundColors(nullptr)
-                , path(nullptr)
-                , hatchStyle(HatchStyleHorizontal)
-            {
-            }
-
-            virtual ~EMFPBrush () override
-            {
-                if (blendPositions != nullptr) {
-                    delete[] blendPositions;
-                    blendPositions = nullptr;
-                }
-                if (colorblendPositions != nullptr) {
-                    delete[] colorblendPositions;
-                    colorblendPositions = nullptr;
-                }
-                if (colorblendColors != nullptr) {
-                    delete[] colorblendColors;
-                    colorblendColors = nullptr;
-                }
-                if (surroundColors != nullptr) {
-                    delete[] surroundColors;
-                    surroundColors = nullptr;
-                }
-                if (path) {
-                    delete path;
-                    path = nullptr;
-                }
-            }
-
-            sal_uInt32 GetType() const { return type; }
-            const ::Color& GetColor() const { return solidColor; }
-
-            void Read (SvStream& s, ImplRenderer& rR)
-            {
-                sal_uInt32 header;
-
-                s.ReadUInt32( header ).ReadUInt32( type );
-
-                SAL_INFO ("cppcanvas.emf", "EMF+\tbrush");
-                SAL_INFO ("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec);
-
-                switch (type) {
-                case 0:
-                    {
-                        sal_uInt32 color;
-
-                        s.ReadUInt32( color );
-                        solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                        SAL_INFO ("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec);
-                        break;
-                    }
-                case 1:
-                    {
-                        sal_uInt32 style;
-                        sal_uInt32 foregroundColor;
-                        sal_uInt32 backgroundColor;
-                        s.ReadUInt32( style );
-                        s.ReadUInt32( foregroundColor );
-                        s.ReadUInt32( backgroundColor );
-
-                        hatchStyle = static_cast<EmfPlusHatchStyle>(style);
-                        solidColor  = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff);
-                        secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff);
-                        SAL_INFO ("cppcanvas.emf", "EMF+\thatch style " << style << " foregroundcolor: 0x" << solidColor.AsRGBHexString() << " background 0x" << secondColor.AsRGBHexString());
-                        break;
-                    }
-                // path gradient
-                case 3:
-                    {
-                        s.ReadUInt32( additionalFlags ).ReadInt32( wrapMode );
-
-                        SAL_INFO ("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
-
-                        sal_uInt32 color;
-
-                        s.ReadUInt32( color );
-                        solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                        SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec);
-
-                        s.ReadFloat( areaX ).ReadFloat( areaY );
-                        SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
-
-                        s.ReadInt32( surroundColorsNumber );
-                        SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
-
-                        if( surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32/sizeof(::Color) )
-                            surroundColorsNumber = SAL_MAX_INT32/sizeof(::Color);
-
-                        surroundColors = new ::Color [surroundColorsNumber];
-                        for (int i = 0; i < surroundColorsNumber; i++) {
-                            s.ReadUInt32( color );
-                            surroundColors[i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                            if (i == 0)
-                                secondColor = surroundColors [0];
-                            SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec);
-                        }
-
-                        if (additionalFlags & 0x01) {
-                            sal_Int32 pathLength;
-
-                            s.ReadInt32( pathLength );
-                            SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength);
-
-                            sal_uInt64 const pos = s.Tell ();
-
-                            sal_uInt32 pathHeader;
-                            sal_Int32 pathPoints, pathFlags;
-                            s.ReadUInt32( pathHeader ).ReadInt32( pathPoints ).ReadInt32( pathFlags );
-
-                            SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)");
-                            SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
-
-                            path = new EMFPPath (pathPoints);
-                            path->Read (s, pathFlags, rR);
-
-                            s.Seek (pos + pathLength);
-
-                            const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (path->GetPolygon (rR, false)));
-                            areaWidth = aBounds.getWidth ();
-                            areaHeight = aBounds.getHeight ();
-
-                            SAL_INFO("cppcanvas.emf", "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << " " << aBounds.getWidth () << "x" << aBounds.getHeight ());
-
-
-                        if (additionalFlags & 0x02) {
-                            SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
-                            ReadXForm( s, transformation );
-                            hasTransformation = true;
-                            SAL_INFO("cppcanvas.emf",
-                                    "EMF+\tm11: "   << transformation.eM11 << " m12: " << transformation.eM12 <<
-                                    "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
-                                    "\nEMF+\tdx: "  << transformation.eDx  << " dy: "  << transformation.eDy);
-
-                        }
-                        if (additionalFlags & 0x08) {
-                            s.ReadInt32( blendPoints );
-                            SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
-                            if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
-                                blendPoints = SAL_MAX_INT32/(2*sizeof(float));
-                            blendPositions = new float [2*blendPoints];
-                            blendFactors = blendPositions + blendPoints;
-                            for (int i=0; i < blendPoints; i ++) {
-                                s.ReadFloat( blendPositions [i] );
-                                SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
-                            }
-                            for (int i=0; i < blendPoints; i ++) {
-                                s.ReadFloat( blendFactors [i] );
-                                SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
-                            }
-                        }
-
-                        if (additionalFlags & 0x04) {
-                            s.ReadInt32( colorblendPoints );
-                            SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
-                            if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
-                                colorblendPoints = SAL_MAX_INT32/sizeof(float);
-                            if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
-                                colorblendPoints = SAL_MAX_INT32/sizeof(::Color);
-                            colorblendPositions = new float [colorblendPoints];
-                            colorblendColors = new ::Color [colorblendPoints];
-                            for (int i=0; i < colorblendPoints; i ++) {
-                                s.ReadFloat( colorblendPositions [i] );
-                                SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
-                            }
-                            for (int i=0; i < colorblendPoints; i ++) {
-                                s.ReadUInt32( color );
-                                colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                                SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
-                            }
-                        }
-                        }
-                        break;
-                    }
-                // linear gradient
-                case 4:
-                    {
-                        s.ReadUInt32( additionalFlags ).ReadInt32( wrapMode );
-
-                        SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec);
-
-                        s.ReadFloat( areaX ).ReadFloat( areaY ).ReadFloat( areaWidth ).ReadFloat( areaHeight );
-
-                        SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight);
-
-                        sal_uInt32 color;
-
-                        s.ReadUInt32( color );
-                        solidColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                        SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec);
-
-                        s.ReadUInt32( color );
-                        secondColor = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                        SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec);
-
-                        // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html
-                        s.ReadUInt32( color );
-                        s.ReadUInt32( color );
-
-                        if (additionalFlags & 0x02) {
-                            SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
-                            ReadXForm( s, transformation );
-                            hasTransformation = true;
-                            SAL_INFO("cppcanvas.emf",
-                                    "EMF+\tm11: "   << transformation.eM11 << " m12: " << transformation.eM12 <<
-                                    "\nEMF+\tm21: " << transformation.eM21 << " m22: " << transformation.eM22 <<
-                                    "\nEMF+\tdx: "  << transformation.eDx  << " dy: "  << transformation.eDy);
-                        }
-                        if (additionalFlags & 0x08) {
-                            s.ReadInt32( blendPoints );
-                            SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints);
-                            if( blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
-                                blendPoints = SAL_MAX_INT32/(2*sizeof(float));
-                            blendPositions = new float [2*blendPoints];
-                            blendFactors = blendPositions + blendPoints;
-                            for (int i=0; i < blendPoints; i ++) {
-                                s.ReadFloat( blendPositions [i] );
-                                SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions [i]);
-                            }
-                            for (int i=0; i < blendPoints; i ++) {
-                                s.ReadFloat( blendFactors [i] );
-                                SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors [i]);
-                            }
-                        }
-
-                        if (additionalFlags & 0x04) {
-                            s.ReadInt32( colorblendPoints );
-                            SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints);
-                            if( colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(float) )
-                                colorblendPoints = SAL_MAX_INT32/sizeof(float);
-                            if( sal_uInt32(colorblendPoints)>SAL_MAX_INT32/sizeof(::Color) )
-                                colorblendPoints = sal_uInt32(SAL_MAX_INT32)/sizeof(::Color);
-                            colorblendPositions = new float [colorblendPoints];
-                            colorblendColors = new ::Color [colorblendPoints];
-                            for (int i=0; i < colorblendPoints; i ++) {
-                                s.ReadFloat( colorblendPositions [i] );
-                                SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions [i]);
-                            }
-                            for (int i=0; i < colorblendPoints; i ++) {
-                                s.ReadUInt32( color );
-                                colorblendColors [i] = ::Color (0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
-                                SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
-                            }
-                        }
-
-                        break;
-                    }
-                default:
-                    SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec);
-                }
-            }
-        };
-
-        /// Convert stroke caps between EMF+ and rendering API
-        sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
-        {
-            switch (nEmfStroke)
-            {
-                case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
-                case EmfPlusLineCapTypeRound:  return rendering::PathCapType::ROUND;
-            }
-
-            // we have no mapping for EmfPlusLineCapTypeTriangle = 0x00000003,
-            // so return BUTT always
-            return rendering::PathCapType::BUTT;
-        }
-
-        sal_Int8 lcl_convertLineJoinType(sal_uInt32 nEmfLineJoin)
-        {
-            switch (nEmfLineJoin)
-            {
-                case EmfPlusLineJoinTypeMiter:        // fall-through
-                case EmfPlusLineJoinTypeMiterClipped: return rendering::PathJoinType::MITER;
-                case EmfPlusLineJoinTypeBevel:        return rendering::PathJoinType::BEVEL;
-                case EmfPlusLineJoinTypeRound:        return rendering::PathJoinType::ROUND;
-            }
-            assert(false); // Line Join type isn't in specification.
-            return 0;
-        }
-
-        struct EMFPCustomLineCap : public EMFPObject
-        {
-            sal_uInt32 type;
-            sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
-            float miterLimit;
-            basegfx::B2DPolyPolygon polygon;
-            bool mbIsFilled;
-
-        public:
-            EMFPCustomLineCap()
-                : EMFPObject()
-                , type(0)
-                , strokeStartCap(0)
-                , strokeEndCap(0)
-                , strokeJoin(0)
-                , miterLimit(0.0)
-                , mbIsFilled(false)
-            {
-            }
-
-            void SetAttributes(rendering::StrokeAttributes& aAttributes)
-            {
-                aAttributes.StartCapType = lcl_convertStrokeCap(strokeStartCap);
-                aAttributes.EndCapType = lcl_convertStrokeCap(strokeEndCap);
-                aAttributes.JoinType = lcl_convertLineJoinType(strokeJoin);
-
-                aAttributes.MiterLimit = miterLimit;
-            }
-
-            void ReadPath(SvStream& s, ImplRenderer& rR, bool bFill)
-            {
-                sal_Int32 pathLength;
-                s.ReadInt32( pathLength );
-                SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
-
-                sal_uInt32 pathHeader;
-                sal_Int32 pathPoints, pathFlags;
-                s.ReadUInt32( pathHeader ).ReadInt32( pathPoints ).ReadInt32( pathFlags );
-
-                SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
-                SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
-
-                EMFPPath path(pathPoints);
-                path.Read(s, pathFlags, rR);
-
-                polygon = path.GetPolygon(rR, false);
-                mbIsFilled = bFill;
-
-                // transformation to convert the path to what LibreOffice
-                // expects
-                B2DHomMatrix aMatrix;
-                aMatrix.scale(1.0, -1.0);
-
-                polygon.transform(aMatrix);
-            };
-
-            void Read (SvStream& s, ImplRenderer& rR)
-            {
-                sal_uInt32 header;
-
-                s.ReadUInt32( header ).ReadUInt32( type );
-
-                SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap");
-                SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
-
-                if (type == EmfPlusCustomLineCapDataTypeDefault)
-                {
-                    sal_uInt32 customLineCapDataFlags, baseCap;
-                    float baseInset;
-                    float widthScale;
-                    float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
-
-                    s.ReadUInt32( customLineCapDataFlags ).ReadUInt32( baseCap ).ReadFloat( baseInset )
-                     .ReadUInt32( strokeStartCap ).ReadUInt32( strokeEndCap ).ReadUInt32( strokeJoin )
-                     .ReadFloat( miterLimit ).ReadFloat( widthScale )
-                     .ReadFloat( fillHotSpotX ).ReadFloat( fillHotSpotY ).ReadFloat( strokeHotSpotX ).ReadFloat( strokeHotSpotY );
-
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
-
-                    if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
-                    {
-                        ReadPath(s, rR, true);
-                    }
-
-                    if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
-                    {
-                        ReadPath(s, rR, false);
-                    }
-                }
-                else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
-                {
-                    // TODO only reads the data, does not use them [I've had
-                    // no test document to be able to implement it]
-
-                    sal_Int32 width, height, middleInset, fillState, lineStartCap;
-                    sal_Int32 lineEndCap, lineJoin, widthScale;
-                    float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
-
-                    s.ReadInt32( width ).ReadInt32( height ).ReadInt32( middleInset ).ReadInt32( fillState ).ReadInt32( lineStartCap )
-                     .ReadInt32( lineEndCap ).ReadInt32( lineJoin ).ReadFloat( miterLimit ).ReadInt32( widthScale )
-                     .ReadFloat( fillHotSpotX ).ReadFloat( fillHotSpotY ).ReadFloat( lineHotSpotX ).ReadFloat( lineHotSpotY );
-
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
-                }
-            }
-        };
-
-        struct EMFPPen : public EMFPBrush
-        {
-            XForm transformation;
-            float width;
-            sal_Int32 startCap;
-            sal_Int32 endCap;
-            sal_Int32 lineJoin;
-            float mitterLimit;
-            sal_Int32 dashStyle;
-            sal_Int32 dashCap;
-            float dashOffset;
-            sal_Int32 dashPatternLen;
-            float *dashPattern;
-            sal_Int32 alignment;
-            sal_Int32 compoundArrayLen;
-            float *compoundArray;
-            sal_Int32 customStartCapLen;
-            EMFPCustomLineCap *customStartCap;
-            sal_Int32 customEndCapLen;
-            EMFPCustomLineCap *customEndCap;
-
-        public:
-            EMFPPen ()
-                : EMFPBrush()
-                , width(0.0)
-                , startCap(0)
-                , endCap(0)
-                , lineJoin(0)
-                , mitterLimit(0.0)
-                , dashStyle(0)
-                , dashCap(0)
-                , dashOffset(0.0)
-                , dashPatternLen(0)
-                , dashPattern(nullptr)
-                , alignment(0)
-                , compoundArrayLen(0)
-                , compoundArray(nullptr)
-                , customStartCapLen(0)
-                , customStartCap(nullptr)
-                , customEndCapLen(0)
-                , customEndCap(nullptr)
-            {
-            }
-
-            virtual ~EMFPPen() override
-            {
-                delete[] dashPattern;
-                delete[] compoundArray;
-                delete customStartCap;
-                delete customEndCap;
-            }
-
-            void SetStrokeWidth(rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
-            {
-#if OSL_DEBUG_LEVEL > 1
-                if (width == 0.0) {
-                    SAL_INFO ("cppcanvas.emf", "TODO: pen with zero width - using minimal which might not be correct\n");
-                }
-#endif
-                rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getLength());
-            }
-
-            void SetStrokeAttributes(rendering::StrokeAttributes& rStrokeAttributes)
-            {
-                rStrokeAttributes.JoinType = lcl_convertLineJoinType(lineJoin);
-
-                if (dashStyle != EmfPlusLineStyleSolid)
-                {
-                    const float dash[] = {3, 3};
-                    const float dot[] = {1, 3};
-                    const float dashdot[] = {3, 3, 1, 3};
-                    const float dashdotdot[] = {3, 3, 1, 3, 1, 3};
-
-                    sal_Int32 nLen = 0;
-                    const float *pPattern = nullptr;
-                    switch (dashStyle)
-                    {
-                        case EmfPlusLineStyleDash:       nLen = SAL_N_ELEMENTS(dash); pPattern = dash; break;
-                        case EmfPlusLineStyleDot:        nLen = SAL_N_ELEMENTS(dot); pPattern = dot; break;
-                        case EmfPlusLineStyleDashDot:    nLen = SAL_N_ELEMENTS(dashdot); pPattern = dashdot; break;
-                        case EmfPlusLineStyleDashDotDot: nLen = SAL_N_ELEMENTS(dashdotdot); pPattern = dashdotdot; break;
-                        case EmfPlusLineStyleCustom:     nLen = dashPatternLen; pPattern = dashPattern; break;
-                    }
-                    if (nLen > 0)
-                    {
-                        uno::Sequence<double> aDashArray(nLen);
-                        for (int i = 0; i < nLen; ++i)
-                            aDashArray[i] = pPattern[i];
-
-                        rStrokeAttributes.DashArray = aDashArray;
-                    }
-                }
-            }
-
-            void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
-            {
-                sal_uInt32 header, unknown, penFlags, unknown2;
-                int i;
-
-                s.ReadUInt32( header ).ReadUInt32( unknown ).ReadUInt32( penFlags ).ReadUInt32( unknown2 ).ReadFloat( width );
-
-                SAL_INFO("cppcanvas.emf", "EMF+\tpen");
-                SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " unknown: 0x" << unknown <<
-                            " additional flags: 0x" << penFlags << " unknown: 0x" << unknown2 << " width: " << std::dec << width );
-
-                if (penFlags & 1)
-                    ReadXForm( s, transformation );
-
-                if (penFlags & 2)
-                {
-                    s.ReadInt32( startCap );
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstartCap: 0x" << std::hex << startCap);
-                }
-                else
-                    startCap = 0;
-
-                if (penFlags & 4)
-                {
-                    s.ReadInt32( endCap );
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tendCap: 0x" << std::hex << endCap);
-                }
-                else
-                    endCap = 0;
-
-                if (penFlags & 8)
-                    s.ReadInt32( lineJoin );
-                else
-                    lineJoin = 0;
-
-                if (penFlags & 16)
-                    s.ReadFloat( mitterLimit );
-                else
-                    mitterLimit = 0;
-
-                if (penFlags & 32)
-                {
-                    s.ReadInt32( dashStyle );
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tdashStyle: 0x" << std::hex << dashStyle);
-                }
-                else
-                    dashStyle = 0;
-
-                if (penFlags & 64)
-                    s.ReadInt32( dashCap );
-                else
-                    dashCap = 0;
-
-                if (penFlags & 128)
-                    s.ReadFloat( dashOffset );
-                else
-                    dashOffset = 0;
-
-                if (penFlags & 256)
-                {
-                    dashStyle = EmfPlusLineStyleCustom;
-
-                    s.ReadInt32( dashPatternLen );
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tdashPatternLen: " << dashPatternLen);
-
-                    if( dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32/sizeof(float) )
-                        dashPatternLen = SAL_MAX_INT32/sizeof(float);
-                    dashPattern = new float [dashPatternLen];
-                    for (i = 0; i < dashPatternLen; i++)
-                    {
-                        s.ReadFloat( dashPattern [i] );
-                        SAL_INFO("cppcanvas.emf", "EMF+\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
-                    }
-                }
-                else
-                    dashPatternLen = 0;
-
-                if (penFlags & 512)
-                    s.ReadInt32( alignment );
-                else
-                    alignment = 0;
-
-                if (penFlags & 1024) {
-                    s.ReadInt32( compoundArrayLen );
-                    if( compoundArrayLen<0 || sal_uInt32(compoundArrayLen)>SAL_MAX_INT32/sizeof(float) )
-                        compoundArrayLen = SAL_MAX_INT32/sizeof(float);
-                    compoundArray = new float [compoundArrayLen];
-                    for (i = 0; i < compoundArrayLen; i++)
-                        s.ReadFloat( compoundArray [i] );
-                } else
-                    compoundArrayLen = 0;
-
-                if (penFlags & 2048)
-                {
-                    s.ReadInt32( customStartCapLen );
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomStartCapLen: " << customStartCapLen);
-                    sal_uInt64 const pos = s.Tell();
-
-                    customStartCap = new EMFPCustomLineCap();
-                    customStartCap->Read(s, rR);
-
-                    // maybe we don't read everything yet, play it safe ;-)
-                    s.Seek(pos + customStartCapLen);
-                }
-                else
-                    customStartCapLen = 0;
-
-                if (penFlags & 4096)
-                {
-                    s.ReadInt32( customEndCapLen );
-                    SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomEndCapLen: " << customEndCapLen);
-                    sal_uInt64 const pos = s.Tell();
-
-                    customEndCap = new EMFPCustomLineCap();
-                    customEndCap->Read(s, rR);
-
-                    // maybe we don't read everything yet, play it safe ;-)
-                    s.Seek(pos + customEndCapLen);
-                }
-                else
-                    customEndCapLen = 0;
-
-                EMFPBrush::Read (s, rR);
-            }
-        };
-
-        struct EMFPImage : public EMFPObject
-        {
-            sal_uInt32 type;
-            sal_Int32 width;
-            sal_Int32 height;
-            sal_Int32 stride;
-            sal_Int32 pixelFormat;
-            Graphic graphic;
-
-
-            void Read (SvMemoryStream &s, sal_uInt32 dataSize, bool bUseWholeStream)
-            {
-                sal_uInt32 header, bitmapType;
-
-                s.ReadUInt32( header ).ReadUInt32( type );
-
-                SAL_INFO("cppcanvas.emf", "EMF+\timage\nEMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec );
-
-                if (type == 1) { // bitmap
-                    s.ReadInt32( width ).ReadInt32( height ).ReadInt32( stride ).ReadInt32( pixelFormat ).ReadUInt32( bitmapType );
-                    SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: " << width << " height: " << height << " stride: " << stride << " pixelFormat: 0x" << std::hex << pixelFormat << std::dec);
-                    if ((bitmapType != 0) || (width == 0)) { // non native formats
-                        GraphicFilter filter;
-
-                        filter.ImportGraphic (graphic, OUString(), s);
-                        SAL_INFO("cppcanvas.emf", "EMF+\tbitmap width: "  << graphic.GetBitmap().GetSizePixel().Width() << " height: " << graphic.GetBitmap().GetSizePixel().Height());
-                    }
-
-                } else if (type == 2) { // metafile
-                    sal_Int32 mfType, mfSize;
-
-                    s.ReadInt32( mfType ).ReadInt32( mfSize );
-                    if (bUseWholeStream)
-                        dataSize = s.remainingSize();
-                    else
-                        dataSize -= 16;
-                    SAL_INFO("cppcanvas.emf", "EMF+\tmetafile type: " << mfType << " dataSize: " << mfSize << " real size calculated from record dataSize: " << dataSize);
-
-                    GraphicFilter filter;
-                    // workaround buggy metafiles, which have wrong mfSize set (n#705956 for example)
-                    SvMemoryStream mfStream (const_cast<char *>(static_cast<char const *>(s.GetData()) + s.Tell()), dataSize, StreamMode::READ);
-
-                    filter.ImportGraphic (graphic, OUString(), mfStream);
-
-                    // debug code - write the stream to debug file /tmp/emf-stream.emf
-#if OSL_DEBUG_LEVEL > 1
-                        mfStream.Seek(0);
-                        static sal_Int32 emfp_debug_stream_number = 0;
-                        OUString emfp_debug_filename = "/tmp/emf-embedded-stream" +
-                            OUString::number(emfp_debug_stream_number++) + ".emf";
-
-                        SvFileStream file( emfp_debug_filename, StreamMode::WRITE | StreamMode::TRUNC );
-
-                        mfStream.WriteStream(file);
-                        file.Flush();
-                        file.Close();
-#endif
-                }
-            }
-        };
-
-        struct EMFPFont : public EMFPObject
-        {
-            float emSize;
-            sal_uInt32 sizeUnit;
-            sal_Int32 fontFlags;
-            OUString family;
-
-            void Read (SvMemoryStream &s)
-            {
-                sal_uInt32 header;
-                sal_uInt32 reserved;
-                sal_uInt32 length;
-
-                s.ReadUInt32( header ).ReadFloat( emSize ).ReadUInt32( sizeUnit ).ReadInt32( fontFlags ).ReadUInt32( reserved ).ReadUInt32( length );
-
-                OSL_ASSERT( ( header >> 12 ) == 0xdbc01 );
-
-                SAL_INFO("cppcanvas.emf", "EMF+\tfont\nEMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec);
-                SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec);
-
-                if (length > 0 && length < 0x4000)
-                {
-                    rtl_uString *pStr = rtl_uString_alloc(length);
-                    sal_Unicode *chars = pStr->buffer;
-
-                    for (sal_uInt32 i = 0; i < length; ++i)
-                        s.ReadUtf16(chars[i]);
-
-                    family = OUString(pStr, SAL_NO_ACQUIRE);
-                    SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << family);
-                }
-            }
-        };
-
         void ImplRenderer::ReadRectangle (SvStream& s, float& x, float& y, float &width, float& height, bool bCompressed)
         {
             if (bCompressed) {
@@ -1368,12 +349,12 @@ namespace cppcanvas
                     if (brush->hasTransformation) {
                         ::basegfx::B2DHomMatrix aTransformation;
 
-                        aTransformation.set (0, 0, brush->transformation.eM11);
-                        aTransformation.set (0, 1, brush->transformation.eM21);
-                        aTransformation.set (0, 2, brush->transformation.eDx);
-                        aTransformation.set (1, 0, brush->transformation.eM12);
-                        aTransformation.set (1, 1, brush->transformation.eM22);
-                        aTransformation.set (1, 2, brush->transformation.eDy);
+                        aTransformation.set (0, 0, brush->brush_transformation.eM11);
+                        aTransformation.set (0, 1, brush->brush_transformation.eM21);
+                        aTransformation.set (0, 2, brush->brush_transformation.eDx);
+                        aTransformation.set (1, 0, brush->brush_transformation.eM12);
+                        aTransformation.set (1, 1, brush->brush_transformation.eM22);
+                        aTransformation.set (1, 2, brush->brush_transformation.eDy);
 
                         aTextureTransformation *= aTransformation;
                     }
diff --git a/cppcanvas/source/mtfrenderer/emfppath.cxx b/cppcanvas/source/mtfrenderer/emfppath.cxx
new file mode 100644
index 0000000..54de41b
--- /dev/null
+++ b/cppcanvas/source/mtfrenderer/emfppath.cxx
@@ -0,0 +1,189 @@
+/* -*- 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 <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/gradienttools.hxx>
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/canvastools.hxx>
+#include <implrenderer.hxx>
+#include <emfppath.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::basegfx;
+
+namespace cppcanvas
+{
+    namespace internal
+    {
+        EMFPPath::EMFPPath (sal_Int32 _nPoints, bool bLines)
+        {
+            if( _nPoints<0 || sal_uInt32(_nPoints)>SAL_MAX_INT32/(2*sizeof(float)) )
+                _nPoints = SAL_MAX_INT32/(2*sizeof(float));
+            nPoints = _nPoints;
+            pPoints = new float [nPoints*2];
+            if (!bLines)
+                pPointTypes = new sal_uInt8 [_nPoints];
+            else
+                pPointTypes = nullptr;
+        }
+
+        EMFPPath::~EMFPPath ()
+        {
+            delete [] pPoints;
+            delete [] pPointTypes;
+        }
+
+        // TODO: remove rR argument when debug code is not longer needed
+        void EMFPPath::Read (SvStream& s, sal_uInt32 pathFlags, ImplRenderer& rR)
+        {
+            for (int i = 0; i < nPoints; i ++) {
+                if (pathFlags & 0x4000) {
+                    // EMFPlusPoint: stored in signed short 16bit integer format
+                    sal_Int16 x, y;
+
+                    s.ReadInt16( x ).ReadInt16( y );
+                    SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPoint [x,y]: " << x << "," << y);
+                    pPoints [i*2] = x;
+                    pPoints [i*2 + 1] = y;
+                } else if (!(pathFlags & 0xC000)) {
+                    // EMFPlusPointF: stored in Single (float) format
+                    s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] );
+                    SAL_INFO ("cppcanvas.emf", "EMF+\tEMFPlusPointF [x,y]: " << pPoints [i*2] << "," << pPoints [i*2 + 1]);
+                } else { //if (pathFlags & 0x8000)
+                    // EMFPlusPointR: points are stored in EMFPlusInteger7 or
+                    // EMFPlusInteger15 objects, see section 2.2.2.21/22
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - parse EMFPlusPointR object (section 2.2.1.6)");
+                }
+
+            }
+
+            if (pPointTypes)
+                for (int i = 0; i < nPoints; i ++) {
+                    s.ReadUChar( pPointTypes [i] );
+                    SAL_INFO ("cppcanvas.emf", "EMF+\tpoint type: " << (int)pPointTypes [i]);
+                }
+
+            aPolygon.clear ();
+
+#if OSL_DEBUG_LEVEL > 1
+            const ::basegfx::B2DRectangle aBounds (::basegfx::tools::getRange (GetPolygon (rR)));
+
+            SAL_INFO ("cppcanvas.emf",
+                        "EMF+\tpolygon bounding box: " << aBounds.getMinX () << "," << aBounds.getMinY () << aBounds.getWidth () << "x" << aBounds.getHeight () << " (mapped)");
+#else
+            (void) rR; // avoid warnings
+#endif
+        }
+
+        ::basegfx::B2DPolyPolygon& EMFPPath::GetPolygon (ImplRenderer& rR, bool bMapIt)
+        {
+            ::basegfx::B2DPolygon polygon;
+
+            aPolygon.clear ();
+
+            int last_normal = 0, p = 0;
+            ::basegfx::B2DPoint prev, mapped;
+            bool hasPrev = false;
+            for (int i = 0; i < nPoints; i ++) {
+                if (p && pPointTypes && (pPointTypes [i] == 0)) {
+                    aPolygon.append (polygon);
+                    last_normal = i;
+                    p = 0;
+                    polygon.clear ();
+                }
+
+                if (bMapIt)
+                    mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]);
+                else
+                    mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]);
+                if (pPointTypes) {
+                    if ((pPointTypes [i] & 0x07) == 3) {
+                        if (((i - last_normal )% 3) == 1) {
+                            polygon.setNextControlPoint (p - 1, mapped);
+                            SAL_INFO ("cppcanvas.emf", "polygon append  next: " << p - 1 << " mapped: " << mapped.getX () << "," << mapped.getY ());
+                            continue;
+                        } else if (((i - last_normal) % 3) == 2) {
+                            prev = mapped;
+                            hasPrev = true;
+                            continue;
+                        }
+                    } else
+                        last_normal = i;
+                }
+                polygon.append (mapped);

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list