[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-5-2+backports' - include/svx svx/Library_svxcore.mk svx/source sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Oct 24 18:58:17 UTC 2018


 include/svx/framelink.hxx                                 |  109 -
 include/svx/framelinkarray.hxx                            |    5 
 include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx |  119 ++
 include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx      |    1 
 svx/Library_svxcore.mk                                    |    1 
 svx/source/dialog/framelink.cxx                           |  467 --------
 svx/source/dialog/framelinkarray.cxx                      |  260 +---
 svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx  |  768 ++++++++++++++
 sw/source/core/layout/paintfrm.cxx                        |  194 +--
 9 files changed, 1078 insertions(+), 846 deletions(-)

New commits:
commit 1b9bc3c3f6f3fb31802be37592fcf4153d3d420d
Author:     Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Mon Oct 22 10:33:03 2018 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Oct 24 20:57:51 2018 +0200

    Reorganize FrameBorderPrimitive creation
    
    Step1: Basic concept, move stuff to svx and new
    SdrFrameBorderPrimitive2D
    
    Step2: Adapt all creators/usages to use
    SdrFrameBorderData/SdrFrameBorderPrimitive2D,
    check functionality
    
    Step3: Re-implement mergre of BorderLinePrimitive2D
    during decomposition of SdrFrameBorderPrimitive2D
    to keep the number of primitives low from the start,
    make merge optional (not urgently needed)
    
    Step4: Migrate and isolate all helper methods
    and classes involved in geometry creation of border
    lines to the implementation (.cxx) of the new
    primitive
    
    Change-Id: I840b6765439bd995f2c57ef36315427b1f0f3e21
    Reviewed-on: https://gerrit.libreoffice.org/62247
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>
    Reviewed-on: https://gerrit.libreoffice.org/62309
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 65f1920fd093..5861b9eb58f2 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -201,115 +201,6 @@ public:
 
 inline bool operator>( const Style& rL, const Style& rR ) { return rR.operator<(rL); }
 
-// Drawing functions
-class SAL_WARN_UNUSED SVX_DLLPUBLIC StyleVectorCombination
-{
-private:
-    struct OffsetAndHalfWidthAndColor
-    {
-        double          mfOffset;
-        double          mfHalfWidth;
-        Color           maColor;
-
-        OffsetAndHalfWidthAndColor(double offset, double halfWidth, Color color) :
-            mfOffset(offset),
-            mfHalfWidth(halfWidth),
-            maColor(color)
-        {}
-    };
-
-    double                                      mfRefModeOffset;
-    basegfx::B2DVector                          maB2DVector;
-    double                                      mfAngle;
-    std::vector< OffsetAndHalfWidthAndColor >   maOffsets;
-
-public:
-    StyleVectorCombination(
-        const Style& rStyle,
-        const basegfx::B2DVector& rB2DVector,
-        const double fAngle,
-        bool bMirrored,
-        const Color* pForceColor = nullptr);
-
-    double getRefModeOffset() const { return mfRefModeOffset; }
-    const basegfx::B2DVector& getB2DVector() const { return maB2DVector; }
-    double getAngle() const { return mfAngle; }
-    bool empty() const { return maOffsets.empty(); }
-    size_t size() const { return maOffsets.size(); }
-    bool operator<( const StyleVectorCombination& rOther) const { return mfAngle < rOther.mfAngle; }
-
-    void getColorAndOffsetAndHalfWidth(size_t nIndex, Color& rColor, double& rfOffset, double& rfHalfWidth) const;
-};
-
-class SAL_WARN_UNUSED SVX_DLLPUBLIC StyleVectorTable
-{
-private:
-    std::vector< StyleVectorCombination >       maEntries;
-
-public:
-    StyleVectorTable()
-    :   maEntries()
-    {
-    }
-
-    void add(
-        const Style& rStyle,
-        const basegfx::B2DVector& rMyVector,
-        const basegfx::B2DVector& rOtherVector,
-        bool bMirrored);
-
-    void sort();
-
-    bool empty() const { return maEntries.empty(); }
-    size_t size() const { return maEntries.size(); }
-    const std::vector< StyleVectorCombination >& getEntries() const{ return maEntries; }
-};
-
-/**
- *  Helper method to create the correct drawinglayer::primitive2d::BorderLinePrimitive2D
- *  for the given data, especially the correct drawinglayer::primitive2d::BorderLine entries
- *  including the correctly solved/created LineStartEnd extends
- *
- *  rTarget : Here the evtl. created BorderLinePrimitive2D will be appended
- *  rOrigin : StartPoint of the Borderline
- *  rX      : Vector of the Borderline
- *  rBorder : svx::frame::Style of the of the Borderline
- *  rStartStyleVectorTable : All other Borderlines which have to be taken into account because
- *      they have the same StartPoint as the current Borderline. These will be used to calculate
- *      the correct LineStartEnd extends tor the BorderLinePrimitive2D. The definition should be
- *      built up using svx::frame::StyleVectorTable and StyleVectorTable::add and includes:
- *          rStyle      : the svx::frame::Style of one other BorderLine
- *          rMyVector   : the Vector of the *new* to-be-defined BorderLine, identical to rX
- *          rOtherVector: the Vector of one other BorderLine (may be, but does not need to be normalized),
- *                        always *pointing away* from the common StartPoint rOrigin
- *          bMirrored   : define if rStyle of one other BorderLine shall be mirrored (e.g. bottom-right edges)
- *      With multiple BorderLines the definitions have to be CounterClockWise. This will be
- *      ensured by StyleVectorTable sorting the entries, but knowing this may allow more efficcient
- *      data creation.
- *  rEndStyleVectorTable: All other BorderLines that have the same EndPoint. There are differences to
- *      the Start definitions:
- *          - do not forget to consequently use -rX for rMyVector
- *          - definitions have to be ClockWise for the EndBorderLines, will be ensured by sorting
- *
- *  If you take all this into account, you will gett correctly extended BorderLinePrimitive2D
- *  reprsentations for the new to be defined BorderLine. That extensions will overlap nicely
- *  with the corresponding BordreLines and take all multiple line definitions in the ::Style into
- *  account.
- *  The internal solver is *not limitied* to ::Style(s) with three parts (Left/Gap/Right), this is
- *  just due to svx::frame::Style's definitions. A new solver based on this one can be created
- *  anytime using more mulötiple borders based on the more flexible
- *  std::vector< drawinglayer::primitive2d::BorderLine > if needed.
- */
-SVX_DLLPUBLIC void CreateBorderPrimitives(
-    drawinglayer::primitive2d::Primitive2DContainer&    rTarget,        /// target for created primitives
-    const basegfx::B2DPoint&    rOrigin,                /// start point of borderline
-    const basegfx::B2DVector&   rX,                     /// X-Axis of borderline with length
-    const Style&                rBorder,                /// Style of borderline
-    const StyleVectorTable&     rStartStyleVectorTable, /// Styles and vectors (pointing away) at borderline start, ccw
-    const StyleVectorTable&     rEndStyleVectorTable,   /// Styles and vectors (pointing away) at borderline end, cw
-    const Color*                pForceColor             /// If specified, overrides frame border color.
-);
-
 }
 }
 
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index c2c207cec5a8..7a4d8e9df640 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -323,11 +323,6 @@ private:
     ArrayImplPtr        mxImpl;
 };
 
-// helper to merge B2DPrimitive(s) in rSource and add to rTarget
-void SVX_DLLPUBLIC HelperMergeInB2DPrimitiveArray(
-    const drawinglayer::primitive2d::Primitive2DContainer& rSource,
-    drawinglayer::primitive2d::Primitive2DContainer& rTarget);
-
 }
 }
 
