[Libreoffice-commits] core.git: Branch 'feature/emfplusprimitiveparser' - drawinglayer/inc drawinglayer/Library_drawinglayer.mk drawinglayer/source

Armin Le Grand Armin.Le.Grand at cib.de
Wed Jun 21 10:21:09 UTC 2017


 drawinglayer/Library_drawinglayer.mk                    |   34 
 drawinglayer/inc/emfplushelper.hxx                      |   52 
 drawinglayer/inc/wmfemfhelper.hxx                       |  215 +
 drawinglayer/source/primitive2d/metafileprimitive2d.cxx | 3198 ----------------
 drawinglayer/source/tools/emfpbrush.cxx                 |  328 +
 drawinglayer/source/tools/emfpbrush.hxx                 |  130 
 drawinglayer/source/tools/emfpcustomlinecap.cxx         |  158 
 drawinglayer/source/tools/emfpcustomlinecap.hxx         |   45 
 drawinglayer/source/tools/emfpfont.cxx                  |   69 
 drawinglayer/source/tools/emfpfont.hxx                  |   40 
 drawinglayer/source/tools/emfphelperdata.cxx            | 1232 ++++++
 drawinglayer/source/tools/emfphelperdata.hxx            |  252 +
 drawinglayer/source/tools/emfpimage.cxx                 |   95 
 drawinglayer/source/tools/emfpimage.hxx                 |   42 
 drawinglayer/source/tools/emfplushelper.cxx             |   47 
 drawinglayer/source/tools/emfppath.cxx                  |  192 
 drawinglayer/source/tools/emfppath.hxx                  |   47 
 drawinglayer/source/tools/emfppen.cxx                   |  301 +
 drawinglayer/source/tools/emfppen.hxx                   |   77 
 drawinglayer/source/tools/emfpregion.cxx                |   90 
 drawinglayer/source/tools/emfpregion.hxx                |   42 
 drawinglayer/source/tools/emfpstringformat.cxx          |   61 
 drawinglayer/source/tools/emfpstringformat.hxx          |   52 
 drawinglayer/source/tools/wmfemfhelper.cxx              | 3119 +++++++++++++++
 24 files changed, 6753 insertions(+), 3165 deletions(-)

New commits:
commit d97090d645b4fc8a2fd7d7cdbe02ddb280aa3d50
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Jun 21 12:19:52 2017 +0200

    emfplus: migrate gdiplus reader to drawinglayer
    
    In the current state interpretation of the GDI+
    data is needed in the MetafilePrimitive in the
    drawinglayer project. Migrate helper stuff and
    reader from cppcanvas to drawinglayer as tooling,
    prepare tooling, prepare changing from direct
    canvas rendering, isolate and migrate existing
    tooling from MetafilePrimitive from reading emf/wmf
    to places where it can be commonly used by both,
    prepare cange of different graphic statue usages,
    start changing XForm to B2DHomMatrix conversions,
    ...
    
    Change-Id: I2d6954f69464653d111abb316fd9654ad3499c3f

diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk
index 8c431c8ec08f..299c33f507b8 100644
--- a/drawinglayer/Library_drawinglayer.mk
+++ b/drawinglayer/Library_drawinglayer.mk
@@ -9,6 +9,11 @@
 
 $(eval $(call gb_Library_Library,drawinglayer))
 
+$(eval $(call gb_Library_set_include,drawinglayer,\
+    $$(INCLUDE) \
+    -I$(SRCDIR)/drawinglayer/inc \
+))
+
 $(eval $(call gb_Library_add_defs,drawinglayer,\
     -DDRAWINGLAYER_DLLIMPLEMENTATION \
 ))
@@ -69,7 +74,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive2d/borderlineprimitive2d \
     drawinglayer/source/primitive2d/clippedborderlineprimitive2d \
     drawinglayer/source/primitive2d/controlprimitive2d \
-	drawinglayer/source/primitive2d/cropprimitive2d \
+    drawinglayer/source/primitive2d/cropprimitive2d \
     drawinglayer/source/primitive2d/discretebitmapprimitive2d \
     drawinglayer/source/primitive2d/discreteshadowprimitive2d \
     drawinglayer/source/primitive2d/embedded3dprimitive2d \
@@ -77,7 +82,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive2d/fillgraphicprimitive2d \
     drawinglayer/source/primitive2d/fillgradientprimitive2d \
     drawinglayer/source/primitive2d/fillhatchprimitive2d \
-	drawinglayer/source/primitive2d/graphicprimitivehelper2d \
+    drawinglayer/source/primitive2d/graphicprimitivehelper2d \
     drawinglayer/source/primitive2d/graphicprimitive2d \
     drawinglayer/source/primitive2d/gridprimitive2d \
     drawinglayer/source/primitive2d/groupprimitive2d \
@@ -91,7 +96,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive2d/modifiedcolorprimitive2d \
     drawinglayer/source/primitive2d/objectinfoprimitive2d \
     drawinglayer/source/primitive2d/pagepreviewprimitive2d \
-	drawinglayer/source/primitive2d/patternfillprimitive2d \
+    drawinglayer/source/primitive2d/patternfillprimitive2d \
     drawinglayer/source/primitive2d/pointarrayprimitive2d \
     drawinglayer/source/primitive2d/polygonprimitive2d \
     drawinglayer/source/primitive2d/polypolygonprimitive2d \
@@ -100,8 +105,8 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive2d/sdrdecompositiontools2d \
     drawinglayer/source/primitive2d/shadowprimitive2d \
     drawinglayer/source/primitive2d/structuretagprimitive2d \
-	drawinglayer/source/primitive2d/svggradientprimitive2d \
-	drawinglayer/source/primitive2d/textbreakuphelper \
+    drawinglayer/source/primitive2d/svggradientprimitive2d \
+    drawinglayer/source/primitive2d/textbreakuphelper \
     drawinglayer/source/primitive2d/textdecoratedprimitive2d \
     drawinglayer/source/primitive2d/texteffectprimitive2d \
     drawinglayer/source/primitive2d/textenumsprimitive2d \
@@ -135,7 +140,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive3d/textureprimitive3d \
     drawinglayer/source/primitive3d/transformprimitive3d \
     drawinglayer/source/processor2d/baseprocessor2d \
-	drawinglayer/source/processor2d/processor2dtools \
+    drawinglayer/source/processor2d/processor2dtools \
     drawinglayer/source/processor2d/contourextractor2d \
     drawinglayer/source/processor2d/getdigitlanguage \
     drawinglayer/source/processor2d/helperwrongspellrenderer \
@@ -155,9 +160,20 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/processor3d/shadow3dextractor \
     drawinglayer/source/processor3d/zbufferprocessor3d \
     drawinglayer/source/texture/texture3d \
-	drawinglayer/source/tools/converters \
-	drawinglayer/source/drawinglayeruno/drawinglayeruno \
-	drawinglayer/source/drawinglayeruno/xprimitive2drenderer \
+    drawinglayer/source/tools/converters \
+    drawinglayer/source/tools/emfplushelper \
+    drawinglayer/source/tools/emfphelperdata \
+    drawinglayer/source/tools/emfpbrush \
+    drawinglayer/source/tools/emfppath \
+    drawinglayer/source/tools/emfppen \
+    drawinglayer/source/tools/emfpregion \
+    drawinglayer/source/tools/emfpimage \
+    drawinglayer/source/tools/emfpfont \
+    drawinglayer/source/tools/emfpstringformat \
+    drawinglayer/source/tools/emfpcustomlinecap \
+    drawinglayer/source/tools/wmfemfhelper \
+    drawinglayer/source/drawinglayeruno/drawinglayeruno \
+    drawinglayer/source/drawinglayeruno/xprimitive2drenderer \
     drawinglayer/source/texture/texture \
     drawinglayer/source/dumper/XShapeDumper \
     drawinglayer/source/dumper/EnhancedShapeDumper \