diff --git a/include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx b/include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx
new file mode 100755
index 000000000000..611ec6b20285
--- /dev/null
+++ b/include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx
@@ -0,0 +1,119 @@
+/* -*- 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_SVX_INC_SDR_PRIMITIVE2D_SDRFRAMEBORDERPRIMITIVE2D_HXX
+#define INCLUDED_SVX_INC_SDR_PRIMITIVE2D_SDRFRAMEBORDERPRIMITIVE2D_HXX
+
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <svx/framelink.hxx>
+
+// predefines
+
+namespace drawinglayer
+{
+    namespace primitive2d
+    {
+        class SVX_DLLPUBLIC SdrFrameBorderData
+        {
+        private:
+            basegfx::B2DPoint   maOrigin;       /// start point of borderline
+            basegfx::B2DVector  maX;            /// X-Axis of borderline with length
+            svx::frame::Style   maStyle;        /// Style of borderline
+            Color               maColor;
+            bool                mbForceColor;
+
+            class SdrConnectStyleData
+            {
+            private:
+                svx::frame::Style   maStyle;
+                basegfx::B2DVector  maNormalizedPerpendicular;
+                bool                mbStyleMirrored;
+
+            public:
+                SdrConnectStyleData(
+                    const svx::frame::Style& rStyle,
+                    const basegfx::B2DVector& rNormalizedPerpendicular,
+                    bool bStyleMirrored);
+
+                const svx::frame::Style& getStyle() const { return maStyle; }
+                const basegfx::B2DVector& getNormalizedPerpendicular() const { return maNormalizedPerpendicular; }
+                bool getStyleMirrored() const { return  mbStyleMirrored; }
+            };
+
+            std::vector<SdrConnectStyleData>   maStart;
+            std::vector<SdrConnectStyleData>   maEnd;
+
+        public:
+            SdrFrameBorderData(
+                const basegfx::B2DPoint& rOrigin,
+                const basegfx::B2DVector& rX,
+                const svx::frame::Style& rStyle,
+                const Color* pForceColor);
+
+            void addSdrConnectStyleData(
+                bool bStart,
+                const svx::frame::Style& rStyle,
+                const basegfx::B2DVector& rNormalizedPerpendicular,
+                bool bStyleMirrored);
+
+            void create2DDecomposition(Primitive2DContainer& rContainer) const;
+        };
+
+        typedef std::vector<SdrFrameBorderData> SdrFrameBorderDataVector;
+
+    } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+    namespace primitive2d
+    {
+        class SVX_DLLPUBLIC SdrFrameBorderPrimitive2D : public BufferedDecompositionPrimitive2D
+        {
+        private:
+            std::shared_ptr<SdrFrameBorderDataVector>   maFrameBorders;
+            bool                                        mbMergeResult;
+
+        protected:
+            // local decomposition.
+            virtual Primitive2DContainer create2DDecomposition(
+                const geometry::ViewInformation2D& aViewInformation) const override;
+
+        public:
+            SdrFrameBorderPrimitive2D(
+                std::shared_ptr<SdrFrameBorderDataVector>& rFrameBorders,
+                bool bMergeResult);
+
+            // compare operator
+            virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
+
+            // data access
+            const SdrFrameBorderDataVector& getFrameBorders() const { return *maFrameBorders.get(); }
+            bool getMergeResult() const { return mbMergeResult; }
+
+            // provide unique ID
+            DeclPrimitive2DIDBlock()
+        };
+    } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+
+#endif // INCLUDED_SVX_INC_SDR_PRIMITIVE2D_SDRFRAMEBORDERPRIMITIVE2D_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
index d2a16623dd02..d6cb948a6bf6 100644
--- a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
+++ b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
@@ -47,6 +47,7 @@
 #define PRIMITIVE2D_ID_SDROLECONTENTPRIMITIVE2D         (PRIMITIVE2D_ID_RANGE_SVX| 21)
 #define PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 22)
 #define PRIMITIVE2D_ID_SDRCHAINEDTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 23)
+#define PRIMITIVE2D_ID_SDRFRAMEBORDERTPRIMITIVE2D       (PRIMITIVE2D_ID_RANGE_SVX| 24)
 
 
 #endif // INCLUDED_SVX_SDR_PRIMITIVE2D_SVX_PRIMITIVETYPES2D_HXX
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 4bb7dcab835f..8c58029d5949 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -247,6 +247,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
     svx/source/sdr/primitive2d/sdrcaptionprimitive2d \
     svx/source/sdr/primitive2d/sdrconnectorprimitive2d \
     svx/source/sdr/primitive2d/sdrmeasureprimitive2d \
+    svx/source/sdr/primitive2d/sdrframeborderprimitive2d \
     svx/source/sdr/primitive2d/sdrattributecreator \
     svx/source/sdr/primitive2d/sdrdecompositiontools \
     svx/source/sdr/primitive3d/sdrattributecreator3d \
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index 4474602c78c6..80dd02450576 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -28,10 +28,6 @@
 #include <tools/gen.hxx>
 #include <editeng/borderline.hxx>
 #include <svtools/borderhelper.hxx>
-
-#include <basegfx/polygon/b2dpolygon.hxx>
-#include <basegfx/polygon/b2dpolygontools.hxx>
-
 #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
 
 
@@ -334,469 +330,6 @@ bool Style::operator<( const Style& rOther) const
     // seem to be equal
     return false;
 }
-
-// Drawing functions
-struct CutSet
-{
-    double          mfOLML;
-    double          mfORML;
-    double          mfOLMR;
-    double          mfORMR;
-
-    CutSet() : mfOLML(0.0), mfORML(0.0), mfOLMR(0.0), mfORMR(0.0)
-    {
-    }
-
-    bool operator<( const CutSet& rOther) const
-    {
-        const double fA(mfOLML + mfORML + mfOLMR + mfORMR);
-        const double fB(rOther.mfOLML + rOther.mfORML + rOther.mfOLMR + rOther.mfORMR);
-
-        return fA < fB;
-    }
-
-    double getSum() const { return mfOLML + mfORML + mfOLMR + mfORMR; }
- } ;
-
-struct ExtendSet
-{
-    double          mfExtLeft;
-    double          mfExtRight;
-
-    ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
-};
-
-void getCutSet(
-    CutSet& rCutSet,
-    const basegfx::B2DPoint& rLeft,
-    const basegfx::B2DPoint& rRight,
-    const basegfx::B2DVector& rX,
-    const basegfx::B2DPoint& rOtherLeft,
-    const basegfx::B2DPoint& rOtherRight,
-    const basegfx::B2DVector& rOtherX)
-{
-    basegfx::tools::findCut(
-        rLeft,
-        rX,
-        rOtherLeft,
-        rOtherX,
-        CutFlagValue::LINE,
-        &rCutSet.mfOLML);
-
-    basegfx::tools::findCut(
-        rRight,
-        rX,
-        rOtherLeft,
-        rOtherX,
-        CutFlagValue::LINE,
-        &rCutSet.mfOLMR);
-
-    basegfx::tools::findCut(
-        rLeft,
-        rX,
-        rOtherRight,
-        rOtherX,
-        CutFlagValue::LINE,
-        &rCutSet.mfORML);
-
-    basegfx::tools::findCut(
-        rRight,
-        rX,
-        rOtherRight,
-        rOtherX,
-        CutFlagValue::LINE,
-        &rCutSet.mfORMR);
-}
-
-void getExtends(
-    std::vector<ExtendSet>& rExtendSet,                         // target Left/Right values to fill
-    const basegfx::B2DPoint& rOrigin,                           // own vector start
-    const StyleVectorCombination& rCombination,                 // own vector and offstets for lines
-    const basegfx::B2DVector& rPerpendX,                        // normalized perpendicular to own vector
-    const std::vector< StyleVectorCombination >& rStyleVector)  // other vectors emerging in this point
-{
-    if(!rCombination.empty() && !rStyleVector.empty() && rCombination.size() == rExtendSet.size())
-    {
-        const size_t nOffsetA(rCombination.size());
-
-        if(1 == nOffsetA)
-        {
-            Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
-            rCombination.getColorAndOffsetAndHalfWidth(0, aMyColor, fMyOffset, fMyHalfWidth);
-
-            if(0xff != aMyColor.GetTransparency())
-            {
-                const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
-                const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
-                std::vector< CutSet > aCutSets;
-
-                for(const auto& rStyleCandidate : rStyleVector)
-                {
-                    const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
-                    const size_t nOffsetB(rStyleCandidate.size());
-
-                    for(size_t other(0); other < nOffsetB; other++)
-                    {
-                        Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
-                        rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
-
-                        if(0xff != aOtherColor.GetTransparency())
-                        {
-                            const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
-                            const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
-
-                            CutSet aNewCutSet;
-                            getCutSet(aNewCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
-                            aCutSets.push_back(aNewCutSet);
-                        }
-                    }
-                }
-
-                if(!aCutSets.empty())
-                {
-                    CutSet aCutSet(aCutSets[0]);
-                    const size_t nNumCutSets(aCutSets.size());
-
-                    if(1 != nNumCutSets)
-                    {
-                        double fCutSet(aCutSet.getSum());
-
-                        for(size_t a(1); a < nNumCutSets; a++)
-                        {
-                            const CutSet& rCandidate(aCutSets[a]);
-                            const double fCandidate(rCandidate.getSum());
-
-                            if(basegfx::fTools::equalZero(fCandidate - fCutSet))
-                            {
-                                // both have equal center point, use medium cut
-                                const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aCutSet.mfOLML, aCutSet.mfORML)));
-                                const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aCutSet.mfOLML, aCutSet.mfORML)));
-                                const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aCutSet.mfOLMR, aCutSet.mfORMR)));
-                                const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aCutSet.mfOLMR, aCutSet.mfORMR)));
-                                aCutSet.mfOLML = fNewOLML;
-                                aCutSet.mfORML = fNewORML;
-                                aCutSet.mfOLMR = fNewOLMR;
-                                aCutSet.mfORMR = fNewORMR;
-                                fCutSet = aCutSet.getSum();
-                            }
-                            else if(fCandidate < fCutSet)
-                            {
-                                // get minimum
-                                fCutSet = fCandidate;
-                                aCutSet = rCandidate;
-                            }
-                        }
-                    }
-
-                    ExtendSet& rExt(rExtendSet[0]);
-
-                    rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
-                    rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
-                }
-            }
-        }
-        else
-        {
-            size_t nVisEdgeUp(0);
-            size_t nVisEdgeDn(0);
-
-            for(size_t my(0); my < nOffsetA; my++)
-            {
-                Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
-                rCombination.getColorAndOffsetAndHalfWidth(my, aMyColor, fMyOffset, fMyHalfWidth);
-
-                if(0xff != aMyColor.GetTransparency())
-                {
-                    const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
-                    const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
-                    const bool bUpper(my <= (nOffsetA >> 1));
-                    const StyleVectorCombination& rStyleCandidate(bUpper ? rStyleVector.front() : rStyleVector.back());
-                    const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
-                    const size_t nOffsetB(rStyleCandidate.size());
-                    std::vector< CutSet > aCutSets;
-
-                    for(size_t other(0); other < nOffsetB; other++)
-                    {
-                        Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
-                        rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
-
-                        if(0xff != aOtherColor.GetTransparency())
-                        {
-                            const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
-                            const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
-                            CutSet aCutSet;
-                            getCutSet(aCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
-                            aCutSets.push_back(aCutSet);
-                        }
-                    }
-
-                    if(!aCutSets.empty())
-                    {
-                        // sort: min to start, max to end
-                        std::sort(aCutSets.begin(), aCutSets.end());
-                        const bool bOtherUpper(rStyleCandidate.getAngle() > F_PI);
-
-                        // check if we need min or max
-                        //  bUpper      bOtherUpper        MinMax
-                        //    t             t               max
-                        //    t             f               min
-                        //    f             f               max
-                        //    f             t               min
-                        const bool bMax(bUpper == bOtherUpper);
-                        size_t nBaseIndex(0);
-                        const size_t nNumCutSets(aCutSets.size());
-
-                        if(bMax)
-                        {
-                            // access at end
-                            nBaseIndex = nNumCutSets - 1 - (bUpper ? nVisEdgeUp : nVisEdgeDn);
-                        }
-                        else
-                        {
-                            // access at start
-                            nBaseIndex = bUpper ? nVisEdgeUp : nVisEdgeDn;
-                        }
-
-                        const size_t nSecuredIndex(std::min(nNumCutSets - 1, std::max(nBaseIndex, static_cast< size_t >(0))));
-                        const CutSet& rCutSet(aCutSets[nSecuredIndex]);
-                        ExtendSet& rExt(rExtendSet[my]);
-
-                        rExt.mfExtLeft = std::min(rCutSet.mfOLML, rCutSet.mfORML);
-                        rExt.mfExtRight = std::min(rCutSet.mfOLMR, rCutSet.mfORMR);
-                    }
-
-                    if(bUpper)
-                    {
-                        nVisEdgeUp++;
-                    }
-                    else
-                    {
-                        nVisEdgeDn++;
-                    }
-                }
-            }
-        }
-    }
-}
-
-StyleVectorCombination::StyleVectorCombination(
-    const Style& rStyle,
-    const basegfx::B2DVector& rB2DVector,
-    double fAngle,
-    bool bMirrored,
-    const Color* pForceColor)
-:   mfRefModeOffset(0.0),
-    maB2DVector(rB2DVector),
-    mfAngle(fAngle),
-    maOffsets()
-{
-    if (rStyle.IsUsed())
-    {
-        RefMode aRefMode(rStyle.GetRefMode());
-        Color aPrim(rStyle.GetColorPrim());
-        Color aSecn(rStyle.GetColorSecn());
-        double fPrim(rStyle.Prim());
-        double fSecn(rStyle.Secn());
-        const bool bSecnUsed(0.0 != fSecn);
-
-        if(bMirrored)
-        {
-            switch(aRefMode)
-            {
-                case RefMode::REFMODE_BEGIN: aRefMode = RefMode::REFMODE_END; break;
-                case RefMode::REFMODE_END: aRefMode = RefMode::REFMODE_BEGIN; break;
-                default: break;
-            }
-
-            if(bSecnUsed)
-            {
-                std::swap(aPrim, aSecn);
-                std::swap(fPrim, fSecn);
-            }
-        }
-
-        if (RefMode::REFMODE_CENTERED != aRefMode)
-        {
-            const double fHalfWidth(rStyle.GetWidth() * 0.5);
-
-            if (RefMode::REFMODE_BEGIN == aRefMode)
-            {
-                // move aligned below vector
-                mfRefModeOffset = fHalfWidth;
-            }
-            else if (RefMode::REFMODE_END == aRefMode)
-            {
-                // move aligned above vector
-                mfRefModeOffset = -fHalfWidth;
-            }
-        }
-
-        if (bSecnUsed)
-        {
-            // both or all three lines used
-            const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
-            const bool bDistTransparent(!rStyle.UseGapColor() || 0xff == rStyle.GetColorGap().GetTransparency());
-            const bool bSecnTransparent(0xff == aSecn.GetTransparency());
-
-            if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
-            {
-                const double a(mfRefModeOffset - (rStyle.GetWidth() * 0.5));
-                const double b(a + fPrim);
-                const double c(b + rStyle.Dist());
-                const double d(c + fSecn);
-
-                maOffsets.push_back(
-                    OffsetAndHalfWidthAndColor(
-                        (a + b) * 0.5,
-                        fPrim * 0.5,
-                        nullptr != pForceColor ? *pForceColor : aPrim));
-
-                maOffsets.push_back(
-                    OffsetAndHalfWidthAndColor(
-                        (b + c) * 0.5,
-                        rStyle.Dist() * 0.5,
-                        rStyle.UseGapColor()
-                            ? (nullptr != pForceColor ? *pForceColor : rStyle.GetColorGap())
-                            : Color(COL_TRANSPARENT)));
-
-                maOffsets.push_back(
-                    OffsetAndHalfWidthAndColor(
-                        (c + d) * 0.5,
-                        fSecn * 0.5,
-                        nullptr != pForceColor ? *pForceColor : aSecn));
-            }
-        }
-        else
-        {
-            // one line used, push two values, from outer to inner
-            if(0xff != rStyle.GetColorPrim().GetTransparency())
-            {
-                maOffsets.push_back(
-                    OffsetAndHalfWidthAndColor(
-                        mfRefModeOffset,
-                        fPrim * 0.5,
-                        nullptr != pForceColor ? *pForceColor : aPrim));
-            }
-        }
-    }
-}
-
-void StyleVectorCombination::getColorAndOffsetAndHalfWidth(size_t nIndex, Color& rColor, double& rfOffset, double& rfHalfWidth) const
-{
-    if(nIndex >= maOffsets.size())
-        return;
-    const OffsetAndHalfWidthAndColor& rCandidate(maOffsets[nIndex]);
-    rfOffset = rCandidate.mfOffset;
-    rfHalfWidth = rCandidate.mfHalfWidth;
-    rColor = rCandidate.maColor;
-}
-
-void StyleVectorTable::add(
-    const Style& rStyle,
-    const basegfx::B2DVector& rMyVector,
-    const basegfx::B2DVector& rOtherVector,
-    bool bMirrored)
-{
-    if(rStyle.IsUsed() && !basegfx::areParallel(rMyVector, rOtherVector))
-    {
-        // create angle between both. angle() needs vectors pointing away from the same point,
-        // so take the mirrored one. Add F_PI to get from -pi..+pi to [0..F_PI2] for sorting
-        const double fAngle(basegfx::B2DVector(-rMyVector.getX(), -rMyVector.getY()).angle(rOtherVector) + F_PI);
-        maEntries.emplace_back(rStyle, rOtherVector, fAngle, bMirrored);
-    }
-}
-
-void StyleVectorTable::sort()
-{
-    // sort inverse fom highest to lowest
-    std::sort(maEntries.begin(), maEntries.end(), [](const StyleVectorCombination& a, const StyleVectorCombination& b) { return a.getAngle() > b.getAngle(); });
-}
-
-void CreateBorderPrimitives(
-    drawinglayer::primitive2d::Primitive2DContainer& rTarget,
-    const basegfx::B2DPoint& rOrigin,
-    const basegfx::B2DVector& rX,
-    const Style& rBorder,
-    const StyleVectorTable& rStartStyleVectorTable,
-    const StyleVectorTable& rEndStyleVectorTable,
-    const Color* pForceColor)
-{
-    // get offset color pairs for  style, one per visible line
-    const StyleVectorCombination aCombination(rBorder, rX, 0.0, false, pForceColor);
-
-    if(!aCombination.empty())
-    {
-        const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
-        const bool bHasStartStyles(!rStartStyleVectorTable.empty());
-        const bool bHasEndStyles(!rEndStyleVectorTable.empty());
-        const size_t nOffsets(aCombination.size());
-        std::vector<ExtendSet> aExtendSetStart(nOffsets);
-        std::vector<ExtendSet> aExtendSetEnd(nOffsets);
-
-        if(bHasStartStyles)
-        {
-            // create extends for line starts, use given point/vector and offsets
-            getExtends(aExtendSetStart, rOrigin, aCombination, aPerpendX, rStartStyleVectorTable.getEntries());
-        }
-
-        if(bHasEndStyles)
-        {
-            // Create extends for line ends, create inverse point/vector and inverse offsets.
-            const StyleVectorCombination aMirroredCombination(rBorder, -rX, 0.0, true, pForceColor);
-
-            getExtends(aExtendSetEnd, rOrigin + rX, aMirroredCombination, -aPerpendX, rEndStyleVectorTable.getEntries());
-
-            // also need to inverse the result to apply to the correct lines
-            std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
-        }
-
-        std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
-        const double fNegLength(-rX.getLength());
-
-        for(size_t a(0); a < nOffsets; a++)
-        {
-            Color aMyColor;
-            double fMyOffset(0.0);
-            double fMyHalfWidth(0.0);
-            aCombination.getColorAndOffsetAndHalfWidth(a, aMyColor, fMyOffset, fMyHalfWidth);
-            const ExtendSet& rExtStart(aExtendSetStart[a]);
-            const ExtendSet& rExtEnd(aExtendSetEnd[a]);
-
-            if(0xff == aMyColor.GetTransparency())
-            {
-                aBorderlines.push_back(
-                    drawinglayer::primitive2d::BorderLine(
-                        fMyHalfWidth * 2.0));
-            }
-            else
-            {
-                aBorderlines.push_back(
-                    drawinglayer::primitive2d::BorderLine(
-                        drawinglayer::attribute::LineAttribute(
-                            aMyColor.getBColor(),
-                            fMyHalfWidth * 2.0),
-                        fNegLength * rExtStart.mfExtLeft,
-                        fNegLength * rExtStart.mfExtRight,
-                        fNegLength * rExtEnd.mfExtRight,
-                        fNegLength * rExtEnd.mfExtLeft));
-            }
-        }
-
-        static double fPatScFact(10.0); // 10.0 multiply, see old code
-        const std::vector<double> aDashing(svtools::GetLineDashing(rBorder.Type(), rBorder.PatternScale() * fPatScFact));
-        const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
-        const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * aCombination.getRefModeOffset()));
-
-        rTarget.push_back(
-            drawinglayer::primitive2d::Primitive2DReference(
-                new drawinglayer::primitive2d::BorderLinePrimitive2D(
-                    aStart,
-                    aStart + rX,
-                    aBorderlines,
-                    aStrokeAttribute)));
-    }
-}
-
 }
 }
 
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index a2aca66a37fd..147017da01f3 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -25,6 +25,7 @@
 #include <algorithm>
 #include <vcl/outdev.hxx>
 #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 
 namespace svx {
@@ -929,26 +930,38 @@ void Array::MirrorSelfX()
 }
 
 // drawing
-void HelperCreateHorizontalEntry(
-    const Array& rArray, const Style& rStyle, size_t col, size_t row,
-    const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const basegfx::B2DVector& rY,
-    drawinglayer::primitive2d::Primitive2DContainer& rSequence,
-    bool bUpper, const Color* pForceColor)
-{
+static void HelperCreateHorizontalEntry(
+    const Array& rArray,
+    const Style& rStyle,
+    size_t col,
+    size_t row,
+    const basegfx::B2DPoint& rOrigin,
+    const basegfx::B2DVector& rX,
+    const basegfx::B2DVector& rY,
+    drawinglayer::primitive2d::SdrFrameBorderDataVector& rData,
+    bool bUpper,
+    const Color* pForceColor)
+{
+    // prepare SdrFrameBorderData
+    rData.emplace_back(
+        bUpper ? rOrigin : basegfx::B2DPoint(rOrigin + rY),
+        rX,
+        rStyle,
+        pForceColor);
+    drawinglayer::primitive2d::SdrFrameBorderData& rInstance(rData.back());
+
     // get involved styles at start
     const Style& rStartFromTR(rArray.GetCellStyleBL( col, row - 1 ));
     const Style& rStartLFromT(rArray.GetCellStyleLeft( col, row - 1 ));
     const Style& rStartLFromL(rArray.GetCellStyleTop( col - 1, row ));
     const Style& rStartLFromB(rArray.GetCellStyleLeft( col, row ));
     const Style& rStartFromBR(rArray.GetCellStyleTL( col, row ));
-    StyleVectorTable aStart;
 
-    aStart.add(rStartFromTR, rX, rX - rY, false);
-    aStart.add(rStartLFromT, rX, -rY, true);
-    aStart.add(rStartLFromL, rX, -rX, true);
-    aStart.add(rStartLFromB, rX, rY, false);
-    aStart.add(rStartFromBR, rX, rX + rY, false);
-    aStart.sort();
+    rInstance.addSdrConnectStyleData(true, rStartFromTR, rX - rY, false);
+    rInstance.addSdrConnectStyleData(true, rStartLFromT, -rY, true);
+    rInstance.addSdrConnectStyleData(true, rStartLFromL, -rX, true);
+    rInstance.addSdrConnectStyleData(true, rStartLFromB, rY, false);
+    rInstance.addSdrConnectStyleData(true, rStartFromBR, rX + rY, false);
 
     // get involved styles at end
     const Style& rEndFromTL(rArray.GetCellStyleBR( col, row - 1 ));
@@ -956,47 +969,46 @@ void HelperCreateHorizontalEntry(
     const Style& rEndRFromR(rArray.GetCellStyleTop( col + 1, row ));
     const Style& rEndRFromB(rArray.GetCellStyleRight( col, row ));
     const Style& rEndFromBL(rArray.GetCellStyleTR( col, row ));
-    StyleVectorTable aEnd;
-    const basegfx::B2DVector aAxis(-rX);
-
-    aEnd.add(rEndFromTL, aAxis, aAxis - rY, true);
-    aEnd.add(rEndRFromT, aAxis, -rY, true);
-    aEnd.add(rEndRFromR, aAxis, rX, false);
-    aEnd.add(rEndRFromB, aAxis, rY, false);
-    aEnd.add(rEndFromBL, aAxis, rY - rX, true);
-    aEnd.sort();
-
-    CreateBorderPrimitives(
-        rSequence,
-        bUpper ? rOrigin : basegfx::B2DPoint(rOrigin + rY),
-        rX,
+
+    rInstance.addSdrConnectStyleData(false, rEndFromTL, -rX - rY, true);
+    rInstance.addSdrConnectStyleData(false, rEndRFromT, -rY, true);
+    rInstance.addSdrConnectStyleData(false, rEndRFromR, rX, false);
+    rInstance.addSdrConnectStyleData(false, rEndRFromB, rY, false);
+    rInstance.addSdrConnectStyleData(false, rEndFromBL, rY - rX, true);
+}
+
+static void HelperCreateVerticalEntry(
+    const Array& rArray,
+    const Style& rStyle,
+    size_t col,
+    size_t row,
+    const basegfx::B2DPoint& rOrigin,
+    const basegfx::B2DVector& rX,
+    const basegfx::B2DVector& rY,
+    drawinglayer::primitive2d::SdrFrameBorderDataVector& rData,
+    bool bLeft,
+    const Color* pForceColor)
+{
+    // prepare SdrFrameBorderData
+    rData.emplace_back(
+        bLeft ? rOrigin : basegfx::B2DPoint(rOrigin + rX),
+        rY,
         rStyle,
-        aStart,
-        aEnd,
-        pForceColor
-    );
-}
+        pForceColor);
+    drawinglayer::primitive2d::SdrFrameBorderData& rInstance(rData.back());
 
-void HelperCreateVerticalEntry(
-    const Array& rArray, const Style& rStyle, size_t col, size_t row,
-    const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const basegfx::B2DVector& rY,
-    drawinglayer::primitive2d::Primitive2DContainer& rSequence,
-    bool bLeft, const Color* pForceColor)
-{
     // get involved styles at start
     const Style& rStartFromBL(rArray.GetCellStyleTR( col - 1, row ));
     const Style& rStartTFromL(rArray.GetCellStyleTop( col - 1, row ));
     const Style& rStartTFromT(rArray.GetCellStyleLeft( col, row - 1 ));
     const Style& rStartTFromR(rArray.GetCellStyleTop( col, row ));
     const Style& rStartFromBR(rArray.GetCellStyleTL( col, row ));
-    StyleVectorTable aStart;
 
-    aStart.add(rStartFromBR, rY, rX + rY, false);
-    aStart.add(rStartTFromR, rY, rX, false);
-    aStart.add(rStartTFromT, rY, -rY, true);
-    aStart.add(rStartTFromL, rY, -rX, true);
-    aStart.add(rStartFromBL, rY, rY - rX, true);
-    aStart.sort();
+    rInstance.addSdrConnectStyleData(true, rStartFromBR, rX + rY, false);
+    rInstance.addSdrConnectStyleData(true, rStartTFromR, rX, false);
+    rInstance.addSdrConnectStyleData(true, rStartTFromT, -rY, true);
+    rInstance.addSdrConnectStyleData(true, rStartTFromL, -rX, true);
+    rInstance.addSdrConnectStyleData(true, rStartFromBL, rY - rX, true);
 
     // get involved styles at end
     const Style& rEndFromTL(rArray.GetCellStyleBR( col - 1, row ));
@@ -1004,67 +1016,12 @@ void HelperCreateVerticalEntry(
     const Style& rEndBFromB(rArray.GetCellStyleLeft( col, row + 1 ));
     const Style& rEndBFromR(rArray.GetCellStyleBottom( col, row ));
     const Style& rEndFromTR(rArray.GetCellStyleBL( col, row ));
-    StyleVectorTable aEnd;
-    const basegfx::B2DVector aAxis(-rY);
-
-    aEnd.add(rEndFromTR, aAxis, rX - rY, false);
-    aEnd.add(rEndBFromR, aAxis, rX, false);
-    aEnd.add(rEndBFromB, aAxis, rY, false);
-    aEnd.add(rEndBFromL, aAxis, -rX, true);
-    aEnd.add(rEndFromTL, aAxis, aAxis - rX, true);
-    aEnd.sort();
-
-    CreateBorderPrimitives(
-        rSequence,
-        bLeft ? rOrigin : basegfx::B2DPoint(rOrigin + rX),
-        rY,
-        rStyle,
-        aStart,
-        aEnd,
-        pForceColor
-    );
-}
 
-void HelperMergeInB2DPrimitiveArray(
-    const drawinglayer::primitive2d::Primitive2DContainer& rSource,
-    drawinglayer::primitive2d::Primitive2DContainer& rTarget)
-{
-    if(rSource.size() > 1)
-    {
-        drawinglayer::primitive2d::Primitive2DReference aCandidate;
-
-        for(const auto& a : rSource)
-        {
-            if(aCandidate.is())
-            {
-                const drawinglayer::primitive2d::Primitive2DReference aMerge(
-                    drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(aCandidate, a));
-
-                if(aMerge.is())
-                {
-                    aCandidate = aMerge;
-                }
-                else
-                {
-                    rTarget.push_back(aCandidate);
-                    aCandidate = a;
-                }
-            }
-            else
-            {
-                aCandidate = a;
-            }
-        }
-
-        if(aCandidate.is())
-        {
-            rTarget.push_back(aCandidate);
-        }
-    }
-    else
-    {
-        rTarget.append(rSource);
-    }
+    rInstance.addSdrConnectStyleData(false, rEndFromTR, rX - rY, false);
+    rInstance.addSdrConnectStyleData(false, rEndBFromR, rX, false);
+    rInstance.addSdrConnectStyleData(false, rEndBFromB, rY, false);
+    rInstance.addSdrConnectStyleData(false, rEndBFromL, -rX, true);
+    rInstance.addSdrConnectStyleData(false, rEndFromTL, -rY - rX, true);
 }
 
 drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
@@ -1095,10 +1052,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     const size_t nStartCol(nFirstCol > 0 ? nFirstCol - 1 : nFirstCol);
     const size_t nEndCol(nLastCol < GetColCount() - 1 ? nLastCol + 1 : nLastCol);
 
-    // various primitive sequences to collect the different border types
-    drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
-    std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nEndCol - nStartCol + 1);
-    drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
+    // prepare SdrFrameBorderDataVector
+    std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData(
+        std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>());
 
     // remember for which merged cells crossed lines were already created. To
     // do so, hold the size_t cell index in a set for fast check
@@ -1148,7 +1104,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rTop.IsUsed())
                     {
-                        HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, aHorizontalSequence, true, pForceColor);
+                        HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, *aData.get(), true, pForceColor);
                     }
                 }
 
@@ -1160,7 +1116,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rBottom.IsUsed())
                     {
-                        HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, aHorizontalSequence, false, pForceColor);
+                        HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, *aData.get(), false, pForceColor);
                     }
                 }
 
@@ -1173,7 +1129,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rLeft.IsUsed())
                     {
-                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], true, pForceColor);
+                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, *aData.get(), true, pForceColor);
                     }
                 }
 
@@ -1185,7 +1141,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rRight.IsUsed())
                     {
-                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], false, pForceColor);
+                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, *aData.get(), false, pForceColor);
                     }
                 }
 
@@ -1226,69 +1182,51 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                         if(rTLBR.IsUsed())
                         {
                             /// top-left and bottom-right Style Tables
+                            aData->emplace_back(
+                                aOrigin,
+                                aX + aY,
+                                rTLBR,
+                                pForceColor);
+                            drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
                             /// Fill top-left Style Table
                             const Style& rTLFromRight(GetCellStyleTop(nCol, nRow));
                             const Style& rTLFromBottom(GetCellStyleLeft(nCol, nRow));
-                            StyleVectorTable aStart;
-                            const basegfx::B2DVector aAxisA(aX + aY);
 
-                            aStart.add(rTLFromRight, aAxisA, aX, false);
-                            aStart.add(rTLFromBottom, aAxisA, aY, false);
-                            aStart.sort();
+                            rInstance.addSdrConnectStyleData(true, rTLFromRight, aX, false);
+                            rInstance.addSdrConnectStyleData(true, rTLFromBottom, aY, false);
 
                             /// Fill bottom-right Style Table
                             const Style& rBRFromBottom(GetCellStyleRight(nCol, nRow));
                             const Style& rBRFromLeft(GetCellStyleBottom(nCol, nRow));
-                            StyleVectorTable aEnd;
-                            const basegfx::B2DVector aAxisB(-aX -aY);
-
-                            aEnd.add(rBRFromBottom, aAxisB, -aY, true);
-                            aEnd.add(rBRFromLeft, aAxisB, -aX, true);
-                            aEnd.sort();
 
-                            CreateBorderPrimitives(
-                                aCrossSequence,
-                                aOrigin,
-                                aX + aY,
-                                rTLBR,
-                                aStart,
-                                aEnd,
-                                pForceColor
-                            );
+                            rInstance.addSdrConnectStyleData(false, rBRFromBottom, -aY, true);
+                            rInstance.addSdrConnectStyleData(false, rBRFromLeft, -aX, true);
                         }
 
                         if(rBLTR.IsUsed())
                         {
                             /// bottom-left and top-right Style Tables
+                            aData->emplace_back(
+                                aOrigin + aY,
+                                aX - aY,
+                                rBLTR,
+                                pForceColor);
+                            drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
                             /// Fill bottom-left Style Table
                             const Style& rBLFromTop(GetCellStyleLeft(nCol, nRow));
                             const Style& rBLFromBottom(GetCellStyleBottom(nCol, nRow));
-                            StyleVectorTable aStart;
-                            const basegfx::B2DVector aAxisA(aX - aY);
 
-                            aStart.add(rBLFromTop, aAxisA, -aY, true);
-                            aStart.add(rBLFromBottom, aAxisA, aX, false);
-                            aStart.sort();
+                            rInstance.addSdrConnectStyleData(true, rBLFromTop, -aY, true);
+                            rInstance.addSdrConnectStyleData(true, rBLFromBottom, aX, false);
 
                             /// Fill top-right Style Table
                             const Style& rTRFromLeft(GetCellStyleTop(nCol, nRow));
                             const Style& rTRFromBottom(GetCellStyleRight(nCol, nRow));
-                            StyleVectorTable aEnd;
-                            const basegfx::B2DVector aAxisB(aY - aX);
-
-                            aEnd.add(rTRFromLeft, aAxisB, -aX, true);
-                            aEnd.add(rTRFromBottom, aAxisB, aY, false);
-                            aEnd.sort();
 
-                            CreateBorderPrimitives(
-                                aCrossSequence,
-                                aOrigin + aY,
-                                aX - aY,
-                                rBLTR,
-                                aStart,
-                                aEnd,
-                                pForceColor
-                            );
+                            rInstance.addSdrConnectStyleData(false, rTRFromLeft, -aX, true);
+                            rInstance.addSdrConnectStyleData(false, rTRFromBottom, aY, false);
                         }
                     }
                 }
@@ -1296,16 +1234,20 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
         }
     }
 
-    // to stay compatible, create order as it was formally. Also try to
-    // merge primitives as far as possible
-    HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aCrossSequence);
+    // create instance of SdrFrameBorderPrimitive2D if
+    // SdrFrameBorderDataVector is used
+    drawinglayer::primitive2d::Primitive2DContainer aSequence;
 
-    for(const auto& aVert : aVerticalSequences)
+    if(!aData->empty())
     {
-        HelperMergeInB2DPrimitiveArray(aVert, aCrossSequence);
+        aSequence.push_back(
+            drawinglayer::primitive2d::Primitive2DReference(
+                new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D(
+                    aData,
+                    true)));
     }
 
-    return aCrossSequence;
+    return aSequence;
 }
 
 drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveArray() const
diff --git a/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx b/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
new file mode 100755
index 000000000000..641968762d32
--- /dev/null
+++ b/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
@@ -0,0 +1,768 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
+#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <svtools/borderhelper.hxx>
+
+namespace
+{
+    class StyleVectorCombination
+    {
+    private:
+        struct OffsetAndHalfWidthAndColor
+        {
+            double          mfOffset;
+            double          mfHalfWidth;
+            Color           maColor;
+
+            OffsetAndHalfWidthAndColor(double offset, double halfWidth, Color color) :
+                mfOffset(offset),
+                mfHalfWidth(halfWidth),
+                maColor(color)
+            {}
+        };
+
+        double                                      mfRefModeOffset;
+        basegfx::B2DVector                          maB2DVector;
+        double                                      mfAngle;
+        std::vector< OffsetAndHalfWidthAndColor >   maOffsets;
+
+    public:
+        StyleVectorCombination(
+            const svx::frame::Style& rStyle,
+            const basegfx::B2DVector& rB2DVector,
+            double fAngle,
+            bool bMirrored,
+            const Color* pForceColor)
+        :   mfRefModeOffset(0.0),
+            maB2DVector(rB2DVector),
+            mfAngle(fAngle),
+            maOffsets()
+        {
+            if (rStyle.IsUsed())
+            {
+                svx::frame::RefMode aRefMode(rStyle.GetRefMode());
+                Color aPrim(rStyle.GetColorPrim());
+                Color aSecn(rStyle.GetColorSecn());
+                double fPrim(rStyle.Prim());
+                double fSecn(rStyle.Secn());
+                const bool bSecnUsed(0.0 != fSecn);
+
+                if(bMirrored)
+                {
+                    switch(aRefMode)
+                    {
+                        case svx::frame::RefMode::REFMODE_BEGIN: aRefMode = svx::frame::RefMode::REFMODE_END; break;
+                        case svx::frame::RefMode::REFMODE_END: aRefMode = svx::frame::RefMode::REFMODE_BEGIN; break;
+                        default: break;
+                    }
+
+                    if(bSecnUsed)
+                    {
+                        std::swap(aPrim, aSecn);
+                        std::swap(fPrim, fSecn);
+                    }
+                }
+
+                if (svx::frame::RefMode::REFMODE_CENTERED != aRefMode)
+                {
+                    const double fHalfWidth(rStyle.GetWidth() * 0.5);
+
+                    if (svx::frame::RefMode::REFMODE_BEGIN == aRefMode)
+                    {
+                        // move aligned below vector
+                        mfRefModeOffset = fHalfWidth;
+                    }
+                    else if (svx::frame::RefMode::REFMODE_END == aRefMode)
+                    {
+                        // move aligned above vector
+                        mfRefModeOffset = -fHalfWidth;
+                    }
+                }
+
+                if (bSecnUsed)
+                {
+                    // both or all three lines used
+                    const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
+                    const bool bDistTransparent(!rStyle.UseGapColor() || 0xff == rStyle.GetColorGap().GetTransparency());
+                    const bool bSecnTransparent(0xff == aSecn.GetTransparency());
+
+                    if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
+                    {
+                        const double a(mfRefModeOffset - (rStyle.GetWidth() * 0.5));
+                        const double b(a + fPrim);
+                        const double c(b + rStyle.Dist());
+                        const double d(c + fSecn);
+
+                        maOffsets.push_back(
+                            OffsetAndHalfWidthAndColor(
+                                (a + b) * 0.5,
+                                fPrim * 0.5,
+                                nullptr != pForceColor ? *pForceColor : aPrim));
+
+                        maOffsets.push_back(
+                            OffsetAndHalfWidthAndColor(
+                                (b + c) * 0.5,
+                                rStyle.Dist() * 0.5,
+                                rStyle.UseGapColor()
+                                    ? (nullptr != pForceColor ? *pForceColor : rStyle.GetColorGap())
+                                    : COL_TRANSPARENT));
+
+                        maOffsets.push_back(
+                            OffsetAndHalfWidthAndColor(
+                                (c + d) * 0.5,
+                                fSecn * 0.5,
+                                nullptr != pForceColor ? *pForceColor : aSecn));
+                    }
+                }
+                else
+                {
+                    // one line used, push two values, from outer to inner
+                    if(0xff != rStyle.GetColorPrim().GetTransparency())
+                    {
+                        maOffsets.push_back(
+                            OffsetAndHalfWidthAndColor(
+                                mfRefModeOffset,
+                                fPrim * 0.5,
+                                nullptr != pForceColor ? *pForceColor : aPrim));
+                    }
+                }
+            }
+        }
+
+        double getRefModeOffset() const { return mfRefModeOffset; }
+        const basegfx::B2DVector& getB2DVector() const { return maB2DVector; }
+        double getAngle() const { return mfAngle; }
+        bool empty() const { return maOffsets.empty(); }
+        size_t size() const { return maOffsets.size(); }
+
+        void getColorAndOffsetAndHalfWidth(size_t nIndex, Color& rColor, double& rfOffset, double& rfHalfWidth) const
+        {
+            if(nIndex >= maOffsets.size())
+                return;
+            const OffsetAndHalfWidthAndColor& rCandidate(maOffsets[nIndex]);
+            rfOffset = rCandidate.mfOffset;
+            rfHalfWidth = rCandidate.mfHalfWidth;
+            rColor = rCandidate.maColor;
+        }
+    };
+
+    class StyleVectorTable
+    {
+    private:
+        std::vector< StyleVectorCombination >       maEntries;
+
+    public:
+        StyleVectorTable()
+        :   maEntries()
+        {
+        }
+
+        void add(
+            const svx::frame::Style& rStyle,
+            const basegfx::B2DVector& rMyVector,
+            const basegfx::B2DVector& rOtherVector,
+            bool bMirrored)
+        {
+            if(rStyle.IsUsed() && !basegfx::areParallel(rMyVector, rOtherVector))
+            {
+                // create angle between both. angle() needs vectors pointing away from the same point,
+                // so take the mirrored one. Add F_PI to get from -pi..+pi to [0..F_PI2] for sorting
+                const double fAngle(basegfx::B2DVector(-rMyVector.getX(), -rMyVector.getY()).angle(rOtherVector) + F_PI);
+                maEntries.emplace_back(rStyle, rOtherVector, fAngle, bMirrored, nullptr);
+            }
+        }
+
+        void sort()
+        {
+            // sort inverse fom highest to lowest
+            std::sort(
+                maEntries.begin(),
+                maEntries.end(),
+                [](const StyleVectorCombination& a, const StyleVectorCombination& b)
+                    { return a.getAngle() > b.getAngle(); });
+        }
+
+        bool empty() const { return maEntries.empty(); }
+        const std::vector< StyleVectorCombination >& getEntries() const{ return maEntries; }
+    };
+
+    struct CutSet
+    {
+        double          mfOLML;
+        double          mfORML;
+        double          mfOLMR;
+        double          mfORMR;
+
+        CutSet() : mfOLML(0.0), mfORML(0.0), mfOLMR(0.0), mfORMR(0.0)
+        {
+        }
+
+        bool operator<( const CutSet& rOther) const
+        {
+            const double fA(mfOLML + mfORML + mfOLMR + mfORMR);
+            const double fB(rOther.mfOLML + rOther.mfORML + rOther.mfOLMR + rOther.mfORMR);
+
+            return fA < fB;
+        }
+
+        double getSum() const { return mfOLML + mfORML + mfOLMR + mfORMR; }
+    };
+
+    void getCutSet(
+        CutSet& rCutSet,
+        const basegfx::B2DPoint& rLeft,
+        const basegfx::B2DPoint& rRight,
+        const basegfx::B2DVector& rX,
+        const basegfx::B2DPoint& rOtherLeft,
+        const basegfx::B2DPoint& rOtherRight,
+        const basegfx::B2DVector& rOtherX)
+    {
+        basegfx::tools::findCut(
+            rLeft,
+            rX,
+            rOtherLeft,
+            rOtherX,
+            CutFlagValue::LINE,
+            &rCutSet.mfOLML);
+
+        basegfx::tools::findCut(
+            rRight,
+            rX,
+            rOtherLeft,
+            rOtherX,
+            CutFlagValue::LINE,
+            &rCutSet.mfOLMR);
+
+        basegfx::tools::findCut(
+            rLeft,
+            rX,
+            rOtherRight,
+            rOtherX,
+            CutFlagValue::LINE,
+            &rCutSet.mfORML);
+
+        basegfx::tools::findCut(
+            rRight,
+            rX,
+            rOtherRight,
+            rOtherX,
+            CutFlagValue::LINE,
+            &rCutSet.mfORMR);
+    }
+
+    struct ExtendSet
+    {
+        double          mfExtLeft;
+        double          mfExtRight;
+
+        ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
+    };
+
+    void getExtends(
+        std::vector<ExtendSet>& rExtendSet,                         // target Left/Right values to fill
+        const basegfx::B2DPoint& rOrigin,                           // own vector start
+        const StyleVectorCombination& rCombination,                 // own vector and offsets for lines
+        const basegfx::B2DVector& rPerpendX,                        // normalized perpendicular to own vector
+        const std::vector< StyleVectorCombination >& rStyleVector)  // other vectors emerging in this point
+    {
+        if(!rCombination.empty() && !rStyleVector.empty() && rCombination.size() == rExtendSet.size())
+        {
+            const size_t nOffsetA(rCombination.size());
+
+            if(1 == nOffsetA)
+            {
+                Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
+                rCombination.getColorAndOffsetAndHalfWidth(0, aMyColor, fMyOffset, fMyHalfWidth);
+
+                if(0xff != aMyColor.GetTransparency())
+                {
+                    const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
+                    const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
+                    std::vector< CutSet > aCutSets;
+
+                    for(const auto& rStyleCandidate : rStyleVector)
+                    {
+                        const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
+                        const size_t nOffsetB(rStyleCandidate.size());
+
+                        for(size_t other(0); other < nOffsetB; other++)
+                        {
+                            Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
+                            rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
+
+                            if(0xff != aOtherColor.GetTransparency())
+                            {
+                                const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
+                                const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
+
+                                CutSet aNewCutSet;
+                                getCutSet(aNewCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
+                                aCutSets.push_back(aNewCutSet);
+                            }
+                        }
+                    }
+
+                    if(!aCutSets.empty())
+                    {
+                        CutSet aCutSet(aCutSets[0]);
+                        const size_t nNumCutSets(aCutSets.size());
+
+                        if(1 != nNumCutSets)
+                        {
+                            double fCutSet(aCutSet.getSum());
+
+                            for(size_t a(1); a < nNumCutSets; a++)
+                            {
+                                const CutSet& rCandidate(aCutSets[a]);
+                                const double fCandidate(rCandidate.getSum());
+
+                                if(basegfx::fTools::equalZero(fCandidate - fCutSet))
+                                {
+                                    // both have equal center point, use medium cut
+                                    const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aCutSet.mfOLML, aCutSet.mfORML)));
+                                    const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aCutSet.mfOLML, aCutSet.mfORML)));
+                                    const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aCutSet.mfOLMR, aCutSet.mfORMR)));
+                                    const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aCutSet.mfOLMR, aCutSet.mfORMR)));
+                                    aCutSet.mfOLML = fNewOLML;
+                                    aCutSet.mfORML = fNewORML;
+                                    aCutSet.mfOLMR = fNewOLMR;
+                                    aCutSet.mfORMR = fNewORMR;
+                                    fCutSet = aCutSet.getSum();
+                                }
+                                else if(fCandidate < fCutSet)
+                                {
+                                    // get minimum
+                                    fCutSet = fCandidate;
+                                    aCutSet = rCandidate;
+                                }
+                            }
+                        }
+
+                        ExtendSet& rExt(rExtendSet[0]);
+
+                        rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
+                        rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
+                    }
+                }
+            }
+            else
+            {
+                size_t nVisEdgeUp(0);
+                size_t nVisEdgeDn(0);
+
+                for(size_t my(0); my < nOffsetA; my++)
+                {
+                    Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
+                    rCombination.getColorAndOffsetAndHalfWidth(my, aMyColor, fMyOffset, fMyHalfWidth);
+
+                    if(0xff != aMyColor.GetTransparency())
+                    {
+                        const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
+                        const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
+                        const bool bUpper(my <= (nOffsetA >> 1));
+                        const StyleVectorCombination& rStyleCandidate(bUpper ? rStyleVector.front() : rStyleVector.back());
+                        const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
+                        const size_t nOffsetB(rStyleCandidate.size());
+                        std::vector< CutSet > aCutSets;
+
+                        for(size_t other(0); other < nOffsetB; other++)
+                        {
+                            Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
+                            rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
+
+                            if(0xff != aOtherColor.GetTransparency())
+                            {
+                                const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
+                                const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
+                                CutSet aCutSet;
+                                getCutSet(aCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
+                                aCutSets.push_back(aCutSet);
+                            }
+                        }
+
+                        if(!aCutSets.empty())
+                        {
+                            // sort: min to start, max to end
+                            std::sort(aCutSets.begin(), aCutSets.end());
+                            const bool bOtherUpper(rStyleCandidate.getAngle() > F_PI);
+
+                            // check if we need min or max
+                            //  bUpper      bOtherUpper        MinMax
+                            //    t             t               max
+                            //    t             f               min
+                            //    f             f               max
+                            //    f             t               min
+                            const bool bMax(bUpper == bOtherUpper);
+                            size_t nBaseIndex(0);
+                            const size_t nNumCutSets(aCutSets.size());
+
+                            if(bMax)
+                            {
+                                // access at end
+                                nBaseIndex = nNumCutSets - 1 - (bUpper ? nVisEdgeUp : nVisEdgeDn);
+                            }
+                            else
+                            {
+                                // access at start
+                                nBaseIndex = bUpper ? nVisEdgeUp : nVisEdgeDn;
+                            }
+
+                            const size_t nSecuredIndex(std::min(nNumCutSets - 1, std::max(nBaseIndex, static_cast< size_t >(0))));
+                            const CutSet& rCutSet(aCutSets[nSecuredIndex]);
+                            ExtendSet& rExt(rExtendSet[my]);
+
+                            rExt.mfExtLeft = std::min(rCutSet.mfOLML, rCutSet.mfORML);
+                            rExt.mfExtRight = std::min(rCutSet.mfOLMR, rCutSet.mfORMR);
+                        }
+
+                        if(bUpper)
+                        {
+                            nVisEdgeUp++;
+                        }
+                        else
+                        {
+                            nVisEdgeDn++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *  Helper method to create the correct drawinglayer::primitive2d::BorderLinePrimitive2D
+     *  for the given data, especially the correct drawinglayer::primitive2d::BorderLine entries
+     *  including the correctly solved/created LineStartEnd extends
+     *
+     *  rTarget : Here the evtl. created BorderLinePrimitive2D will be appended
+     *  rOrigin : StartPoint of the Borderline
+     *  rX      : Vector of the Borderline
+     *  rBorder : svx::frame::Style of the of the Borderline
+     *  rStartStyleVectorTable : All other Borderlines which have to be taken into account because
+     *      they have the same StartPoint as the current Borderline. These will be used to calculate
+     *      the correct LineStartEnd extends tor the BorderLinePrimitive2D. The definition should be
+     *      built up using svx::frame::StyleVectorTable and StyleVectorTable::add and includes:
+     *          rStyle      : the svx::frame::Style of one other BorderLine
+     *          rMyVector   : the Vector of the *new* to-be-defined BorderLine, identical to rX
+     *          rOtherVector: the Vector of one other BorderLine (may be, but does not need to be normalized),
+     *                        always *pointing away* from the common StartPoint rOrigin
+     *          bMirrored   : define if rStyle of one other BorderLine shall be mirrored (e.g. bottom-right edges)
+     *      With multiple BorderLines the definitions have to be CounterClockWise. This will be
+     *      ensured by StyleVectorTable sorting the entries, but knowing this may allow more efficient
+     *      data creation.
+     *  rEndStyleVectorTable: All other BorderLines that have the same EndPoint. There are differences to
+     *      the Start definitions:
+     *          - do not forget to consequently use -rX for rMyVector
+     *          - definitions have to be ClockWise for the EndBorderLines, will be ensured by sorting
+     *
+     *  If you take all this into account, you will gett correctly extended BorderLinePrimitive2D
+     *  representations for the new to be defined BorderLine. That extensions will overlap nicely
+     *  with the corresponding BorderLines and take all multiple line definitions in the ::Style into
+     *  account.
+     *  The internal solver is *not limited* to ::Style(s) with three parts (Left/Gap/Right), this is
+     *  just due to svx::frame::Style's definitions. A new solver based on this one can be created
+     *  anytime using more mulötiple borders based on the more flexible
+     *  std::vector< drawinglayer::primitive2d::BorderLine > if needed.
+     */
+    void CreateBorderPrimitives(
+        drawinglayer::primitive2d::Primitive2DContainer& rTarget,   /// target for created primitives
+        const basegfx::B2DPoint& rOrigin,                           /// start point of borderline
+        const basegfx::B2DVector& rX,                               /// X-Axis of borderline with length
+        const svx::frame::Style& rBorder,                           /// Style of borderline
+        const StyleVectorTable& rStartStyleVectorTable,             /// Styles and vectors (pointing away) at borderline start, ccw
+        const StyleVectorTable& rEndStyleVectorTable,               /// Styles and vectors (pointing away) at borderline end, cw
+        const Color* pForceColor)                                   /// If specified, overrides frame border color.
+    {
+        // get offset color pairs for  style, one per visible line
+        const StyleVectorCombination aCombination(rBorder, rX, 0.0, false, pForceColor);
+
+        if(aCombination.empty())
+            return;
+
+        const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
+        const bool bHasStartStyles(!rStartStyleVectorTable.empty());
+        const bool bHasEndStyles(!rEndStyleVectorTable.empty());
+        const size_t nOffsets(aCombination.size());
+        std::vector<ExtendSet> aExtendSetStart(nOffsets);
+        std::vector<ExtendSet> aExtendSetEnd(nOffsets);
+
+        if(bHasStartStyles)
+        {
+            // create extends for line starts, use given point/vector and offsets
+            getExtends(aExtendSetStart, rOrigin, aCombination, aPerpendX, rStartStyleVectorTable.getEntries());
+        }
+
+        if(bHasEndStyles)
+        {
+            // Create extends for line ends, create inverse point/vector and inverse offsets.
+            const StyleVectorCombination aMirroredCombination(rBorder, -rX, 0.0, true, pForceColor);
+
+            getExtends(aExtendSetEnd, rOrigin + rX, aMirroredCombination, -aPerpendX, rEndStyleVectorTable.getEntries());
+
+            // also need to inverse the result to apply to the correct lines
+            std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
+        }
+
+        std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
+        const double fNegLength(-rX.getLength());
+
+        for(size_t a(0); a < nOffsets; a++)
+        {
+            Color aMyColor;
+            double fMyOffset(0.0);
+            double fMyHalfWidth(0.0);
+            aCombination.getColorAndOffsetAndHalfWidth(a, aMyColor, fMyOffset, fMyHalfWidth);
+            const ExtendSet& rExtStart(aExtendSetStart[a]);
+            const ExtendSet& rExtEnd(aExtendSetEnd[a]);
+
+            if(0xff == aMyColor.GetTransparency())
+            {
+                aBorderlines.push_back(
+                    drawinglayer::primitive2d::BorderLine(
+                        fMyHalfWidth * 2.0));
+            }
+            else
+            {
+                aBorderlines.push_back(
+                    drawinglayer::primitive2d::BorderLine(
+                        drawinglayer::attribute::LineAttribute(
+                            aMyColor.getBColor(),
+                            fMyHalfWidth * 2.0),
+                        fNegLength * rExtStart.mfExtLeft,
+                        fNegLength * rExtStart.mfExtRight,
+                        fNegLength * rExtEnd.mfExtRight,
+                        fNegLength * rExtEnd.mfExtLeft));
+            }
+        }
+
+        static double fPatScFact(10.0); // 10.0 multiply, see old code
+        const std::vector<double> aDashing(svtools::GetLineDashing(rBorder.Type(), rBorder.PatternScale() * fPatScFact));
+        const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
+        const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * aCombination.getRefModeOffset()));
+
+        rTarget.push_back(
+            drawinglayer::primitive2d::Primitive2DReference(
+                new drawinglayer::primitive2d::BorderLinePrimitive2D(
+                    aStart,
+                    aStart + rX,
+                    aBorderlines,
+                    aStrokeAttribute)));
+    }
+}
+
+namespace drawinglayer
+{
+    namespace primitive2d
+    {
+        SdrFrameBorderData::SdrConnectStyleData::SdrConnectStyleData(
+            const svx::frame::Style& rStyle,
+            const basegfx::B2DVector& rNormalizedPerpendicular,
+            bool bStyleMirrored)
+        :   maStyle(rStyle),
+            maNormalizedPerpendicular(rNormalizedPerpendicular),
+            mbStyleMirrored(bStyleMirrored)
+        {
+        }
+
+        SdrFrameBorderData::SdrFrameBorderData(
+            const basegfx::B2DPoint& rOrigin,
+            const basegfx::B2DVector& rX,
+            const svx::frame::Style& rStyle,
+            const Color* pForceColor)
+        :   maOrigin(rOrigin),
+            maX(rX),
+            maStyle(rStyle),
+            maColor(nullptr != pForceColor ? *pForceColor : Color()),
+            mbForceColor(nullptr != pForceColor),
+            maStart(),
+            maEnd()
+        {
+        }
+
+        void SdrFrameBorderData::addSdrConnectStyleData(
+            bool bStart,
+            const svx::frame::Style& rStyle,
+            const basegfx::B2DVector& rNormalizedPerpendicular,
+            bool bStyleMirrored)
+        {
+            if(rStyle.IsUsed())
+            {
+                if(bStart)
+                {
+                    maStart.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
+                }
+                else
+                {
+                    maEnd.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
+                }
+            }
+        }
+
+        void SdrFrameBorderData::create2DDecomposition(Primitive2DContainer& rContainer) const
+        {
+            StyleVectorTable aStartVector;
+            StyleVectorTable aEndVector;
+            const basegfx::B2DVector aAxis(-maX);
+
+            for(const auto& rStart : maStart)
+            {
+                aStartVector.add(
+                    rStart.getStyle(),
+                    maX,
+                    rStart.getNormalizedPerpendicular(),
+                    rStart.getStyleMirrored());
+            }
+
+            for(const auto& rEnd : maEnd)
+            {
+                aEndVector.add(
+                    rEnd.getStyle(),
+                    aAxis,
+                    rEnd.getNormalizedPerpendicular(),
+                    rEnd.getStyleMirrored());
+            }
+
+            aStartVector.sort();
+            aEndVector.sort();
+
+            CreateBorderPrimitives(
+                rContainer,
+                maOrigin,
+                maX,
+                maStyle,
+                aStartVector,
+                aEndVector,
+                mbForceColor ? &maColor : nullptr);
+        }
+    } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+    namespace primitive2d
+    {
+        Primitive2DContainer SdrFrameBorderPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const
+        {
+            Primitive2DContainer aRetval;
+
+            if(getMergeResult())
+            {
+                // decompose all buffered SdrFrameBorderData entries and try to merge them
+                // to reduce existing number of BorderLinePrimitive2D(s)
+                for(const auto& rCandidate : getFrameBorders())
+                {
+                    // get decomposition on one SdrFrameBorderData entry
+                    Primitive2DContainer aPartial;
+                    rCandidate.create2DDecomposition(aPartial);
+
+                    for(const auto& aCandidatePartial : aPartial)
+                    {
+                        if(aRetval.empty())
+                        {
+                            // no local data yet, just add as 1st entry, done
+                            aRetval.push_back(aCandidatePartial);
+                        }
+                        else
+                        {
+                            bool bDidMerge(false);
+
+                            for(auto& aCandidateRetval : aRetval)
+                            {
+                                // try to merge by appending new data to existing data
+                                const drawinglayer::primitive2d::Primitive2DReference aMergeRetvalPartial(
+                                    drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
+                                        aCandidateRetval,
+                                        aCandidatePartial));
+
+                                if(aMergeRetvalPartial.is())
+                                {
+                                    // could append, replace existing data with merged data, done
+                                    aCandidateRetval = aMergeRetvalPartial;
+                                    bDidMerge = true;
+                                    break;
+                                }
+
+                                // try to merge by appending existing data to new data
+                                const drawinglayer::primitive2d::Primitive2DReference aMergePartialRetval(
+                                    drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
+                                        aCandidatePartial,
+                                        aCandidateRetval));
+
+                                if(aMergePartialRetval.is())
+                                {
+                                    // could append, replace existing data with merged data, done
+                                    aCandidateRetval = aMergePartialRetval;
+                                    bDidMerge = true;
+                                    break;
+                                }
+                            }
+
+                            if(!bDidMerge)
+                            {
+                                // no merge aftzer checking all existing data, append as new segment
+                                aRetval.push_back(aCandidatePartial);
+                            }
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // just decompose all buffered SdrFrameBorderData entries, do not try to merge
+                for(const auto& rCandidate : getFrameBorders())
+                {
+                    rCandidate.create2DDecomposition(aRetval);
+                }
+            }
+
+            return aRetval;
+        }
+
+        SdrFrameBorderPrimitive2D::SdrFrameBorderPrimitive2D(
+            std::shared_ptr<SdrFrameBorderDataVector>& rFrameBorders,
+            bool bMergeResult)
+        :   BufferedDecompositionPrimitive2D(),
+            maFrameBorders(std::move(rFrameBorders)),
+            mbMergeResult(bMergeResult)
+        {
+        }
+
+        bool SdrFrameBorderPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+        {
+            if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+            {
+                const SdrFrameBorderPrimitive2D& rCompare = static_cast<const SdrFrameBorderPrimitive2D&>(rPrimitive);
+
+                return maFrameBorders == rCompare.maFrameBorders;
+            }
+
+            return false;
+        }
+
+        // provide unique ID
+        ImplPrimitive2DIDBlock(SdrFrameBorderPrimitive2D, PRIMITIVE2D_ID_SDRFRAMEBORDERTPRIMITIVE2D)
+
+    } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 77a675329219..c8fcefe1a162 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -64,6 +64,7 @@
 #include <colfrm.hxx>
 #include <sw_primitivetypes2d.hxx>
 
+#include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
 #include <svx/sdr/contact/viewobjectcontact.hxx>
 #include <svx/sdr/contact/viewcontact.hxx>
@@ -2380,8 +2381,10 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
     aUpper.Pos() += pUpper->Frame().Pos();
     SwRect aUpperAligned( aUpper );
     ::SwAlignRect( aUpperAligned, gProp.pSGlobalShell, &rDev );
-    drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
-    drawinglayer::primitive2d::Primitive2DContainer aVerticalSequence;
+
+    // prepare SdrFrameBorderDataVector
+    std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData(
+        std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>());
 
     while ( true )
     {
@@ -2519,30 +2522,20 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
                     if(!aX.equalZero())
                     {
                         const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX));
-                        svx::frame::StyleVectorTable aStartVector;
-
-                        aStartVector.add(aStyles[ 1 ], aX, -aY, true); // aLFromT
-                        aStartVector.add(aStyles[ 2 ], aX, -aX, true); // aLFromL
-                        aStartVector.add(aStyles[ 3 ], aX, aY, false); // aLFromB
-                        aStartVector.sort();
-
-                        svx::frame::StyleVectorTable aEndVector;
-                        const basegfx::B2DVector aAxis(-aX);
-
-                        aEndVector.add(aStyles[ 4 ], aAxis, -aY, true); // aRFromT
-                        aEndVector.add(aStyles[ 5 ], aAxis, aX, false); // aRFromR
-                        aEndVector.add(aStyles[ 6 ], aAxis, aY, false); // aRFromB
-                        aEndVector.sort();
-
-                        CreateBorderPrimitives(
-                            aHorizontalSequence,
+                        aData->emplace_back(
                             aOrigin,
                             aX,
-                            aStyles[ 0 ],
-                            aStartVector,
-                            aEndVector,
-                            pTmpColor
-                        );
+                            aStyles[0],
+                            pTmpColor);
+                        drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
+                        rInstance.addSdrConnectStyleData(true, aStyles[1], -aY, true); // aLFromT
+                        rInstance.addSdrConnectStyleData(true, aStyles[2], -aX, true); // aLFromL
+                        rInstance.addSdrConnectStyleData(true, aStyles[3], aY, false); // aLFromB
+
+                        rInstance.addSdrConnectStyleData(false, aStyles[4], -aY, true); // aRFromT
+                        rInstance.addSdrConnectStyleData(false, aStyles[5], aX, false); // aRFromR
+                        rInstance.addSdrConnectStyleData(false, aStyles[6], aY, false); // aRFromB
                     }
                 }
                 else // vertical
@@ -2553,30 +2546,20 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
                     if(!aX.equalZero())
                     {
                         const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX));
-                        svx::frame::StyleVectorTable aStartVector;
-
-                        aStartVector.add(aStyles[ 3 ], aX, -aY, false); // aTFromR
-                        aStartVector.add(aStyles[ 2 ], aX, -aX, true); // aTFromT
-                        aStartVector.add(aStyles[ 1 ], aX, aY, true); // aTFromL
-                        aStartVector.sort();
-
-                        svx::frame::StyleVectorTable aEndVector;
-                        const basegfx::B2DVector aAxis(-aX);
-
-                        aEndVector.add(aStyles[ 6 ], aAxis, -aY, false); // aBFromR
-                        aEndVector.add(aStyles[ 5 ], aAxis, aX, false); // aBFromB
-                        aEndVector.add(aStyles[ 4 ], aAxis, aY, true); // aBFromL
-                        aEndVector.sort();
-
-                        CreateBorderPrimitives(
-                            aVerticalSequence,
+                        aData->emplace_back(
                             aOrigin,
                             aX,
-                            aStyles[ 0 ],
-                            aStartVector,
-                            aEndVector,
-                            pTmpColor
-                        );
+                            aStyles[0],
+                            pTmpColor);
+                        drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
+                        rInstance.addSdrConnectStyleData(true, aStyles[3], -aY, false); // aTFromR
+                        rInstance.addSdrConnectStyleData(true, aStyles[2], -aX, true); // aTFromT
+                        rInstance.addSdrConnectStyleData(true, aStyles[1], aY, true); // aTFromL
+
+                        rInstance.addSdrConnectStyleData(false, aStyles[6], -aY, false); // aBFromR
+                        rInstance.addSdrConnectStyleData(false, aStyles[5], aX, false); // aBFromB
+                        rInstance.addSdrConnectStyleData(false, aStyles[4], aY, true); // aBFromL
                     }
                 }
             }