diff --git a/drawinglayer/inc/emfplushelper.hxx b/drawinglayer/inc/emfplushelper.hxx
new file mode 100644
index 000000000000..1a685a631abd
--- /dev/null
+++ b/drawinglayer/inc/emfplushelper.hxx
@@ -0,0 +1,52 @@
+/* -*- 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_DRAWINGLAYER_INC_EMFPLUSHELPER_HXX
+#define INCLUDED_DRAWINGLAYER_INC_EMFPLUSHELPER_HXX
+
+#include <sal/config.h>
+
+ /// predefines
+namespace emfplushelper { struct EmfPlusHelperData; }
+namespace wmfemfhelper { class TargetHolders; }
+namespace wmfemfhelper { class PropertyHolders; }
+
+namespace emfplushelper
+{
+    /// EMF+ data holder
+    class EmfPlusHelper
+    {
+    private:
+        EmfPlusHelperData*      mpD;
+
+    public:
+        EmfPlusHelper(SvMemoryStream& rMemoryStream);
+        ~EmfPlusHelper();
+
+        void processEmfPlusData(
+            SvMemoryStream& rMemoryStream,
+            wmfemfhelper::TargetHolders& rTargetHolders,
+            wmfemfhelper::PropertyHolders& rPropertyHolders,
+            const drawinglayer::geometry::ViewInformation2D& rViewInformation);
+    };
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/inc/wmfemfhelper.hxx b/drawinglayer/inc/wmfemfhelper.hxx
new file mode 100644
index 000000000000..699b065795df
--- /dev/null
+++ b/drawinglayer/inc/wmfemfhelper.hxx
@@ -0,0 +1,215 @@
+/* -*- 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_DRAWINGLAYER_INC_WMFEMFHELPER_HXX
+#define INCLUDED_DRAWINGLAYER_INC_WMFEMFHELPER_HXX
+
+#include <sal/config.h>
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+
+// predefines
+namespace drawinglayer { namespace geometry { class ViewInformation2D; }}
+class GDIMetaFile;
+namespace wmfemfhelper { class PropertyHolder; }
+
+namespace wmfemfhelper
+{
+    /** Helper class to buffer and hold a Primitive target vector. It
+    encapsulates the new/delete functionality and allows to work
+    on pointers of the implementation classes. All data will
+    be converted to uno sequences of uno references when accessing the
+    data.
+    */
+    class TargetHolder
+    {
+    private:
+        std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargets;
+
+    public:
+        TargetHolder();
+        ~TargetHolder();
+        sal_uInt32 size() const;
+        void append(drawinglayer::primitive2d::BasePrimitive2D* pCandidate);
+        drawinglayer::primitive2d::Primitive2DContainer getPrimitive2DSequence(const PropertyHolder& rPropertyHolder);
+    };
+}
+
+namespace wmfemfhelper
+{
+    /** Helper class which builds a stack on the TargetHolder class */
+    class TargetHolders
+    {
+    private:
+        std::vector< TargetHolder* >          maTargetHolders;
+
+    public:
+        TargetHolders();
+        sal_uInt32 size() const;
+        void Push();
+        void Pop();
+        TargetHolder& Current();
+        ~TargetHolders();
+    };
+}
+
+namespace wmfemfhelper
+{
+    /** helper class for graphic context
+
+    This class allows to hold a complete representation of classic
+    VCL OutputDevice state. This data is needed for correct
+    interpretation of the MetaFile action flow.
+    */
+    class PropertyHolder
+    {
+    private:
+        /// current transformation (aka MapMode)
+        basegfx::B2DHomMatrix   maTransformation;
+        MapUnit                 maMapUnit;
+
+        /// current colors
+        basegfx::BColor         maLineColor;
+        basegfx::BColor         maFillColor;
+        basegfx::BColor         maTextColor;
+        basegfx::BColor         maTextFillColor;
+        basegfx::BColor         maTextLineColor;
+        basegfx::BColor         maOverlineColor;
+
+        /// clipping
+        basegfx::B2DPolyPolygon maClipPolyPoygon;
+
+        /// font, etc.
+        vcl::Font               maFont;
+        RasterOp                maRasterOp;
+        ComplexTextLayoutFlags   mnLayoutMode;
+        LanguageType            maLanguageType;
+        PushFlags               mnPushFlags;
+
+        /// contains all active markers
+        bool                    mbLineColor : 1;
+        bool                    mbFillColor : 1;
+        bool                    mbTextColor : 1;
+        bool                    mbTextFillColor : 1;
+        bool                    mbTextLineColor : 1;
+        bool                    mbOverlineColor : 1;
+        bool                    mbClipPolyPolygonActive : 1;
+
+    public:
+        PropertyHolder();
+
+        /// read/write accesses
+        const basegfx::B2DHomMatrix& getTransformation() const { return maTransformation; }
+        void setTransformation(const basegfx::B2DHomMatrix& rNew) { if (rNew != maTransformation) maTransformation = rNew; }
+
+        MapUnit getMapUnit() const { return maMapUnit; }
+        void setMapUnit(MapUnit eNew) { if (eNew != maMapUnit) maMapUnit = eNew; }
+
+        const basegfx::BColor& getLineColor() const { return maLineColor; }
+        void setLineColor(const basegfx::BColor& rNew) { if (rNew != maLineColor) maLineColor = rNew; }
+        bool getLineColorActive() const { return mbLineColor; }
+        void setLineColorActive(bool bNew) { if (bNew != mbLineColor) mbLineColor = bNew; }
+
+        const basegfx::BColor& getFillColor() const { return maFillColor; }
+        void setFillColor(const basegfx::BColor& rNew) { if (rNew != maFillColor) maFillColor = rNew; }
+        bool getFillColorActive() const { return mbFillColor; }
+        void setFillColorActive(bool bNew) { if (bNew != mbFillColor) mbFillColor = bNew; }
+
+        const basegfx::BColor& getTextColor() const { return maTextColor; }
+        void setTextColor(const basegfx::BColor& rNew) { if (rNew != maTextColor) maTextColor = rNew; }
+        bool getTextColorActive() const { return mbTextColor; }
+        void setTextColorActive(bool bNew) { if (bNew != mbTextColor) mbTextColor = bNew; }
+
+        const basegfx::BColor& getTextFillColor() const { return maTextFillColor; }
+        void setTextFillColor(const basegfx::BColor& rNew) { if (rNew != maTextFillColor) maTextFillColor = rNew; }
+        bool getTextFillColorActive() const { return mbTextFillColor; }
+        void setTextFillColorActive(bool bNew) { if (bNew != mbTextFillColor) mbTextFillColor = bNew; }
+
+        const basegfx::BColor& getTextLineColor() const { return maTextLineColor; }
+        void setTextLineColor(const basegfx::BColor& rNew) { if (rNew != maTextLineColor) maTextLineColor = rNew; }
+        bool getTextLineColorActive() const { return mbTextLineColor; }
+        void setTextLineColorActive(bool bNew) { if (bNew != mbTextLineColor) mbTextLineColor = bNew; }
+
+        const basegfx::BColor& getOverlineColor() const { return maOverlineColor; }
+        void setOverlineColor(const basegfx::BColor& rNew) { if (rNew != maOverlineColor) maOverlineColor = rNew; }
+        bool getOverlineColorActive() const { return mbOverlineColor; }
+        void setOverlineColorActive(bool bNew) { if (bNew != mbOverlineColor) mbOverlineColor = bNew; }
+
+        const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPoygon; }
+        void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if (rNew != maClipPolyPoygon) maClipPolyPoygon = rNew; }
+        bool getClipPolyPolygonActive() const { return mbClipPolyPolygonActive; }
+        void setClipPolyPolygonActive(bool bNew) { if (bNew != mbClipPolyPolygonActive) mbClipPolyPolygonActive = bNew; }
+
+        const vcl::Font& getFont() const { return maFont; }
+        void setFont(const vcl::Font& rFont) { if (rFont != maFont) maFont = rFont; }
+
+        const RasterOp& getRasterOp() const { return maRasterOp; }
+        void setRasterOp(const RasterOp& rRasterOp) { if (rRasterOp != maRasterOp) maRasterOp = rRasterOp; }
+        bool isRasterOpInvert() const { return (RasterOp::Xor == maRasterOp || RasterOp::Invert == maRasterOp); }
+        bool isRasterOpForceBlack() const { return RasterOp::N0 == maRasterOp; }
+        bool isRasterOpActive() const { return isRasterOpInvert() || isRasterOpForceBlack(); }
+
+        ComplexTextLayoutFlags getLayoutMode() const { return mnLayoutMode; }
+        void setLayoutMode(ComplexTextLayoutFlags nNew) { if (nNew != mnLayoutMode) mnLayoutMode = nNew; }
+
+        LanguageType getLanguageType() const { return maLanguageType; }
+        void setLanguageType(LanguageType aNew) { if (aNew != maLanguageType) maLanguageType = aNew; }
+
+        PushFlags getPushFlags() const { return mnPushFlags; }
+        void setPushFlags(PushFlags nNew) { if (nNew != mnPushFlags) mnPushFlags = nNew; }
+
+        bool getLineOrFillActive() const { return (mbLineColor || mbFillColor); }
+    };
+}
+
+namespace wmfemfhelper
+{
+    /** stack for properites
+
+    This class builds a stack based on the PropertyHolder
+    class. It encapsulates the pointer/new/delete usage to
+    make it safe and implements the push/pop as needed by a
+    VCL Metafile interpreter. The critical part here are the
+    flag values VCL OutputDevice uses here; not all stuff is
+    pushed and thus needs to be copied at pop.
+    */
+    class PropertyHolders
+    {
+    private:
+        std::vector< PropertyHolder* >          maPropertyHolders;
+
+    public:
+        PropertyHolders();
+        void PushDefault();
+        void Push(PushFlags nPushFlags);
+        void Pop();
+        PropertyHolder& Current();
+        ~PropertyHolders();
+    };
+}
+
+namespace wmfemfhelper
+{
+    drawinglayer::primitive2d::Primitive2DContainer interpretMetafile(
+        const GDIMetaFile& rMetaFile,
+        const drawinglayer::geometry::ViewInformation2D& rViewInformation);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
index 4737f78c765b..65ec52c894de 100644
--- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
@@ -18,3141 +18,47 @@
  */
 
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
-#include <basegfx/tools/canvastools.hxx>
-#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <basegfx/color/bcolor.hxx>
-#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
-#include <vcl/lineinfo.hxx>
-#include <drawinglayer/attribute/lineattribute.hxx>
-#include <drawinglayer/attribute/strokeattribute.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
-#include <vcl/metaact.hxx>
-#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
-#include <basegfx/matrix/b2dhommatrixtools.hxx>
-#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
-#include <basegfx/polygon/b2dpolygontools.hxx>
-#include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx>
-#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <vcl/salbtype.hxx>
-#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
-#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
-#include <vcl/svapp.hxx>
-#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
-#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
-#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
-#include <basegfx/polygon/b2dpolygonclipper.hxx>
-#include <drawinglayer/primitive2d/invertprimitive2d.hxx>
-#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
-#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
-#include <drawinglayer/primitive2d/wallpaperprimitive2d.hxx>
-#include <drawinglayer/primitive2d/textprimitive2d.hxx>
-#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
-#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
-#include <i18nlangtag/languagetag.hxx>
-#include <drawinglayer/primitive2d/textlineprimitive2d.hxx>
-#include <drawinglayer/primitive2d/textstrikeoutprimitive2d.hxx>
-#include <drawinglayer/primitive2d/epsprimitive2d.hxx>
-#include <tools/fract.hxx>
-#include <numeric>
-
-
-using namespace com::sun::star;
-
-
-namespace
-{
-    /** helper class for graphic context
-
-        This class allows to hold a complete representation of classic
-        VCL OutputDevice state. This data is needed for correct
-        interpretation of the MetaFile action flow.
-    */
-    class PropertyHolder
-    {
-    private:
-        /// current transformation (aka MapMode)
-        basegfx::B2DHomMatrix   maTransformation;
-        MapUnit                 maMapUnit;
-
-        /// current colors
-        basegfx::BColor         maLineColor;
-        basegfx::BColor         maFillColor;
-        basegfx::BColor         maTextColor;
-        basegfx::BColor         maTextFillColor;
-        basegfx::BColor         maTextLineColor;
-        basegfx::BColor         maOverlineColor;
-
-        /// clipping
-        basegfx::B2DPolyPolygon maClipPolyPoygon;
-
-        /// font, etc.
-        vcl::Font               maFont;
-        RasterOp                maRasterOp;
-        ComplexTextLayoutFlags   mnLayoutMode;
-        LanguageType            maLanguageType;
-        PushFlags               mnPushFlags;
-
-        /// contains all active markers
-        bool                    mbLineColor : 1;
-        bool                    mbFillColor : 1;
-        bool                    mbTextColor : 1;
-        bool                    mbTextFillColor : 1;
-        bool                    mbTextLineColor : 1;
-        bool                    mbOverlineColor : 1;
-        bool                    mbClipPolyPolygonActive : 1;
-
-    public:
-        PropertyHolder()
-        :   maTransformation(),
-            maMapUnit(MapUnit::Map100thMM),
-            maLineColor(),
-            maFillColor(),
-            maTextColor(COL_BLACK),
-            maTextFillColor(),
-            maTextLineColor(),
-            maOverlineColor(),
-            maClipPolyPoygon(),
-            maFont(),
-            maRasterOp(RasterOp::OverPaint),
-            mnLayoutMode(ComplexTextLayoutFlags::Default),
-            maLanguageType(0),
-            mnPushFlags(PushFlags::NONE),
-            mbLineColor(false),
-            mbFillColor(false),
-            mbTextColor(true),
-            mbTextFillColor(false),
-            mbTextLineColor(false),
-            mbOverlineColor(false),
-            mbClipPolyPolygonActive(false)
-        {
-        }
-
-        /// read/write accesses
-        const basegfx::B2DHomMatrix& getTransformation() const { return maTransformation; }
-        void setTransformation(const basegfx::B2DHomMatrix& rNew) { if(rNew != maTransformation) maTransformation = rNew; }
-
-        MapUnit getMapUnit() const { return maMapUnit; }
-        void setMapUnit(MapUnit eNew) { if(eNew != maMapUnit) maMapUnit = eNew; }
-
-        const basegfx::BColor& getLineColor() const { return maLineColor; }
-        void setLineColor(const basegfx::BColor& rNew) { if(rNew != maLineColor) maLineColor = rNew; }
-        bool getLineColorActive() const { return mbLineColor; }
-        void setLineColorActive(bool bNew) { if(bNew != mbLineColor) mbLineColor = bNew; }
-
-        const basegfx::BColor& getFillColor() const { return maFillColor; }
-        void setFillColor(const basegfx::BColor& rNew) { if(rNew != maFillColor) maFillColor = rNew; }
-        bool getFillColorActive() const { return mbFillColor; }
-        void setFillColorActive(bool bNew) { if(bNew != mbFillColor) mbFillColor = bNew; }
-
-        const basegfx::BColor& getTextColor() const { return maTextColor; }
-        void setTextColor(const basegfx::BColor& rNew) { if(rNew != maTextColor) maTextColor = rNew; }
-        bool getTextColorActive() const { return mbTextColor; }
-        void setTextColorActive(bool bNew) { if(bNew != mbTextColor) mbTextColor = bNew; }
-
-        const basegfx::BColor& getTextFillColor() const { return maTextFillColor; }
-        void setTextFillColor(const basegfx::BColor& rNew) { if(rNew != maTextFillColor) maTextFillColor = rNew; }
-        bool getTextFillColorActive() const { return mbTextFillColor; }
-        void setTextFillColorActive(bool bNew) { if(bNew != mbTextFillColor) mbTextFillColor = bNew; }
-
-        const basegfx::BColor& getTextLineColor() const { return maTextLineColor; }
-        void setTextLineColor(const basegfx::BColor& rNew) { if(rNew != maTextLineColor) maTextLineColor = rNew; }
-        bool getTextLineColorActive() const { return mbTextLineColor; }
-        void setTextLineColorActive(bool bNew) { if(bNew != mbTextLineColor) mbTextLineColor = bNew; }
-
-        const basegfx::BColor& getOverlineColor() const { return maOverlineColor; }
-        void setOverlineColor(const basegfx::BColor& rNew) { if(rNew != maOverlineColor) maOverlineColor = rNew; }
-        bool getOverlineColorActive() const { return mbOverlineColor; }
-        void setOverlineColorActive(bool bNew) { if(bNew != mbOverlineColor) mbOverlineColor = bNew; }
-
-        const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPoygon; }
-        void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if(rNew != maClipPolyPoygon) maClipPolyPoygon = rNew; }
-        bool getClipPolyPolygonActive() const { return mbClipPolyPolygonActive; }
-        void setClipPolyPolygonActive(bool bNew) { if(bNew != mbClipPolyPolygonActive) mbClipPolyPolygonActive = bNew; }
-
-        const vcl::Font& getFont() const { return maFont; }
-        void setFont(const vcl::Font& rFont) { if(rFont != maFont) maFont = rFont; }
-
-        const RasterOp& getRasterOp() const { return maRasterOp; }
-        void setRasterOp(const RasterOp& rRasterOp) { if(rRasterOp != maRasterOp) maRasterOp = rRasterOp; }
-        bool isRasterOpInvert() const { return (RasterOp::Xor == maRasterOp || RasterOp::Invert == maRasterOp); }
-        bool isRasterOpForceBlack() const { return RasterOp::N0 == maRasterOp; }
-        bool isRasterOpActive() const { return isRasterOpInvert() || isRasterOpForceBlack(); }
-
-        ComplexTextLayoutFlags getLayoutMode() const { return mnLayoutMode; }
-        void setLayoutMode(ComplexTextLayoutFlags nNew) { if(nNew != mnLayoutMode) mnLayoutMode = nNew; }
-
-        LanguageType getLanguageType() const { return maLanguageType; }
-        void setLanguageType(LanguageType aNew) { if(aNew != maLanguageType) maLanguageType = aNew; }
-
-        PushFlags getPushFlags() const { return mnPushFlags; }
-        void setPushFlags(PushFlags nNew) { if(nNew != mnPushFlags) mnPushFlags = nNew; }
-
-        bool getLineOrFillActive() const { return (mbLineColor || mbFillColor); }
-    };
-} // end of anonymous namespace
-
-
-namespace
-{
-    /** stack for properites
-
-        This class builds a stack based on the PropertyHolder
-        class. It encapsulates the pointer/new/delete usage to
-        make it safe and implements the push/pop as needed by a
-        VCL Metafile interpreter. The critical part here are the
-        flag values VCL OutputDevice uses here; not all stuff is
-        pushed and thus needs to be copied at pop.
-    */
-    class PropertyHolders
-    {
-    private:
-        std::vector< PropertyHolder* >          maPropertyHolders;
-
-    public:
-        PropertyHolders()
-        {
-            maPropertyHolders.push_back(new PropertyHolder());
-        }
-
-        void PushDefault()
-        {
-            PropertyHolder* pNew = new PropertyHolder();
-            maPropertyHolders.push_back(pNew);
-        }
-
-        void Push(PushFlags nPushFlags)
-        {
-            if(bool(nPushFlags))
-            {
-                OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: PUSH with no property holders (!)");
-                if ( !maPropertyHolders.empty() )
-                {
-                    PropertyHolder* pNew = new PropertyHolder(*maPropertyHolders.back());
-                    pNew->setPushFlags(nPushFlags);
-                    maPropertyHolders.push_back(pNew);
-                }
-            }
-        }
-
-        void Pop()
-        {
-            OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: POP with no property holders (!)");
-            const sal_uInt32 nSize(maPropertyHolders.size());
-
-            if(nSize)
-            {
-                const PropertyHolder* pTip = maPropertyHolders.back();
-                const PushFlags nPushFlags(pTip->getPushFlags());
-
-                if(nPushFlags != PushFlags::NONE)
-                {
-                    if(nSize > 1)
-                    {
-                        // copy back content for all non-set flags
-                        PropertyHolder* pLast = maPropertyHolders[nSize - 2];
-
-                        if(PushFlags::ALL != nPushFlags)
-                        {
-                            if(!(nPushFlags & PushFlags::LINECOLOR      ))
-                            {
-                                pLast->setLineColor(pTip->getLineColor());
-                                pLast->setLineColorActive(pTip->getLineColorActive());
-                            }
-                            if(!(nPushFlags & PushFlags::FILLCOLOR      ))
-                            {
-                                pLast->setFillColor(pTip->getFillColor());
-                                pLast->setFillColorActive(pTip->getFillColorActive());
-                            }
-                            if(!(nPushFlags & PushFlags::FONT           ))
-                            {
-                                pLast->setFont(pTip->getFont());
-                            }
-                            if(!(nPushFlags & PushFlags::TEXTCOLOR      ))
-                            {
-                                pLast->setTextColor(pTip->getTextColor());
-                                pLast->setTextColorActive(pTip->getTextColorActive());
-                            }
-                            if(!(nPushFlags & PushFlags::MAPMODE        ))
-                            {
-                                pLast->setTransformation(pTip->getTransformation());
-                                pLast->setMapUnit(pTip->getMapUnit());
-                            }
-                            if(!(nPushFlags & PushFlags::CLIPREGION     ))
-                            {
-                                pLast->setClipPolyPolygon(pTip->getClipPolyPolygon());
-                                pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive());
-                            }
-                            if(!(nPushFlags & PushFlags::RASTEROP       ))
-                            {
-                                pLast->setRasterOp(pTip->getRasterOp());
-                            }
-                            if(!(nPushFlags & PushFlags::TEXTFILLCOLOR  ))
-                            {
-                                pLast->setTextFillColor(pTip->getTextFillColor());
-                                pLast->setTextFillColorActive(pTip->getTextFillColorActive());
-                            }
-                            if(!(nPushFlags & PushFlags::TEXTALIGN      ))
-                            {
-                                if(pLast->getFont().GetAlignment() != pTip->getFont().GetAlignment())
-                                {
-                                    vcl::Font aFont(pLast->getFont());
-                                    aFont.SetAlignment(pTip->getFont().GetAlignment());
-                                    pLast->setFont(aFont);
-                                }
-                            }
-                            if(!(nPushFlags & PushFlags::REFPOINT       ))
-                            {
-                                // not supported
-                            }
-                            if(!(nPushFlags & PushFlags::TEXTLINECOLOR  ))
-                            {
-                                pLast->setTextLineColor(pTip->getTextLineColor());
-                                pLast->setTextLineColorActive(pTip->getTextLineColorActive());
-                            }
-                            if(!(nPushFlags & PushFlags::TEXTLAYOUTMODE ))
-                            {
-                                pLast->setLayoutMode(pTip->getLayoutMode());
-                            }
-                            if(!(nPushFlags & PushFlags::TEXTLANGUAGE   ))
-                            {
-                                pLast->setLanguageType(pTip->getLanguageType());
-                            }
-                            if(!(nPushFlags & PushFlags::OVERLINECOLOR  ))
-                            {
-                                pLast->setOverlineColor(pTip->getOverlineColor());
-                                pLast->setOverlineColorActive(pTip->getOverlineColorActive());
-                            }
-                        }
-                    }
-                }
-
-                // execute the pop
-                delete maPropertyHolders.back();
-                maPropertyHolders.pop_back();
-            }
-        }
-
-        PropertyHolder& Current()
-        {
-            static PropertyHolder aDummy;
-            OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: CURRENT with no property holders (!)");
-            return maPropertyHolders.empty() ? aDummy : *maPropertyHolders.back();
-        }
-
-        ~PropertyHolders()
-        {
-            while(!maPropertyHolders.empty())
-            {
-                delete maPropertyHolders.back();
-                maPropertyHolders.pop_back();
-            }
-        }
-    };
-} // end of anonymous namespace
-
-
-namespace
-{
-    /** helper to convert a vcl::Region to a B2DPolyPolygon
-        when it does not yet contain one. In the future
-        this may be expanded to merge the polygons created
-        from rectangles or use a special algo to directly turn
-        the spans of regions to a single, already merged
-        PolyPolygon.
-     */
-    basegfx::B2DPolyPolygon getB2DPolyPolygonFromRegion(const vcl::Region& rRegion)
-    {
-        basegfx::B2DPolyPolygon aRetval;
-
-        if(!rRegion.IsEmpty())
-        {
-            aRetval = rRegion.GetAsB2DPolyPolygon();
-        }
-
-        return aRetval;
-    }
-} // end of anonymous namespace
-
-
-namespace
-{
-    /** Helper class to buffer and hold a Primitive target vector. It
-        encapsulates the new/delete functionality and allows to work
-        on pointers of the implementation classes. All data will
-        be converted to uno sequences of uno references when accessing the
-        data.
-    */
-    class TargetHolder
-    {
-    private:
-        std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargets;
-
-    public:
-        TargetHolder()
-        :   aTargets()
-        {
-        }
-
-        ~TargetHolder()
-        {
-            const sal_uInt32 nCount(aTargets.size());
-
-            for(sal_uInt32 a(0); a < nCount; a++)
-            {
-                delete aTargets[a];
-            }
-        }
-
-        sal_uInt32 size() const
-        {
-            return aTargets.size();
-        }
-
-        void append(drawinglayer::primitive2d::BasePrimitive2D* pCandidate)
-        {
-            if(pCandidate)
-            {
-                aTargets.push_back(pCandidate);
-            }
-        }
-
-        drawinglayer::primitive2d::Primitive2DContainer getPrimitive2DSequence(const PropertyHolder& rPropertyHolder)
-        {
-            const sal_uInt32 nCount(aTargets.size());
-            drawinglayer::primitive2d::Primitive2DContainer xRetval(nCount);
-
-            for(sal_uInt32 a(0); a < nCount; a++)
-            {
-                xRetval[a] = aTargets[a];
-            }
-
-            // All Targets were pointers, but do not need to be deleted since they
-            // were converted to UNO API references now, so they stay as long as
-            // referenced. Do NOT delete the C++ implementation classes here, but clear
-            // the buffer to not delete them in the destructor.
-            aTargets.clear();
-
-            if(!xRetval.empty() && rPropertyHolder.getClipPolyPolygonActive())
-            {
-                const basegfx::B2DPolyPolygon& rClipPolyPolygon = rPropertyHolder.getClipPolyPolygon();
-
-                if(rClipPolyPolygon.count())
-                {
-                    const drawinglayer::primitive2d::Primitive2DReference xMask(
-                        new drawinglayer::primitive2d::MaskPrimitive2D(
-                            rClipPolyPolygon,
-                            xRetval));
-
-                    xRetval = drawinglayer::primitive2d::Primitive2DContainer { xMask };
-                }
-            }
-
-            return xRetval;
-        }
-    };
-} // end of anonymous namespace
-
-
-namespace
-{
-    /** Helper class which builds a stack on the TargetHolder class */
-    class TargetHolders
-    {
-    private:
-        std::vector< TargetHolder* >          maTargetHolders;
-
-    public:
-        TargetHolders()
-        {
-            maTargetHolders.push_back(new TargetHolder());
-        }
-
-        sal_uInt32 size() const
-        {
-            return maTargetHolders.size();
-        }
-
-        void Push()
-        {
-            maTargetHolders.push_back(new TargetHolder());
-        }
-
-        void Pop()
-        {
-            OSL_ENSURE(maTargetHolders.size(), "TargetHolders: POP with no property holders (!)");
-            if(!maTargetHolders.empty())
-            {
-                delete maTargetHolders.back();
-                maTargetHolders.pop_back();
-            }
-        }
-
-        TargetHolder& Current()
-        {
-            static TargetHolder aDummy;
-            OSL_ENSURE(maTargetHolders.size(), "TargetHolders: CURRENT with no property holders (!)");
-            return maTargetHolders.empty() ? aDummy : *maTargetHolders.back();
-        }
-
-        ~TargetHolders()
-        {
-            while(!maTargetHolders.empty())
-            {
-                delete maTargetHolders.back();
-                maTargetHolders.pop_back();
-            }
-        }
-    };
-} // end of anonymous namespace
-
-
-namespace drawinglayer
-{
-    namespace primitive2d
-    {
-        /** NonOverlappingFillGradientPrimitive2D class
-
-            This is a special version of the FillGradientPrimitive2D which decomposes
-            to a non-overlapping geometry version of the gradient. This needs to be
-            used to support the old XOR paint-'trick'.
-
-            It does not need an own identifier since a renderer who wants to interpret
-            it itself may do so. It just overrides the decomposition of the C++
-            implementation class to do an alternative decomposition.
-         */
-        class NonOverlappingFillGradientPrimitive2D : public FillGradientPrimitive2D
-        {
-        protected:
-            /// local decomposition.
-            virtual void create2DDecomposition(Primitive2DContainer& rContainer,
-                const geometry::ViewInformation2D& rViewInformation) const override;
-
-        public:
-            /// constructor
-            NonOverlappingFillGradientPrimitive2D(
-                const basegfx::B2DRange& rObjectRange,
-                const attribute::FillGradientAttribute& rFillGradient)
-            :   FillGradientPrimitive2D(rObjectRange, rFillGradient)
-            {
-            }
-        };
-
-        void NonOverlappingFillGradientPrimitive2D::create2DDecomposition(
-            Primitive2DContainer& rContainer,
-            const geometry::ViewInformation2D& /*rViewInformation*/) const
-        {
-            if(!getFillGradient().isDefault())
-            {
-                createFill(rContainer, false);
-            }
-        }
-    } // end of namespace primitive2d
-} // end of namespace drawinglayer
-
-
-namespace
-{
-    /** helper to convert a MapMode to a transformation */
-    basegfx::B2DHomMatrix getTransformFromMapMode(const MapMode& rMapMode)
-    {
-        basegfx::B2DHomMatrix aMapping;
-        const Fraction aNoScale(1, 1);
-        const Point& rOrigin(rMapMode.GetOrigin());
-
-        if(0 != rOrigin.X() || 0 != rOrigin.Y())
-        {
-            aMapping.translate(rOrigin.X(), rOrigin.Y());
-        }
-
-        if(rMapMode.GetScaleX() != aNoScale || rMapMode.GetScaleY() != aNoScale)
-        {
-            aMapping.scale(
-                double(rMapMode.GetScaleX()),
-                double(rMapMode.GetScaleY()));
-        }
-
-        return aMapping;
-    }
-
-    /** helper to create a PointArrayPrimitive2D based on current context */
-    void createPointArrayPrimitive(
-        const std::vector< basegfx::B2DPoint >& rPositions,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties,
-        const basegfx::BColor& rBColor)
-    {
-        if(!rPositions.empty())
-        {
-            if(rProperties.getTransformation().isIdentity())
-            {
-                rTarget.append(
-                    new drawinglayer::primitive2d::PointArrayPrimitive2D(
-                        rPositions,
-                        rBColor));
-            }
-            else
-            {
-                std::vector< basegfx::B2DPoint > aPositions(rPositions);
-
-                for(basegfx::B2DPoint & aPosition : aPositions)
-                {
-                    aPosition = rProperties.getTransformation() * aPosition;
-                }
-
-                rTarget.append(
-                    new drawinglayer::primitive2d::PointArrayPrimitive2D(
-                        aPositions,
-                        rBColor));
-            }
-        }
-    }
-
-    /** helper to create a PolygonHairlinePrimitive2D based on current context */
-    void createHairlinePrimitive(
-        const basegfx::B2DPolygon& rLinePolygon,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(rLinePolygon.count())
-        {
-            basegfx::B2DPolygon aLinePolygon(rLinePolygon);
-            aLinePolygon.transform(rProperties.getTransformation());
-            rTarget.append(
-                new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
-                    aLinePolygon,
-                    rProperties.getLineColor()));
-        }
-    }
-
-    /** helper to create a PolyPolygonColorPrimitive2D based on current context */
-    void createFillPrimitive(
-        const basegfx::B2DPolyPolygon& rFillPolyPolygon,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(rFillPolyPolygon.count())
-        {
-            basegfx::B2DPolyPolygon aFillPolyPolygon(rFillPolyPolygon);
-            aFillPolyPolygon.transform(rProperties.getTransformation());
-            rTarget.append(
-                new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
-                    aFillPolyPolygon,
-                    rProperties.getFillColor()));
-        }
-    }
-
-    /** helper to create a PolygonStrokePrimitive2D based on current context */
-    void createLinePrimitive(
-        const basegfx::B2DPolygon& rLinePolygon,
-        const LineInfo& rLineInfo,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(rLinePolygon.count())
-        {
-            const bool bDashDotUsed(LineStyle::Dash == rLineInfo.GetStyle());
-            const bool bWidthUsed(rLineInfo.GetWidth() > 1);
-
-            if(bDashDotUsed || bWidthUsed)
-            {
-                basegfx::B2DPolygon aLinePolygon(rLinePolygon);
-                aLinePolygon.transform(rProperties.getTransformation());
-                const drawinglayer::attribute::LineAttribute aLineAttribute(
-                    rProperties.getLineColor(),
-                    bWidthUsed ? rLineInfo.GetWidth() : 0.0,
-                    rLineInfo.GetLineJoin(),
-                    rLineInfo.GetLineCap());
-
-                if(bDashDotUsed)
-                {
-                    std::vector< double > fDotDashArray;
-                    const double fDashLen(rLineInfo.GetDashLen());
-                    const double fDotLen(rLineInfo.GetDotLen());
-                    const double fDistance(rLineInfo.GetDistance());
-
-                    for(sal_uInt16 a(0); a < rLineInfo.GetDashCount(); a++)
-                    {
-                        fDotDashArray.push_back(fDashLen);
-                        fDotDashArray.push_back(fDistance);
-                    }
-
-                    for(sal_uInt16 b(0); b < rLineInfo.GetDotCount(); b++)
-                    {
-                        fDotDashArray.push_back(fDotLen);
-                        fDotDashArray.push_back(fDistance);
-                    }
-
-                    const double fAccumulated(std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
-                    const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
-                        fDotDashArray,
-                        fAccumulated);
-
-                    rTarget.append(
-                        new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
-                            aLinePolygon,
-                            aLineAttribute,
-                            aStrokeAttribute));
-                }
-                else
-                {
-                    rTarget.append(
-                        new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
-                            aLinePolygon,
-                            aLineAttribute));
-                }
-            }
-            else
-            {
-                createHairlinePrimitive(rLinePolygon, rTarget, rProperties);
-            }
-        }
-    }
-
-    /** helper to create needed line and fill primitives based on current context */
-    void createHairlineAndFillPrimitive(
-        const basegfx::B2DPolygon& rPolygon,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(rProperties.getFillColorActive())
-        {
-            createFillPrimitive(basegfx::B2DPolyPolygon(rPolygon), rTarget, rProperties);
-        }
-
-        if(rProperties.getLineColorActive())
-        {
-            createHairlinePrimitive(rPolygon, rTarget, rProperties);
-        }
-    }
-
-    /** helper to create needed line and fill primitives based on current context */
-    void createHairlineAndFillPrimitive(
-        const basegfx::B2DPolyPolygon& rPolyPolygon,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(rProperties.getFillColorActive())
-        {
-            createFillPrimitive(rPolyPolygon, rTarget, rProperties);
-        }
-
-        if(rProperties.getLineColorActive())
-        {
-            for(sal_uInt32 a(0); a < rPolyPolygon.count(); a++)
-            {
-                createHairlinePrimitive(rPolyPolygon.getB2DPolygon(a), rTarget, rProperties);
-            }
-        }
-    }
-
-    /** helper to create DiscreteBitmapPrimitive2D based on current context.
-        The DiscreteBitmapPrimitive2D is especially created for this usage
-        since no other usage defines a bitmap visualisation based on top-left
-        position and size in pixels. At the end it will create a view-dependent
-        transformed embedding of a BitmapPrimitive2D.
-    */
-    void createBitmapExPrimitive(
-        const BitmapEx& rBitmapEx,
-        const Point& rPoint,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(!rBitmapEx.IsEmpty())
-        {
-            basegfx::B2DPoint aPoint(rPoint.X(), rPoint.Y());
-            aPoint = rProperties.getTransformation() * aPoint;
-
-            rTarget.append(
-                new drawinglayer::primitive2d::DiscreteBitmapPrimitive2D(
-                    rBitmapEx,
-                    aPoint));
-        }
-    }
-
-    /** helper to create BitmapPrimitive2D based on current context */
-    void createBitmapExPrimitive(
-        const BitmapEx& rBitmapEx,
-        const Point& rPoint,
-        const Size& rSize,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperties)
-    {
-        if(!rBitmapEx.IsEmpty())
-        {
-            basegfx::B2DHomMatrix aObjectTransform;
-
-            aObjectTransform.set(0, 0, rSize.Width());
-            aObjectTransform.set(1, 1, rSize.Height());
-            aObjectTransform.set(0, 2, rPoint.X());
-            aObjectTransform.set(1, 2, rPoint.Y());
-
-            aObjectTransform = rProperties.getTransformation() * aObjectTransform;
-
-            rTarget.append(
-                new drawinglayer::primitive2d::BitmapPrimitive2D(
-                    rBitmapEx,
-                    aObjectTransform));
-        }
-    }
-
-    /** helper to create a regular BotmapEx from a MaskAction (definitions
-        which use a bitmap without transparence but define one of the colors as
-        transparent)
-     */
-    BitmapEx createMaskBmpEx(const Bitmap& rBitmap, const Color& rMaskColor)
-    {
-        const Color aWhite(COL_WHITE);
-        BitmapPalette aBiLevelPalette(2);
-
-        aBiLevelPalette[0] = aWhite;
-        aBiLevelPalette[1] = rMaskColor;
-
-        Bitmap aMask(rBitmap.CreateMask(aWhite));
-        Bitmap aSolid(rBitmap.GetSizePixel(), 1, &aBiLevelPalette);
-
-        aSolid.Erase(rMaskColor);
-
-        return BitmapEx(aSolid, aMask);
-    }
-
-    /** helper to convert from a VCL Gradient definition to the corresponding
-        data for primitive representation
-     */
-    drawinglayer::attribute::FillGradientAttribute createFillGradientAttribute(const Gradient& rGradient)
-    {
-        const Color aStartColor(rGradient.GetStartColor());
-        const sal_uInt16 nStartIntens(rGradient.GetStartIntensity());
-        basegfx::BColor aStart(aStartColor.getBColor());
-
-        if(nStartIntens != 100)
-        {
-            const basegfx::BColor aBlack;
-            aStart = interpolate(aBlack, aStart, (double)nStartIntens * 0.01);
-        }
-
-        const Color aEndColor(rGradient.GetEndColor());
-        const sal_uInt16 nEndIntens(rGradient.GetEndIntensity());
-        basegfx::BColor aEnd(aEndColor.getBColor());
-
-        if(nEndIntens != 100)
-        {
-            const basegfx::BColor aBlack;
-            aEnd = interpolate(aBlack, aEnd, (double)nEndIntens * 0.01);
-        }
-
-        drawinglayer::attribute::GradientStyle aGradientStyle(drawinglayer::attribute::GradientStyle::Rect);
-
-        switch(rGradient.GetStyle())
-        {
-            case GradientStyle::Linear :
-            {
-                aGradientStyle = drawinglayer::attribute::GradientStyle::Linear;
-                break;
-            }
-            case GradientStyle::Axial :
-            {
-                aGradientStyle = drawinglayer::attribute::GradientStyle::Axial;
-                break;
-            }
-            case GradientStyle::Radial :
-            {
-                aGradientStyle = drawinglayer::attribute::GradientStyle::Radial;
-                break;
-            }
-            case GradientStyle::Elliptical :
-            {
-                aGradientStyle = drawinglayer::attribute::GradientStyle::Elliptical;
-                break;
-            }
-            case GradientStyle::Square :
-            {
-                aGradientStyle = drawinglayer::attribute::GradientStyle::Square;
-                break;
-            }
-            default : // GradientStyle::Rect
-            {
-                aGradientStyle = drawinglayer::attribute::GradientStyle::Rect;
-                break;
-            }
-        }
-
-        return drawinglayer::attribute::FillGradientAttribute(
-            aGradientStyle,
-            (double)rGradient.GetBorder() * 0.01,
-            (double)rGradient.GetOfsX() * 0.01,
-            (double)rGradient.GetOfsY() * 0.01,
-            (double)rGradient.GetAngle() * F_PI1800,
-            aStart,
-            aEnd,
-            rGradient.GetSteps());
-    }
-
-    /** helper to convert from a VCL Hatch definition to the corresponding
-        data for primitive representation
-     */
-    drawinglayer::attribute::FillHatchAttribute createFillHatchAttribute(const Hatch& rHatch)
-    {
-        drawinglayer::attribute::HatchStyle aHatchStyle(drawinglayer::attribute::HatchStyle::Single);
-
-        switch(rHatch.GetStyle())
-        {
-            default : // case HatchStyle::Single :
-            {
-                aHatchStyle = drawinglayer::attribute::HatchStyle::Single;
-                break;
-            }
-            case HatchStyle::Double :
-            {
-                aHatchStyle = drawinglayer::attribute::HatchStyle::Double;
-                break;
-            }
-            case HatchStyle::Triple :
-            {
-                aHatchStyle = drawinglayer::attribute::HatchStyle::Triple;
-                break;
-            }
-        }
-
-        return drawinglayer::attribute::FillHatchAttribute(
-            aHatchStyle,
-            (double)rHatch.GetDistance(),
-            (double)rHatch.GetAngle() * F_PI1800,
-            rHatch.GetColor().getBColor(),
-            3, // same default as VCL, a minimum of three discrete units (pixels) offset
-            false);
-    }
-
-    /** helper to take needed action on ClipRegion change. This method needs to be called
-        on any vcl::Region change, e.g. at the obvious actions doing this, but also at pop-calls
-        which change the vcl::Region of the current context. It takes care of creating the
-        current embedded context, set the new vcl::Region at the context and possibly prepare
-        a new target for including new geometry into the current region
-     */
-    void HandleNewClipRegion(
-        const basegfx::B2DPolyPolygon& rClipPolyPolygon,
-        TargetHolders& rTargetHolders,
-        PropertyHolders& rPropertyHolders)
-    {
-        const bool bNewActive(rClipPolyPolygon.count());
-
-        // #i108636# The handling of new ClipPolyPolygons was not done as good as possible
-        // in the first version of this interpreter; e.g. when a ClipPolyPolygon was set
-        // initially and then using a lot of push/pop actions, the pop always leads
-        // to setting a 'new' ClipPolyPolygon which indeed is the return to the ClipPolyPolygon
-        // of the properties next on the stack.
-
-        // This ClipPolyPolygon is identical to the current one, so there is no need to
-        // create a MaskPrimitive2D containing the up-to-now created primitives, but
-        // this was done before. While this does not lead to wrong primitive
-        // representations of the metafile data, it creates unnecessarily expensive
-        // representations. Just detecting when no really 'new' ClipPolyPolygon gets set
-        // solves the problem.
-
-        if(!rPropertyHolders.Current().getClipPolyPolygonActive() && !bNewActive)
-        {
-            // no active ClipPolyPolygon exchanged by no new one, done
-            return;
-        }
-
-        if(rPropertyHolders.Current().getClipPolyPolygonActive() && bNewActive)
-        {
-            // active ClipPolyPolygon and new active ClipPolyPolygon
-            if(rPropertyHolders.Current().getClipPolyPolygon() == rClipPolyPolygon)
-            {
-                // new is the same as old, done
-                return;
-            }
-        }
-
-        // Here the old and the new are definitively different, maybe
-        // old one and/or new one is not active.
-
-        // Handle deletion of old ClipPolyPolygon. The process evtl. created primitives which
-        // belong to this active ClipPolyPolygon. These need to be embedded to a
-        // MaskPrimitive2D accordingly.
-        if(rPropertyHolders.Current().getClipPolyPolygonActive() && rTargetHolders.size() > 1)
-        {
-            drawinglayer::primitive2d::Primitive2DContainer aSubContent;
-
-            if(rPropertyHolders.Current().getClipPolyPolygon().count()
-                && rTargetHolders.Current().size())
-            {
-                aSubContent = rTargetHolders.Current().getPrimitive2DSequence(
-                    rPropertyHolders.Current());
-            }
-
-            rTargetHolders.Pop();
-
-            if(!aSubContent.empty())
-            {
-                rTargetHolders.Current().append(
-                    new drawinglayer::primitive2d::GroupPrimitive2D(
-                        aSubContent));
-            }
-        }
-
-        // apply new settings to current properties by setting
-        // the new region now
-        rPropertyHolders.Current().setClipPolyPolygonActive(bNewActive);
-
-        if(bNewActive)
-        {
-            rPropertyHolders.Current().setClipPolyPolygon(rClipPolyPolygon);
-
-            // prepare new content holder for new active region
-            rTargetHolders.Push();
-        }
-    }
-
-    /** helper to handle the change of RasterOp. It takes care of encapsulating all current
-        geometry to the current RasterOp (if changed) and needs to be called on any RasterOp
-        change. It will also start a new geometry target to embrace to the new RasterOp if
-        a changing RasterOp is used. Currently, RasterOp::Xor and RasterOp::Invert are supported using
-        InvertPrimitive2D, and RasterOp::N0 by using a ModifiedColorPrimitive2D to force to black paint
-     */
-    void HandleNewRasterOp(
-        RasterOp aRasterOp,
-        TargetHolders& rTargetHolders,
-        PropertyHolders& rPropertyHolders)
-    {
-        // check if currently active
-        if(rPropertyHolders.Current().isRasterOpActive() && rTargetHolders.size() > 1)
-        {
-            drawinglayer::primitive2d::Primitive2DContainer aSubContent;
-
-            if(rTargetHolders.Current().size())
-            {
-                aSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current());
-            }
-
-            rTargetHolders.Pop();
-
-            if(!aSubContent.empty())
-            {
-                if(rPropertyHolders.Current().isRasterOpForceBlack())
-                {
-                    // force content to black
-                    rTargetHolders.Current().append(
-                        new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
-                            aSubContent,
-                            basegfx::BColorModifierSharedPtr(
-                                new basegfx::BColorModifier_replace(
-                                    basegfx::BColor(0.0, 0.0, 0.0)))));
-                }
-                else // if(rPropertyHolders.Current().isRasterOpInvert())
-                {
-                    // invert content
-                    rTargetHolders.Current().append(
-                        new drawinglayer::primitive2d::InvertPrimitive2D(
-                            aSubContent));
-                }
-            }
-        }
-
-        // apply new settings
-        rPropertyHolders.Current().setRasterOp(aRasterOp);
-
-        // check if now active
-        if(rPropertyHolders.Current().isRasterOpActive())
-        {
-            // prepare new content holder for new invert
-            rTargetHolders.Push();
-        }
-    }
-
-    /** helper to create needed data to emulate the VCL Wallpaper Metafile action.
-        It is a quite mighty action. This helper is for simple color filled background.
-     */
-    drawinglayer::primitive2d::BasePrimitive2D* CreateColorWallpaper(
-        const basegfx::B2DRange& rRange,
-        const basegfx::BColor& rColor,
-        PropertyHolder& rPropertyHolder)
-    {
-        basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(rRange));
-        aOutline.transform(rPropertyHolder.getTransformation());
-
-        return new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
-            basegfx::B2DPolyPolygon(aOutline),
-            rColor);
-    }
-
-    /** helper to create needed data to emulate the VCL Wallpaper Metafile action.
-        It is a quite mighty action. This helper is for gradient filled background.
-     */
-    drawinglayer::primitive2d::BasePrimitive2D* CreateGradientWallpaper(
-        const basegfx::B2DRange& rRange,
-        const Gradient& rGradient,
-        PropertyHolder& rPropertyHolder)
-    {
-        const drawinglayer::attribute::FillGradientAttribute aAttribute(createFillGradientAttribute(rGradient));
-
-        if(aAttribute.getStartColor() == aAttribute.getEndColor())
-        {
-            // not really a gradient. Create filled rectangle
-            return CreateColorWallpaper(rRange, aAttribute.getStartColor(), rPropertyHolder);
-        }
-        else
-        {
-            // really a gradient
-            drawinglayer::primitive2d::BasePrimitive2D* pRetval =
-                new drawinglayer::primitive2d::FillGradientPrimitive2D(
-                    rRange,
-                    aAttribute);
-
-            if(!rPropertyHolder.getTransformation().isIdentity())
-            {
-                const drawinglayer::primitive2d::Primitive2DReference xPrim(pRetval);
-                const drawinglayer::primitive2d::Primitive2DContainer xSeq { xPrim };
-
-                pRetval = new drawinglayer::primitive2d::TransformPrimitive2D(
-                    rPropertyHolder.getTransformation(),
-                    xSeq);
-            }
-
-            return pRetval;
-        }
-    }
-
-    /** helper to create needed data to emulate the VCL Wallpaper Metafile action.
-        It is a quite mighty action. This helper decides if color and/or gradient
-        background is needed for the wanted bitmap fill and then creates the needed
-        WallpaperBitmapPrimitive2D. This primitive was created for this purpose and
-        takes over all needed logic of orientations and tiling.
-     */
-    void CreateAndAppendBitmapWallpaper(
-        basegfx::B2DRange aWallpaperRange,
-        const Wallpaper& rWallpaper,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperty)
-    {
-        const BitmapEx aBitmapEx(rWallpaper.GetBitmap());
-        const WallpaperStyle eWallpaperStyle(rWallpaper.GetStyle());
-
-        // if bitmap visualisation is transparent, maybe background
-        // needs to be filled. Create background
-        if(aBitmapEx.IsTransparent()
-            || (WallpaperStyle::Tile != eWallpaperStyle && WallpaperStyle::Scale != eWallpaperStyle))
-        {
-            if(rWallpaper.IsGradient())
-            {
-                rTarget.append(
-                    CreateGradientWallpaper(
-                        aWallpaperRange,
-                        rWallpaper.GetGradient(),
-                        rProperty));
-            }
-            else if(!rWallpaper.GetColor().GetTransparency())
-            {
-                rTarget.append(
-                    CreateColorWallpaper(
-                        aWallpaperRange,
-                        rWallpaper.GetColor().getBColor(),
-                        rProperty));
-            }
-        }
-
-        // use wallpaper rect if set
-        if(rWallpaper.IsRect() && !rWallpaper.GetRect().IsEmpty())
-        {
-            aWallpaperRange = basegfx::B2DRange(
-                rWallpaper.GetRect().Left(), rWallpaper.GetRect().Top(),
-                rWallpaper.GetRect().Right(), rWallpaper.GetRect().Bottom());
-        }
-
-        drawinglayer::primitive2d::BasePrimitive2D* pBitmapWallpaperFill =
-            new drawinglayer::primitive2d::WallpaperBitmapPrimitive2D(
-                aWallpaperRange,
-                aBitmapEx,
-                eWallpaperStyle);
-
-        if(rProperty.getTransformation().isIdentity())
-        {
-            // add directly
-            rTarget.append(pBitmapWallpaperFill);
-        }
-        else
-        {
-            // when a transformation is set, embed to it
-            const drawinglayer::primitive2d::Primitive2DReference xPrim(pBitmapWallpaperFill);
-
-            rTarget.append(
-                new drawinglayer::primitive2d::TransformPrimitive2D(
-                    rProperty.getTransformation(),
-                    drawinglayer::primitive2d::Primitive2DContainer { xPrim }));
-        }
-    }
-
-    /** helper to decide UnderlineAbove for text primitives */
-    bool isUnderlineAbove(const vcl::Font& rFont)
-    {
-        if(!rFont.IsVertical())
-        {
-            return false;
-        }
-
-        if((LANGUAGE_JAPANESE == rFont.GetLanguage()) || (LANGUAGE_JAPANESE == rFont.GetCJKContextLanguage()))
-        {
-            // the underline is right for Japanese only
-            return true;
-        }
-
-        return false;
-    }
-
-    void createFontAttributeTransformAndAlignment(
-        drawinglayer::attribute::FontAttribute& rFontAttribute,
-        basegfx::B2DHomMatrix& rTextTransform,
-        basegfx::B2DVector& rAlignmentOffset,
-        PropertyHolder& rProperty)
-    {
-        const vcl::Font& rFont = rProperty.getFont();
-        basegfx::B2DVector aFontScaling;
-
-        rFontAttribute = drawinglayer::attribute::FontAttribute(
-            drawinglayer::primitive2d::getFontAttributeFromVclFont(
-                aFontScaling,
-                rFont,
-                bool(rProperty.getLayoutMode() & ComplexTextLayoutFlags::BiDiRtl),
-                bool(rProperty.getLayoutMode() & ComplexTextLayoutFlags::BiDiStrong)));
-
-        // add FontScaling
-        rTextTransform.scale(aFontScaling.getX(), aFontScaling.getY());
-
-        // take text align into account
-        if(ALIGN_BASELINE != rFont.GetAlignment())
-        {
-            drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice;
-            aTextLayouterDevice.setFont(rFont);
-
-            if(ALIGN_TOP == rFont.GetAlignment())
-            {
-                rAlignmentOffset.setY(aTextLayouterDevice.getFontAscent());
-            }
-            else // ALIGN_BOTTOM
-            {
-                rAlignmentOffset.setY(-aTextLayouterDevice.getFontDescent());
-            }
-
-            rTextTransform.translate(rAlignmentOffset.getX(), rAlignmentOffset.getY());
-        }
-
-        // add FontRotation (if used)
-        if(rFont.GetOrientation())
-        {
-            rTextTransform.rotate(-rFont.GetOrientation() * F_PI1800);
-        }
-    }
-
-    /** helper which takes complete care for creating the needed text primitives. It
-        takes care of decorated stuff and all the geometry adaptions needed
-     */
-    void processMetaTextAction(
-        const Point& rTextStartPosition,
-        const OUString& rText,
-        sal_uInt16 nTextStart,
-        sal_uInt16 nTextLength,
-        const std::vector< double >& rDXArray,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperty)
-    {
-        drawinglayer::primitive2d::BasePrimitive2D* pResult = nullptr;
-        const vcl::Font& rFont = rProperty.getFont();
-        basegfx::B2DVector aAlignmentOffset(0.0, 0.0);
-
-        if(nTextLength)
-        {
-            drawinglayer::attribute::FontAttribute aFontAttribute;
-            basegfx::B2DHomMatrix aTextTransform;
-
-            // fill parameters derived from current font
-            createFontAttributeTransformAndAlignment(
-                aFontAttribute,
-                aTextTransform,
-                aAlignmentOffset,
-                rProperty);
-
-            // add TextStartPosition
-            aTextTransform.translate(rTextStartPosition.X(), rTextStartPosition.Y());
-
-            // prepare FontColor and Locale
-            const basegfx::BColor aFontColor(rProperty.getTextColor());
-            const Color aFillColor(rFont.GetFillColor());
-            const css::lang::Locale aLocale(LanguageTag(rProperty.getLanguageType()).getLocale());
-            const bool bWordLineMode(rFont.IsWordLineMode());
-
-            const bool bDecoratedIsNeeded(
-                   LINESTYLE_NONE != rFont.GetOverline()
-                || LINESTYLE_NONE != rFont.GetUnderline()
-                || STRIKEOUT_NONE != rFont.GetStrikeout()
-                || FontEmphasisMark::NONE != (rFont.GetEmphasisMark() & FontEmphasisMark::Style)
-                || FontRelief::NONE != rFont.GetRelief()
-                || rFont.IsShadow()
-                || bWordLineMode);
-
-            if(bDecoratedIsNeeded)
-            {
-                // prepare overline, underline and strikeout data
-                const drawinglayer::primitive2d::TextLine eFontOverline(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rFont.GetOverline()));
-                const drawinglayer::primitive2d::TextLine eFontLineStyle(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rFont.GetUnderline()));
-                const drawinglayer::primitive2d::TextStrikeout eTextStrikeout(drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rFont.GetStrikeout()));
-
-                // check UndelineAbove
-                const bool bUnderlineAbove(drawinglayer::primitive2d::TEXT_LINE_NONE != eFontLineStyle && isUnderlineAbove(rFont));
-
-                // prepare emphasis mark data
-                drawinglayer::primitive2d::TextEmphasisMark eTextEmphasisMark(drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_NONE);
-
-                switch(rFont.GetEmphasisMark() & FontEmphasisMark::Style)
-                {
-                    case FontEmphasisMark::Dot : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_DOT; break;
-                    case FontEmphasisMark::Circle : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_CIRCLE; break;
-                    case FontEmphasisMark::Disc : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_DISC; break;
-                    case FontEmphasisMark::Accent : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_ACCENT; break;
-                    default: break;
-                }
-
-                const bool bEmphasisMarkAbove(rFont.GetEmphasisMark() & FontEmphasisMark::PosAbove);
-                const bool bEmphasisMarkBelow(rFont.GetEmphasisMark() & FontEmphasisMark::PosBelow);
-
-                // prepare font relief data
-                drawinglayer::primitive2d::TextRelief eTextRelief(drawinglayer::primitive2d::TEXT_RELIEF_NONE);
-
-                switch(rFont.GetRelief())
-                {
-                    case FontRelief::Embossed : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_EMBOSSED; break;
-                    case FontRelief::Engraved : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_ENGRAVED; break;
-                    default : break; // RELIEF_NONE, FontRelief_FORCE_EQUAL_SIZE
-                }
-
-                // prepare shadow/outline data
-                const bool bShadow(rFont.IsShadow());
-
-                // TextDecoratedPortionPrimitive2D is needed, create one
-                pResult = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
-
-                    // attributes for TextSimplePortionPrimitive2D
-                    aTextTransform,
-                    rText,
-                    nTextStart,
-                    nTextLength,
-                    rDXArray,
-                    aFontAttribute,
-                    aLocale,
-                    aFontColor,
-                    aFillColor,
-
-                    // attributes for TextDecoratedPortionPrimitive2D
-                    rProperty.getOverlineColorActive() ? rProperty.getOverlineColor() : aFontColor,
-                    rProperty.getTextLineColorActive() ? rProperty.getTextLineColor() : aFontColor,
-                    eFontOverline,
-                    eFontLineStyle,
-                    bUnderlineAbove,
-                    eTextStrikeout,
-                    bWordLineMode,
-                    eTextEmphasisMark,
-                    bEmphasisMarkAbove,
-                    bEmphasisMarkBelow,
-                    eTextRelief,
-                    bShadow);
-            }
-            else
-            {
-                // TextSimplePortionPrimitive2D is enough
-                pResult = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
-                    aTextTransform,
-                    rText,
-                    nTextStart,
-                    nTextLength,
-                    rDXArray,
-                    aFontAttribute,
-                    aLocale,
-                    aFontColor);
-            }
-        }
-
-        if(pResult && rProperty.getTextFillColorActive())
-        {
-            // text background is requested, add and encapsulate both to new primitive
-            drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice;
-            aTextLayouterDevice.setFont(rFont);
-
-            // get text width
-            double fTextWidth(0.0);
-
-            if(rDXArray.empty())
-            {
-                fTextWidth = aTextLayouterDevice.getTextWidth(rText, nTextStart, nTextLength);
-            }
-            else
-            {
-                fTextWidth = rDXArray.back();
-            }
-
-            if(basegfx::fTools::more(fTextWidth, 0.0))
-            {
-                // build text range
-                const basegfx::B2DRange aTextRange(
-                    0.0, -aTextLayouterDevice.getFontAscent(),
-                    fTextWidth, aTextLayouterDevice.getFontDescent());
-
-                // create Transform
-                basegfx::B2DHomMatrix aTextTransform;
-
-                aTextTransform.translate(aAlignmentOffset.getX(), aAlignmentOffset.getY());
-
-                if(rFont.GetOrientation())
-                {
-                    aTextTransform.rotate(-rFont.GetOrientation() * F_PI1800);
-                }
-
-                aTextTransform.translate(rTextStartPosition.X(), rTextStartPosition.Y());
-
-                // prepare Primitive2DSequence, put text in foreground
-                drawinglayer::primitive2d::Primitive2DContainer aSequence(2);
-                aSequence[1] = drawinglayer::primitive2d::Primitive2DReference(pResult);
-
-                // prepare filled polygon
-                basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aTextRange));
-                aOutline.transform(aTextTransform);
-
-                aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(
-                    new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
-                        basegfx::B2DPolyPolygon(aOutline),
-                        rProperty.getTextFillColor()));
-
-                // set as group at pResult
-                pResult = new drawinglayer::primitive2d::GroupPrimitive2D(aSequence);
-            }
-        }
-
-        if(pResult)
-        {
-            // add created text primitive to target
-            if(rProperty.getTransformation().isIdentity())
-            {
-                rTarget.append(pResult);
-            }
-            else
-            {
-                // when a transformation is set, embed to it
-                const drawinglayer::primitive2d::Primitive2DReference aReference(pResult);
-
-                rTarget.append(
-                    new drawinglayer::primitive2d::TransformPrimitive2D(
-                        rProperty.getTransformation(),
-                        drawinglayer::primitive2d::Primitive2DContainer { aReference }));
-            }
-        }
-    }
-
-    /** helper which takes complete care for creating the needed textLine primitives */
-    void proccessMetaTextLineAction(
-        const MetaTextLineAction& rAction,
-        TargetHolder& rTarget,
-        PropertyHolder& rProperty)
-    {
-        const double fLineWidth(fabs((double)rAction.GetWidth()));
-
-        if(fLineWidth > 0.0)
-        {
-            const drawinglayer::primitive2d::TextLine aOverlineMode(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rAction.GetOverline()));
-            const drawinglayer::primitive2d::TextLine aUnderlineMode(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rAction.GetUnderline()));
-            const drawinglayer::primitive2d::TextStrikeout aTextStrikeout(drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rAction.GetStrikeout()));
-
-            const bool bOverlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aOverlineMode);
-            const bool bUnderlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aUnderlineMode);
-            const bool bStrikeoutUsed(drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE != aTextStrikeout);
-
-            if(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed)
-            {
-                std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargetVector;
-                basegfx::B2DVector aAlignmentOffset(0.0, 0.0);
-                drawinglayer::attribute::FontAttribute aFontAttribute;
-                basegfx::B2DHomMatrix aTextTransform;
-
-                // fill parameters derived from current font
-                createFontAttributeTransformAndAlignment(
-                    aFontAttribute,
-                    aTextTransform,
-                    aAlignmentOffset,
-                    rProperty);
-
-                // add TextStartPosition
-                aTextTransform.translate(rAction.GetStartPoint().X(), rAction.GetStartPoint().Y());
-
-                // prepare TextLayouter (used in most cases)
-                drawinglayer::primitive2d::TextLayouterDevice aTextLayouter;
-                aTextLayouter.setFont(rProperty.getFont());
-
-                if(bOverlineUsed)
-                {
-                    // create primitive geometry for overline
-                    aTargetVector.push_back(
-                        new drawinglayer::primitive2d::TextLinePrimitive2D(
-                            aTextTransform,
-                            fLineWidth,
-                            aTextLayouter.getOverlineOffset(),
-                            aTextLayouter.getOverlineHeight(),
-                            aOverlineMode,
-                            rProperty.getOverlineColor()));
-                }
-
-                if(bUnderlineUsed)
-                {
-                    // create primitive geometry for underline
-                    aTargetVector.push_back(
-                        new drawinglayer::primitive2d::TextLinePrimitive2D(
-                            aTextTransform,
-                            fLineWidth,
-                            aTextLayouter.getUnderlineOffset(),
-                            aTextLayouter.getUnderlineHeight(),
-                            aUnderlineMode,
-                            rProperty.getTextLineColor()));
-                }
-
-                if(bStrikeoutUsed)
-                {
-                    // create primitive geometry for strikeout
-                    if(drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout
-                        || drawinglayer::primitive2d::TEXT_STRIKEOUT_X == aTextStrikeout)
-                    {
-                        // strikeout with character
-                        const sal_Unicode aStrikeoutChar(
-                            drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout ? '/' : 'X');
-                        const css::lang::Locale aLocale(LanguageTag(
-                            rProperty.getLanguageType()).getLocale());
-
-                        aTargetVector.push_back(
-                            new drawinglayer::primitive2d::TextCharacterStrikeoutPrimitive2D(
-                                aTextTransform,
-                                fLineWidth,
-                                rProperty.getTextColor(),
-                                aStrikeoutChar,
-                                aFontAttribute,
-                                aLocale));
-                    }
-                    else
-                    {
-                        // strikeout with geometry
-                        aTargetVector.push_back(
-                            new drawinglayer::primitive2d::TextGeometryStrikeoutPrimitive2D(
-                                aTextTransform,
-                                fLineWidth,
-                                rProperty.getTextColor(),
-                                aTextLayouter.getUnderlineHeight(),
-                                aTextLayouter.getStrikeoutOffset(),
-                                aTextStrikeout));
-                    }
-                }
-
-                if(!aTargetVector.empty())
-                {
-                    // add created text primitive to target
-                    if(rProperty.getTransformation().isIdentity())
-                    {
-                        for(drawinglayer::primitive2d::BasePrimitive2D* a : aTargetVector)
-                        {
-                            rTarget.append(a);
-                        }
-                    }
-                    else
-                    {
-                        // when a transformation is set, embed to it
-                        drawinglayer::primitive2d::Primitive2DContainer xTargets(aTargetVector.size());
-
-                        for(size_t a(0); a < aTargetVector.size(); a++)
-                        {
-                            xTargets[a] = drawinglayer::primitive2d::Primitive2DReference(aTargetVector[a]);
-                        }
-
-                        rTarget.append(
-                            new drawinglayer::primitive2d::TransformPrimitive2D(
-                                rProperty.getTransformation(),
-                                xTargets));
-                    }
-                }
-            }
-        }
-
-    }
-
-    /** This is the main interpreter method. It is designed to handle the given Metafile
-        completely inside the given context and target. It may use and modify the context and
-        target. This design allows to call itself recursively which adapted contexts and
-        targets as e.g. needed for the MetaActionType::FLOATTRANSPARENT where the content is expressed
-        as a metafile as sub-content.
-
-        This interpreter is as free of VCL functionality as possible. It uses VCL data classes
-        (else reading the data would not be possible), but e.g. does NOT use a local OutputDevice
-        as most other MetaFile interpreters/exporters do to hold and work with the current context.
-        This is necessary to be able to get away from the strong internal VCL-binding.
-
-        It tries to combine e.g. pixel and/or point actions and to stitch together single line primitives
-        where possible (which is not trivial with the possible line geometry definitions).
-
-        It tries to handle clipping no longer as Regions and spans of Rectangles, but as PolyPolygon
-        ClipRegions with (where possible) high precision by using the best possible data quality
-        from the Region. The vcl::Region is unavoidable as data container, but nowadays allows the transport
-        of Polygon-based clip regions. Where this is not used, a Polygon is constructed from the
-        vcl::Region ranges. All primitive clipping uses the MaskPrimitive2D with Polygon-based clipping.
-
-        I have marked the single MetaActions with:
-
-        SIMPLE, DONE:
-        Simple, e.g nothing to do or value setting in the context
-
-        CHECKED, WORKS WELL:
-        Thoroughly tested with extra written test code which created a replacement
-        Metafile just to test this action in various combinations
-
-        NEEDS IMPLEMENTATION:
-        Not implemented and asserted, but also no usage found, neither in own Metafile
-        creations, nor in EMF/WMF imports (checked with a whole bunch of critical EMF/WMF
-        bugdocs)
-
-        For more comments, see the single action implementations.
-    */
-    void interpretMetafile(
-        const GDIMetaFile& rMetaFile,
-        TargetHolders& rTargetHolders,
-        PropertyHolders& rPropertyHolders,
-        const drawinglayer::geometry::ViewInformation2D& rViewInformation)
-    {
-        const size_t nCount(rMetaFile.GetActionSize());
-
-        for(size_t nAction(0); nAction < nCount; nAction++)
-        {
-            MetaAction* pAction = rMetaFile.GetAction(nAction);
-
-            switch(pAction->GetType())
-            {
-                case MetaActionType::NONE :
-                {
-                    /** SIMPLE, DONE */
-                    break;
-                }
-                case MetaActionType::PIXEL :
-                {
-                    /** CHECKED, WORKS WELL */
-                    std::vector< basegfx::B2DPoint > aPositions;
-                    Color aLastColor(COL_BLACK);
-
-                    while(MetaActionType::PIXEL == pAction->GetType() && nAction < nCount)
-                    {
-                        const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
-
-                        if(pA->GetColor() != aLastColor)
-                        {
-                            if(!aPositions.empty())
-                            {
-                                createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor());
-                                aPositions.clear();
-                            }
-
-                            aLastColor = pA->GetColor();
-                        }
-
-                        const Point& rPoint = pA->GetPoint();
-                        aPositions.push_back(basegfx::B2DPoint(rPoint.X(), rPoint.Y()));
-                        nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction);
-                    }
-
-                    nAction--;
-
-                    if(!aPositions.empty())
-                    {
-                        createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), aLastColor.getBColor());
-                    }
-
-                    break;
-                }
-                case MetaActionType::POINT :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineColorActive())
-                    {
-                        std::vector< basegfx::B2DPoint > aPositions;
-
-                        while(MetaActionType::POINT == pAction->GetType() && nAction < nCount)
-                        {
-                            const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
-                            const Point& rPoint = pA->GetPoint();
-                            aPositions.push_back(basegfx::B2DPoint(rPoint.X(), rPoint.Y()));
-                            nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction);
-                        }
-
-                        nAction--;
-
-                        if(!aPositions.empty())
-                        {
-                            createPointArrayPrimitive(aPositions, rTargetHolders.Current(), rPropertyHolders.Current(), rPropertyHolders.Current().getLineColor());
-                        }
-                    }
-
-                    break;
-                }
-                case MetaActionType::LINE :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineColorActive())
-                    {
-                        basegfx::B2DPolygon aLinePolygon;
-                        LineInfo aLineInfo;
-
-                        while(MetaActionType::LINE == pAction->GetType() && nAction < nCount)
-                        {
-                            const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
-                            const Point& rStartPoint = pA->GetStartPoint();
-                            const Point& rEndPoint = pA->GetEndPoint();
-                            const basegfx::B2DPoint aStart(rStartPoint.X(), rStartPoint.Y());
-                            const basegfx::B2DPoint aEnd(rEndPoint.X(), rEndPoint.Y());
-
-                            if(aLinePolygon.count())
-                            {
-                                if(pA->GetLineInfo() == aLineInfo
-                                    && aStart == aLinePolygon.getB2DPoint(aLinePolygon.count() - 1))
-                                {
-                                    aLinePolygon.append(aEnd);
-                                }
-                                else
-                                {
-                                    aLineInfo.SetLineJoin(basegfx::B2DLineJoin::NONE); // It were lines; force to NONE
-                                    createLinePrimitive(aLinePolygon, aLineInfo, rTargetHolders.Current(), rPropertyHolders.Current());
-                                    aLinePolygon.clear();
-                                    aLineInfo = pA->GetLineInfo();
-                                    aLinePolygon.append(aStart);
-                                    aLinePolygon.append(aEnd);
-                                }
-                            }
-                            else
-                            {
-                                aLineInfo = pA->GetLineInfo();
-                                aLinePolygon.append(aStart);
-                                aLinePolygon.append(aEnd);
-                            }
-
-                            nAction++; if(nAction < nCount) pAction = rMetaFile.GetAction(nAction);
-                        }
-
-                        nAction--;
-
-                        if(aLinePolygon.count())
-                        {
-                            aLineInfo.SetLineJoin(basegfx::B2DLineJoin::NONE); // It were lines; force to NONE
-                            createLinePrimitive(aLinePolygon, aLineInfo, rTargetHolders.Current(), rPropertyHolders.Current());
-                        }
-                    }
-
-                    break;
-                }
-                case MetaActionType::RECT :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaRectAction* pA = static_cast<const MetaRectAction*>(pAction);
-                        const tools::Rectangle& rRectangle = pA->GetRect();
-
-                        if(!rRectangle.IsEmpty())
-                        {
-                            const basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom());
-
-                            if(!aRange.isEmpty())
-                            {
-                                const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange));
-                                createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                            }
-                        }
-                    }
-
-                    break;
-                }
-                case MetaActionType::ROUNDRECT :
-                {
-                    /** CHECKED, WORKS WELL */
-                    /** The original OutputDevice::DrawRect paints nothing when nHor or nVer is zero; but just
-                        because the tools::Polygon operator creating the rounding does produce nonsense. I assume
-                        this an error and create an unrounded rectangle in that case (implicit in
-                        createPolygonFromRect)
-                     */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
-                        const tools::Rectangle& rRectangle = pA->GetRect();
-
-                        if(!rRectangle.IsEmpty())
-                        {
-                            const basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom());
-
-                            if(!aRange.isEmpty())
-                            {
-                                const sal_uInt32 nHor(pA->GetHorzRound());
-                                const sal_uInt32 nVer(pA->GetVertRound());
-                                basegfx::B2DPolygon aOutline;
-
-                                if(nHor || nVer)
-                                {
-                                    double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0));
-                                    double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0));
-                                    fRadiusX = std::max(0.0, std::min(1.0, fRadiusX));
-                                    fRadiusY = std::max(0.0, std::min(1.0, fRadiusY));
-
-                                    aOutline = basegfx::tools::createPolygonFromRect(aRange, fRadiusX, fRadiusY);
-                                }
-                                else
-                                {
-                                    aOutline = basegfx::tools::createPolygonFromRect(aRange);
-                                }
-
-                                createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                            }
-                        }
-                    }
-
-                    break;
-                }
-                case MetaActionType::ELLIPSE :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
-                        const tools::Rectangle& rRectangle = pA->GetRect();
-
-                        if(!rRectangle.IsEmpty())
-                        {
-                            const basegfx::B2DRange aRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom());
-
-                            if(!aRange.isEmpty())
-                            {
-                                const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromEllipse(
-                                    aRange.getCenter(), aRange.getWidth() * 0.5, aRange.getHeight() * 0.5));
-
-                                createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                            }
-                        }
-                    }
-
-                    break;
-                }
-                case MetaActionType::ARC :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineColorActive())
-                    {
-                        const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
-                        const tools::Polygon aToolsPoly(pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Arc);
-                        const basegfx::B2DPolygon aOutline(aToolsPoly.getB2DPolygon());
-
-                        createHairlinePrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                    }
-
-                    break;
-                }
-                case MetaActionType::PIE :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaPieAction* pA = static_cast<const MetaPieAction*>(pAction);
-                        const tools::Polygon aToolsPoly(pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Pie);
-                        const basegfx::B2DPolygon aOutline(aToolsPoly.getB2DPolygon());
-
-                        createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                    }
-
-                    break;
-                }
-                case MetaActionType::CHORD :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
-                        const tools::Polygon aToolsPoly(pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Chord);
-                        const basegfx::B2DPolygon aOutline(aToolsPoly.getB2DPolygon());
-
-                        createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                    }
-
-                    break;
-                }
-                case MetaActionType::POLYLINE :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineColorActive())
-                    {
-                        const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pAction);
-                        createLinePrimitive(pA->GetPolygon().getB2DPolygon(), pA->GetLineInfo(), rTargetHolders.Current(), rPropertyHolders.Current());
-                    }
-
-                    break;
-                }
-                case MetaActionType::POLYGON :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaPolygonAction* pA = static_cast<const MetaPolygonAction*>(pAction);
-                        basegfx::B2DPolygon aOutline(pA->GetPolygon().getB2DPolygon());
-
-                        // the metafile play interprets the polygons from MetaPolygonAction
-                        // always as closed and always paints an edge from last to first point,
-                        // so force to closed here to emulate that
-                        if(aOutline.count() > 1 && !aOutline.isClosed())
-                        {
-                            aOutline.setClosed(true);
-                        }
-
-                        createHairlineAndFillPrimitive(aOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                    }
-
-                    break;
-                }
-                case MetaActionType::POLYPOLYGON :
-                {
-                    /** CHECKED, WORKS WELL */
-                    if(rPropertyHolders.Current().getLineOrFillActive())
-                    {
-                        const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pAction);
-                        basegfx::B2DPolyPolygon aPolyPolygonOutline(pA->GetPolyPolygon().getB2DPolyPolygon());
-
-                        // the metafile play interprets the single polygons from MetaPolyPolygonAction
-                        // always as closed and always paints an edge from last to first point,
-                        // so force to closed here to emulate that
-                        for(sal_uInt32 b(0); b < aPolyPolygonOutline.count(); b++)
-                        {
-                            basegfx::B2DPolygon aPolygonOutline(aPolyPolygonOutline.getB2DPolygon(b));
-
-                            if(aPolygonOutline.count() > 1 && !aPolygonOutline.isClosed())
-                            {
-                                aPolygonOutline.setClosed(true);
-                                aPolyPolygonOutline.setB2DPolygon(b, aPolygonOutline);
-                            }
-                        }
-
-                        createHairlineAndFillPrimitive(aPolyPolygonOutline, rTargetHolders.Current(), rPropertyHolders.Current());
-                    }
-
-                    break;
-                }
-                case MetaActionType::TEXT :
-                {
-                    /** CHECKED, WORKS WELL */
-                    const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
-                    sal_uInt32 nTextLength(pA->GetLen());
-                    const sal_uInt32 nTextIndex(pA->GetIndex());
-                    const sal_uInt32 nStringLength(pA->GetText().getLength());
-
-                    if(nTextLength + nTextIndex > nStringLength)
-                    {
-                        nTextLength = nStringLength - nTextIndex;
-                    }
-
-                    if(nTextLength && rPropertyHolders.Current().getTextColorActive())
-                    {
-                        const std::vector< double > aDXArray{};
-                        processMetaTextAction(
-                            pA->GetPoint(),
-                            pA->GetText(),
-                            nTextIndex,
-                            nTextLength,
-                            aDXArray,

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list