@@ -2584,15 +2567,19 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
         ++aIter;
     }
 
-    // to stay compatible, create order as it was formally. Also try to
-    // merge primitives as far as possible
-    drawinglayer::primitive2d::Primitive2DContainer aSequence;
-
-    svx::frame::HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aSequence);
-    svx::frame::HelperMergeInB2DPrimitiveArray(aVerticalSequence, aSequence);
-
-    // paint
-    mrTabFrame.ProcessPrimitives(aSequence);
+    // create instance of SdrFrameBorderPrimitive2D if
+    // SdrFrameBorderDataVector is used
+    if(!aData->empty())
+    {
+        drawinglayer::primitive2d::Primitive2DContainer aSequence;
+        aSequence.push_back(
+            drawinglayer::primitive2d::Primitive2DReference(
+                new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D(
+                    aData,
+                    true)));
+        // paint
+        mrTabFrame.ProcessPrimitives(aSequence);
+    }
 
     // restore output device:
     rDev.SetDrawMode( nOldDrawMode );
@@ -4508,6 +4495,10 @@ namespace drawinglayer
             basegfx::B2DPoint aBottomLeft(getB2DHomMatrix() * basegfx::B2DPoint(0.0, 1.0));
             basegfx::B2DPoint aBottomRight(getB2DHomMatrix() * basegfx::B2DPoint(1.0, 1.0));
 
+            // prepare SdrFrameBorderDataVector
+            std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData(
+                std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>());
+
             if(getStyleTop().IsUsed())
             {
                 // move top left/right inwards half border width
@@ -4550,108 +4541,99 @@ namespace drawinglayer
             {
                 // create BorderPrimitive(s) for top border
                 const basegfx::B2DVector aVector(aTopRight - aTopLeft);
-                svx::frame::StyleVectorTable aStartStyleVectorTable;
-                svx::frame::StyleVectorTable aEndStyleVectorTable;
+                aData->emplace_back(
+                    aTopLeft,
+                    aVector,
+                    getStyleTop(),
+                    nullptr);
+                drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
 
                 if(getStyleLeft().IsUsed())
                 {
-                    aStartStyleVectorTable.add(getStyleLeft(), aVector, basegfx::B2DVector(aBottomLeft - aTopLeft), false);
+                    rInstance.addSdrConnectStyleData(true, getStyleLeft(), basegfx::B2DVector(aBottomLeft - aTopLeft), false);
                 }
 
                 if(getStyleRight().IsUsed())
                 {
-                    aEndStyleVectorTable.add(getStyleRight(), -aVector, basegfx::B2DVector(aBottomRight - aTopRight), false);
+                    rInstance.addSdrConnectStyleData(false, getStyleRight(), basegfx::B2DVector(aBottomRight - aTopRight), false);
                 }
-
-                CreateBorderPrimitives(
-                    aRetval,
-                    aTopLeft,
-                    aVector,
-                    getStyleTop(),
-                    aStartStyleVectorTable,
-                    aEndStyleVectorTable,
-                    nullptr);
             }
 
             if(getStyleRight().IsUsed())
             {
                 // create BorderPrimitive(s) for right border
                 const basegfx::B2DVector aVector(aBottomRight - aTopRight);
-                svx::frame::StyleVectorTable aStartStyleVectorTable;
-                svx::frame::StyleVectorTable aEndStyleVectorTable;
+                aData->emplace_back(
+                    aTopRight,
+                    aVector,
+                    getStyleRight(),
+                    nullptr);
+                drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
 
                 if(getStyleTop().IsUsed())
                 {
-                    aStartStyleVectorTable.add(getStyleTop(), aVector, basegfx::B2DVector(aTopLeft - aTopRight), false);
+                    rInstance.addSdrConnectStyleData(true, getStyleTop(), basegfx::B2DVector(aTopLeft - aTopRight), false);
                 }
 
                 if(getStyleBottom().IsUsed())
                 {
-                    aEndStyleVectorTable.add(getStyleBottom(), -aVector, basegfx::B2DVector(aBottomLeft - aBottomRight), false);
+                    rInstance.addSdrConnectStyleData(false, getStyleBottom(), basegfx::B2DVector(aBottomLeft - aBottomRight), false);
                 }
-
-                CreateBorderPrimitives(
-                    aRetval,
-                    aTopRight,
-                    aVector,
-                    getStyleRight(),
-                    aStartStyleVectorTable,
-                    aEndStyleVectorTable,
-                    nullptr);
             }
 
             if(getStyleBottom().IsUsed())
             {
                 // create BorderPrimitive(s) for bottom border
                 const basegfx::B2DVector aVector(aBottomLeft - aBottomRight);
-                svx::frame::StyleVectorTable aStartStyleVectorTable;
-                svx::frame::StyleVectorTable aEndStyleVectorTable;
+                aData->emplace_back(
+                    aBottomRight,
+                    aVector,
+                    getStyleBottom(),
+                    nullptr);
+                drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
 
                 if(getStyleRight().IsUsed())
                 {
-                    aStartStyleVectorTable.add(getStyleRight(), aVector, basegfx::B2DVector(aTopRight - aBottomRight), false);
+                    rInstance.addSdrConnectStyleData(true, getStyleRight(), basegfx::B2DVector(aTopRight - aBottomRight), false);
                 }
 
                 if(getStyleLeft().IsUsed())
                 {
-                    aEndStyleVectorTable.add(getStyleLeft(), -aVector, basegfx::B2DVector(aTopLeft - aBottomLeft), false);
+                    rInstance.addSdrConnectStyleData(false, getStyleLeft(), basegfx::B2DVector(aTopLeft - aBottomLeft), false);
                 }
-
-                CreateBorderPrimitives(
-                    aRetval,
-                    aBottomRight,
-                    aVector,
-                    getStyleBottom(),
-                    aStartStyleVectorTable,
-                    aEndStyleVectorTable,
-                    nullptr);
             }
 
             if(getStyleLeft().IsUsed())
             {
                 // create BorderPrimitive(s) for left border
                 const basegfx::B2DVector aVector(aTopLeft - aBottomLeft);
-                svx::frame::StyleVectorTable aStartStyleVectorTable;
-                svx::frame::StyleVectorTable aEndStyleVectorTable;
+                aData->emplace_back(
+                    aBottomLeft,
+                    aVector,
+                    getStyleLeft(),
+                    nullptr);
+                drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
 
                 if(getStyleBottom().IsUsed())
                 {
-                    aStartStyleVectorTable.add(getStyleBottom(), aVector, basegfx::B2DVector(aBottomRight - aBottomLeft), false);
+                    rInstance.addSdrConnectStyleData(true, getStyleBottom(), basegfx::B2DVector(aBottomRight - aBottomLeft), false);
                 }
 
                 if(getStyleTop().IsUsed())
                 {
-                    aEndStyleVectorTable.add(getStyleTop(), -aVector, basegfx::B2DVector(aTopRight - aTopLeft), false);
+                    rInstance.addSdrConnectStyleData(false, getStyleTop(), basegfx::B2DVector(aTopRight - aTopLeft), false);
                 }
+            }
 
-                CreateBorderPrimitives(
-                    aRetval,
-                    aBottomLeft,
-                    aVector,
-                    getStyleLeft(),
-                    aStartStyleVectorTable,
-                    aEndStyleVectorTable,
-                    nullptr);
+            // create instance of SdrFrameBorderPrimitive2D if
+            // SdrFrameBorderDataVector is used
+            if(!aData->empty())
+            {
+                aRetval.push_back(
+                    drawinglayer::primitive2d::Primitive2DReference(
+                        new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D(
+                            aData,
+                            true)));
             }
 
             return aRetval;


More information about the Libreoffice-commits mailing list