[Libreoffice-commits] core.git: Branch 'feature/borderline3' - drawinglayer/CppunitTest_drawinglayer_border.mk drawinglayer/qa drawinglayer/source include/drawinglayer svx/source sw/source

Armin Le Grand Armin.Le.Grand at cib.de
Fri Sep 8 11:42:17 UTC 2017


 drawinglayer/CppunitTest_drawinglayer_border.mk            |    1 
 drawinglayer/qa/unit/border.cxx                            |  105 +
 drawinglayer/source/primitive2d/borderlineprimitive2d.cxx  |  434 +++-----
 include/drawinglayer/primitive2d/borderlineprimitive2d.hxx |  124 --
 svx/source/dialog/framelink.cxx                            |  703 +++----------
 svx/source/dialog/framelinkarray.cxx                       |   10 
 sw/source/core/layout/paintfrm.cxx                         |  187 +--
 7 files changed, 572 insertions(+), 992 deletions(-)

New commits:
commit bbdcbceed51c08c0f4f1653a4af225d2231cf462
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Sep 8 13:39:29 2017 +0200

    borderline: Adapted BorderLinePrimitive2D and usages
    
    Big changes to BorderLinePrimitive2D and BorderLine, freeing
    it from one/three entries, going to a free definition using
    gaps with width but without color. Adapted usages and creation,
    not yet tested much
    
    Change-Id: Ic1255a790401901c3166d200205bc23322b37185

diff --git a/drawinglayer/CppunitTest_drawinglayer_border.mk b/drawinglayer/CppunitTest_drawinglayer_border.mk
index 194c86a6e8ca..fa2f715590cd 100644
--- a/drawinglayer/CppunitTest_drawinglayer_border.mk
+++ b/drawinglayer/CppunitTest_drawinglayer_border.mk
@@ -25,6 +25,7 @@ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_border, \
 	test \
 	tl \
 	unotest \
+	svt \
 ))
 
 $(eval $(call gb_CppunitTest_use_externals,drawinglayer_border,\
diff --git a/drawinglayer/qa/unit/border.cxx b/drawinglayer/qa/unit/border.cxx
index a070f9cdff24..e56a40dac379 100644
--- a/drawinglayer/qa/unit/border.cxx
+++ b/drawinglayer/qa/unit/border.cxx
@@ -25,6 +25,7 @@
 #include <vcl/vclptr.hxx>
 #include <vcl/virdev.hxx>
 #include <editeng/borderline.hxx>
+#include <svtools/borderhelper.hxx>
 
 using namespace com::sun::star;
 
@@ -49,7 +50,7 @@ void DrawinglayerBorderTest::testDoubleDecompositionSolid()
     // 1.47 pixels is 0.03cm at 130% zoom and 96 DPI.
     basegfx::B2DPoint aStart(0, 20);
     basegfx::B2DPoint aEnd(100, 20);
-    double fLeftWidth = 1.47;
+    double const fLeftWidth = 1.47;
     double const fDistance = 1.47;
     double const fRightWidth = 1.47;
     double const fExtendLeftStart = 0;
@@ -58,30 +59,39 @@ void DrawinglayerBorderTest::testDoubleDecompositionSolid()
     double const fExtendRightEnd = 0;
     basegfx::BColor aColorRight;
     basegfx::BColor aColorLeft;
-    basegfx::BColor aColorGap;
-    bool const bHasGapColor = false;
-    SvxBorderLineStyle const nStyle = SvxBorderLineStyle::DOUBLE;
+    const std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0));
+    const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
+    std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
+
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(
+            drawinglayer::attribute::LineAttribute(
+                aColorLeft,
+                fLeftWidth),
+            fExtendLeftStart,
+            fExtendLeftStart,
+            fExtendLeftEnd,
+            fExtendLeftEnd));
+
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(fDistance));
+
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(
+            drawinglayer::attribute::LineAttribute(
+                aColorRight,
+                fRightWidth),
+            fExtendRightStart,
+            fExtendRightStart,
+            fExtendRightEnd,
+            fExtendRightEnd));
+
     rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> aBorder(
         new drawinglayer::primitive2d::BorderLinePrimitive2D(
             aStart,
             aEnd,
-            drawinglayer::primitive2d::BorderLine(
-                fLeftWidth,
-                aColorLeft,
-                drawinglayer::primitive2d::BorderLineExtend(
-                    fExtendLeftStart,
-                    fExtendLeftEnd)),
-            drawinglayer::primitive2d::BorderLine(
-                fDistance,
-                aColorGap),
-            drawinglayer::primitive2d::BorderLine(
-                fRightWidth,
-                aColorRight,
-                drawinglayer::primitive2d::BorderLineExtend(
-                    fExtendRightStart,
-                    fExtendRightEnd)),
-            bHasGapColor,
-            nStyle));
+            aBorderlines,
+            aStrokeAttribute));
 
     // Decompose it into polygons.
     drawinglayer::geometry::ViewInformation2D aView;
@@ -126,33 +136,42 @@ void DrawinglayerBorderTest::testDoublePixelProcessing()
     double const fExtendRightEnd = 0;
     basegfx::BColor aColorRight;
     basegfx::BColor aColorLeft;
-    basegfx::BColor aColorGap;
-    bool const bHasGapColor = false;
-    SvxBorderLineStyle const nStyle = SvxBorderLineStyle::DOUBLE;
-    rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> xBorder(
+    const std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0));
+    const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
+    std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
+
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(
+            drawinglayer::attribute::LineAttribute(
+                aColorLeft,
+                fLeftWidth),
+            fExtendLeftStart,
+            fExtendLeftStart,
+            fExtendLeftEnd,
+            fExtendLeftEnd));
+
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(fDistance));
+
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(
+            drawinglayer::attribute::LineAttribute(
+                aColorRight,
+                fRightWidth),
+            fExtendRightStart,
+            fExtendRightStart,
+            fExtendRightEnd,
+            fExtendRightEnd));
+
+    rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> aBorder(
         new drawinglayer::primitive2d::BorderLinePrimitive2D(
             aStart,
             aEnd,
-            drawinglayer::primitive2d::BorderLine(
-                fLeftWidth,
-                aColorLeft,
-                drawinglayer::primitive2d::BorderLineExtend(
-                    fExtendLeftStart,
-                    fExtendLeftEnd)),
-            drawinglayer::primitive2d::BorderLine(
-                fDistance,
-                aColorGap),
-            drawinglayer::primitive2d::BorderLine(
-                fRightWidth,
-                aColorRight,
-                drawinglayer::primitive2d::BorderLineExtend(
-                    fExtendRightStart,
-                    fExtendRightEnd)),
-            bHasGapColor,
-            nStyle));
+            aBorderlines,
+            aStrokeAttribute));
 
     drawinglayer::primitive2d::Primitive2DContainer aPrimitives;
-    aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(xBorder.get()));
+    aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(aBorder.get()));
 
     // Process the primitives.
     pProcessor->process(aPrimitives);
diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
index 47da04a10945..9421ed8b249b 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -37,140 +37,56 @@ namespace drawinglayer
 {
     namespace primitive2d
     {
-        BorderLineExtend::BorderLineExtend()
-        :   mfExtends()
-        {
-        }
-
-        BorderLineExtend::BorderLineExtend(
-            double fStart,
-            double fEnd)
-        :   mfExtends(2)
-        {
-            mfExtends[0] = fStart;
-            mfExtends[1] = fEnd;
-        }
-
-        BorderLineExtend::BorderLineExtend(
+        BorderLine::BorderLine(
+            const drawinglayer::attribute::LineAttribute& rLineAttribute,
             double fStartLeft,
             double fStartRight,
             double fEndLeft,
             double fEndRight)
-        :   mfExtends(4)
-        {
-            mfExtends[0] = fStartLeft;
-            mfExtends[1] = fStartRight;
-            mfExtends[2] = fEndLeft;
-            mfExtends[3] = fEndRight;
-        }
-
-        BorderLineExtend::~BorderLineExtend()
-        {
-        }
-
-        bool BorderLineExtend::equalStart() const
+        :   maLineAttribute(rLineAttribute),
+            mfStartLeft(fStartLeft),
+            mfStartRight(fStartRight),
+            mfEndLeft(fEndLeft),
+            mfEndRight(fEndRight),
+            mbIsGap(false)
         {
-            if (mfExtends.empty()|| 2 == mfExtends.size())
-                return true;
-            return mfExtends[0] == mfExtends[1];
         }
 
-        bool BorderLineExtend::equalEnd() const
-        {
-            if (mfExtends.empty() || 2 == mfExtends.size())
-                return true;
-            return mfExtends[2] == mfExtends[3];
-        }
-
-        double BorderLineExtend::getStartLeft() const
-        {
-            if (mfExtends.empty())
-                return 0.0;
-            return mfExtends[0];
-        }
-
-        double BorderLineExtend::getStartRight() const
-        {
-            if (mfExtends.empty())
-                return 0.0;
-            if (2 == mfExtends.size())
-                return mfExtends[0];
-            return mfExtends[1];
-        }
-
-        double BorderLineExtend::getEndLeft() const
+        BorderLine::BorderLine(
+            double fWidth)
+        :   maLineAttribute(basegfx::BColor(), fWidth),
+            mfStartLeft(0.0),
+            mfStartRight(0.0),
+            mfEndLeft(0.0),
+            mfEndRight(0.0),
+            mbIsGap(true)
         {
-            if (mfExtends.empty())
-                return 0.0;
-            if (2 == mfExtends.size())
-                return mfExtends[1];
-            return mfExtends[2];
         }
 
-        double BorderLineExtend::getEndRight() const {
-            if (mfExtends.empty())
-                return 0.0;
-            if (2 == mfExtends.size())
-                return mfExtends[1];
-            return mfExtends[3];
-        }
-
-        double BorderLineExtend::getStartAverage() const
+        BorderLine::~BorderLine()
         {
-            if (mfExtends.empty())
-                return 0.0;
-            if (2 == mfExtends.size())
-                return mfExtends[0];
-            return (mfExtends[0] + mfExtends[1]) * 0.5;
         }
 
-        double BorderLineExtend::getEndAverage() const
+        bool BorderLine::operator==(const BorderLine& rBorderLine) const
         {
-            if (mfExtends.empty())
-                return 0.0;
-            if (2 == mfExtends.size())
-                return mfExtends[1];
-            return (mfExtends[2] + mfExtends[3]) * 0.5;
+            return getLineAttribute() == rBorderLine.getLineAttribute()
+                && getStartLeft() == rBorderLine.getStartLeft()
+                && getStartRight() == rBorderLine.getStartRight()
+                && getEndLeft() == rBorderLine.getEndLeft()
+                && getEndRight() == rBorderLine.getEndRight()
+                && isGap() == rBorderLine.isGap();
         }
 
-        bool BorderLineExtend::operator==(const BorderLineExtend& rBorderLineExtend) const
+        double BorderLine::getAdaptedWidth(double fMinWidth) const
         {
-            if (mfExtends.size() == rBorderLineExtend.mfExtends.size())
+            if(isGap())
             {
-                return mfExtends == rBorderLineExtend.mfExtends;
+                return std::max(getLineAttribute().getWidth(), fMinWidth);
+            }
+            else
+            {
+                return getLineAttribute().getWidth();
             }
-
-            return false;
-        }
-
-        BorderLine::BorderLine(
-            double fWidth,
-            const basegfx::BColor& rRGBColor,
-            const BorderLineExtend& rBorderLineExtend)
-            : mfWidth(fWidth),
-            maRGBColor(rRGBColor),
-            maBorderLineExtend(rBorderLineExtend)
-        {
-        }
-
-        BorderLine::BorderLine(
-            double fWidth,
-            const basegfx::BColor& rRGBColor)
-            : mfWidth(fWidth),
-            maRGBColor(rRGBColor),
-            maBorderLineExtend()
-        {
-        }
-
-        BorderLine::~BorderLine()
-        {
-        }
-
-        bool BorderLine::operator==(const BorderLine& rBorderLine) const
-        {
-            return getWidth() == rBorderLine.getWidth()
-                && getRGBColor() == rBorderLine.getRGBColor()
-                && getBorderLineExtend() == rBorderLine.getBorderLineExtend();
         }
 
         // helper to add a centered, maybe stroked line primitive to rContainer
@@ -179,7 +95,7 @@ namespace drawinglayer
             const basegfx::B2DPoint& rStart,
             const basegfx::B2DPoint& rEnd,
             const attribute::LineAttribute& rLineAttribute,
-            const attribute::StrokeAttribute & rStrokeAttribute)
+            const attribute::StrokeAttribute& rStrokeAttribute)
         {
             basegfx::B2DPolygon aPolygon;
 
@@ -203,94 +119,135 @@ namespace drawinglayer
             }
         }
 
+        double BorderLinePrimitive2D::getFullWidth() const
+        {
+            double fRetval(0.0);
+
+            for(const auto& candidate : maBorderLines)
+            {
+                fRetval += candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance);
+            }
+
+            return fRetval;
+        }
+
         void BorderLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
         {
-            if (!getStart().equal(getEnd()))
+            if (!getStart().equal(getEnd()) && !getBorderLines().empty())
             {
                 // get data and vectors
                 basegfx::B2DVector aVector(getEnd() - getStart());
                 aVector.normalize();
                 const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector));
-                static double fPatScFact(10.0); // 10.0 multiply, see old code
-                const std::vector<double> aDashing(svtools::GetLineDashing(getStyle(), getPatternScale() * fPatScFact));
-                const attribute::StrokeAttribute aStrokeAttribute(aDashing);
+                const double fFullWidth(getFullWidth());
+                double fOffset(fFullWidth * -0.5);
 
-                if (3 == getBorderLines().size())
+                for(const auto& candidate : maBorderLines)
                 {
-                    // double line with gap. Use mfDiscreteGapDistance (see get2DDecomposition) as distance.
-                    // That value is prepared to be at least one pixel (discrete unit) so that the
-                    // decomposition is view-dependent in this cases
-                    const BorderLine& rLeft(getBorderLines()[0]);
-                    const BorderLine& rGap(getBorderLines()[1]);
-                    const BorderLine& rRight(getBorderLines()[2]);
-                    const double fFullWidth(rLeft.getWidth() + mfDiscreteGapDistance + rRight.getWidth());
+                    const double fWidth(candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance) * 0.5);
 
+                    if(!candidate.isGap())
                     {
-                        // inside line (left of vector). Create stroke primitive centered on left line width
-                        const double fDeltaY((rLeft.getWidth() - fFullWidth) * 0.5);
-                        const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
-                        const basegfx::B2DPoint aStart(getStart() - (aVector * rLeft.getBorderLineExtend().getStartAverage()) + aDeltaY);
-                        const basegfx::B2DPoint aEnd(getEnd() + (aVector * rLeft.getBorderLineExtend().getEndAverage()) + aDeltaY);
-                        const attribute::LineAttribute aLineAttribute(rLeft.getRGBColor(), rLeft.getWidth());
+                        const basegfx::B2DVector aDeltaY(aPerpendicular * (fOffset + (fWidth * 0.5)));
+                        const basegfx::B2DPoint aStart(getStart() - (aVector * candidate.getStartAverage()) + aDeltaY);
+                        const basegfx::B2DPoint aEnd(getEnd() + (aVector * candidate.getEndAverage()) + aDeltaY);
 
                         addPolygonStrokePrimitive2D(
                             rContainer,
                             aStart,
                             aEnd,
-                            aLineAttribute,
-                            aStrokeAttribute);
+                            candidate.getLineAttribute(),
+                            getStrokeAttribute());
                     }
 
-                    if (hasGapColor())
-                    {
-                        // gap (if visible, found practical usage in Writer MultiColorBorderLines).
-                        // Create stroke primitive on vector with given color centered on gap position
-                        const double fDeltaY(((fFullWidth - mfDiscreteGapDistance) * 0.5) - rRight.getWidth());
-                        const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
-                        const basegfx::B2DPoint aStart(getStart() - (aVector * rGap.getBorderLineExtend().getStartAverage()) + aDeltaY);
-                        const basegfx::B2DPoint aEnd(getEnd() + (aVector * rGap.getBorderLineExtend().getEndAverage()) + aDeltaY);
-                        const attribute::LineAttribute aLineAttribute(rGap.getRGBColor(), mfDiscreteGapDistance);
-
-                        addPolygonStrokePrimitive2D(
-                            rContainer,
-                            aStart,
-                            aEnd,
-                            aLineAttribute,
-                            aStrokeAttribute);
-                    }
-
-                    {
-                        // outside line (right of vector). Create stroke primitive centered on right line width
-                        const double fDeltaY((fFullWidth - rRight.getWidth()) * 0.5);
-                        const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
-                        const basegfx::B2DPoint aStart(getStart() - (aVector * rRight.getBorderLineExtend().getStartAverage()) + aDeltaY);
-                        const basegfx::B2DPoint aEnd(getEnd() + (aVector * rRight.getBorderLineExtend().getEndAverage()) + aDeltaY);
-                        const attribute::LineAttribute aLineAttribute(rRight.getRGBColor(), rRight.getWidth());
-
-                        addPolygonStrokePrimitive2D(
-                            rContainer,
-                            aStart,
-                            aEnd,
-                            aLineAttribute,
-                            aStrokeAttribute);
-                    }
-                }
-                else
-                {
-                    // single line, only inside values used, no vertical offsets
-                    const BorderLine& rBorderLine(getBorderLines()[0]);
-                    const attribute::LineAttribute aLineAttribute(rBorderLine.getRGBColor(), rBorderLine.getWidth());
-
-                    addPolygonStrokePrimitive2D(
-                        rContainer,
-                        getStart() - (aVector * rBorderLine.getBorderLineExtend().getStartAverage()),
-                        getEnd() + (aVector * rBorderLine.getBorderLineExtend().getEndAverage()),
-                        aLineAttribute,
-                        aStrokeAttribute);
+                    fOffset += fWidth;
                 }
             }
         }
 
+
+
+
+        //         static double fPatScFact(10.0); // 10.0 multiply, see old code
+        //         const std::vector<double> aDashing(svtools::GetLineDashing(getStyle(), getPatternScale() * fPatScFact));
+        //         const attribute::StrokeAttribute aStrokeAttribute(aDashing);
+
+        //         if (3 == getBorderLines().size())
+        //         {
+        //             // double line with gap. Use mfSmallestAllowedDiscreteGapDistance (see get2DDecomposition) as distance.
+        //             // That value is prepared to be at least one pixel (discrete unit) so that the
+        //             // decomposition is view-dependent in this cases
+        //             const BorderLine& rLeft(getBorderLines()[0]);
+        //             const BorderLine& rGap(getBorderLines()[1]);
+        //             const BorderLine& rRight(getBorderLines()[2]);
+        //             const double fFullWidth(rLeft.getWidth() + mfSmallestAllowedDiscreteGapDistance + rRight.getWidth());
+
+        //             {
+        //                 // inside line (left of vector). Create stroke primitive centered on left line width
+        //                 const double fDeltaY((rLeft.getWidth() - fFullWidth) * 0.5);
+        //                 const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
+        //                 const basegfx::B2DPoint aStart(getStart() - (aVector * rLeft.getBorderLineExtend().getStartAverage()) + aDeltaY);
+        //                 const basegfx::B2DPoint aEnd(getEnd() + (aVector * rLeft.getBorderLineExtend().getEndAverage()) + aDeltaY);
+        //                 const attribute::LineAttribute aLineAttribute(rLeft.getRGBColor(), rLeft.getWidth());
+
+        //                 addPolygonStrokePrimitive2D(
+        //                     rContainer,
+        //                     aStart,
+        //                     aEnd,
+        //                     aLineAttribute,
+        //                     aStrokeAttribute);
+        //             }
+
+        //             if (hasGapColor())
+        //             {
+        //                 // gap (if visible, found practical usage in Writer MultiColorBorderLines).
+        //                 // Create stroke primitive on vector with given color centered on gap position
+        //                 const double fDeltaY(((fFullWidth - mfSmallestAllowedDiscreteGapDistance) * 0.5) - rRight.getWidth());
+        //                 const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
+        //                 const basegfx::B2DPoint aStart(getStart() - (aVector * rGap.getBorderLineExtend().getStartAverage()) + aDeltaY);
+        //                 const basegfx::B2DPoint aEnd(getEnd() + (aVector * rGap.getBorderLineExtend().getEndAverage()) + aDeltaY);
+        //                 const attribute::LineAttribute aLineAttribute(rGap.getRGBColor(), mfSmallestAllowedDiscreteGapDistance);
+
+        //                 addPolygonStrokePrimitive2D(
+        //                     rContainer,
+        //                     aStart,
+        //                     aEnd,
+        //                     aLineAttribute,
+        //                     aStrokeAttribute);
+        //             }
+
+        //             {
+        //                 // outside line (right of vector). Create stroke primitive centered on right line width
+        //                 const double fDeltaY((fFullWidth - rRight.getWidth()) * 0.5);
+        //                 const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
+        //                 const basegfx::B2DPoint aStart(getStart() - (aVector * rRight.getBorderLineExtend().getStartAverage()) + aDeltaY);
+        //                 const basegfx::B2DPoint aEnd(getEnd() + (aVector * rRight.getBorderLineExtend().getEndAverage()) + aDeltaY);
+        //                 const attribute::LineAttribute aLineAttribute(rRight.getRGBColor(), rRight.getWidth());
+
+        //                 addPolygonStrokePrimitive2D(
+        //                     rContainer,
+        //                     aStart,
+        //                     aEnd,
+        //                     aLineAttribute,
+        //                     aStrokeAttribute);
+        //             }
+        //         }
+        //         else
+        //         {
+        //             // single line, only inside values used, no vertical offsets
+        //             const BorderLine& rBorderLine(getBorderLines()[0]);
+        //             const attribute::LineAttribute aLineAttribute(rBorderLine.getRGBColor(), rBorderLine.getWidth());
+
+        //             addPolygonStrokePrimitive2D(
+        //                 rContainer,
+        //                 getStart() - (aVector * rBorderLine.getBorderLineExtend().getStartAverage()),
+        //                 getEnd() + (aVector * rBorderLine.getBorderLineExtend().getEndAverage()),
+        //                 aLineAttribute,
+        //                 aStrokeAttribute);
+        //         }
+        //     }
+        // }
+
         bool BorderLinePrimitive2D::isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const
         {
             if (!getStart().equal(getEnd()))
@@ -307,42 +264,15 @@ namespace drawinglayer
         BorderLinePrimitive2D::BorderLinePrimitive2D(
             const basegfx::B2DPoint& rStart,
             const basegfx::B2DPoint& rEnd,
-            const BorderLine& rBorderLine,
-            SvxBorderLineStyle nStyle,
-            double fPatternScale)
-        :   BufferedDecompositionPrimitive2D(),
-            maStart(rStart),
-            maEnd(rEnd),
-            maBorderLines(),
-            mbHasGapColor(false),
-            mnStyle(nStyle),
-            mfPatternScale(fPatternScale),
-            mfDiscreteGapDistance(0.0)
-        {
-            maBorderLines.push_back(rBorderLine);
-        }
-
-        BorderLinePrimitive2D::BorderLinePrimitive2D(
-            const basegfx::B2DPoint& rStart,
-            const basegfx::B2DPoint& rEnd,
-            const BorderLine& rLeft,
-            const BorderLine& rGap,
-            const BorderLine& rRight,
-            bool bHasGapColor,
-            SvxBorderLineStyle nStyle,
-            double fPatternScale)
+            const std::vector< BorderLine >& rBorderLines,
+            const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute)
         :   BufferedDecompositionPrimitive2D(),
             maStart(rStart),
             maEnd(rEnd),
-            maBorderLines(),
-            mbHasGapColor(bHasGapColor),
-            mnStyle(nStyle),
-            mfPatternScale(fPatternScale),
-            mfDiscreteGapDistance(0.0)
+            maBorderLines(rBorderLines),
+            maStrokeAttribute(rStrokeAttribute),
+            mfSmallestAllowedDiscreteGapDistance(0.0)
         {
-            maBorderLines.push_back(rLeft);
-            maBorderLines.push_back(rGap);
-            maBorderLines.push_back(rRight);
         }
 
         bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
@@ -353,9 +283,7 @@ namespace drawinglayer
 
                 if (getStart() == rCompare.getStart()
                     && getEnd() == rCompare.getEnd()
-                    && hasGapColor() == rCompare.hasGapColor()
-                    && getStyle() == rCompare.getStyle()
-                    && getPatternScale() == rCompare.getPatternScale())
+                    && getStrokeAttribute() == rCompare.getStrokeAttribute())
                 {
                     if (getBorderLines().size() == rCompare.getBorderLines().size())
                     {
@@ -373,36 +301,64 @@ namespace drawinglayer
             return false;
         }
 
+        bool BorderLinePrimitive2D::getSmallestGap(double& rfSmallestGap) const
+        {
+            bool bGapFound(false);
+
+            for(const auto& candidate : maBorderLines)
+            {
+                if(candidate.isGap())
+                {
+                    if(bGapFound)
+                    {
+                        rfSmallestGap = std::min(rfSmallestGap, candidate.getLineAttribute().getWidth());
+                    }
+                    else
+                    {
+                        bGapFound = true;
+                        rfSmallestGap = candidate.getLineAttribute().getWidth();
+                    }
+                }
+            }
+
+            return bGapFound;
+        }
+
         void BorderLinePrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const
         {
             ::osl::MutexGuard aGuard(m_aMutex);
 
-            if (!getStart().equal(getEnd()) && 3 == getBorderLines().size())
+            if (!getStart().equal(getEnd()) && getBorderLines().size() > 1)
             {
-                // Double line with gap. In this case, we want to be view-dependent.
-                // Get the current DiscreteUnit, look at X and Y and use the maximum
-                const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
-                const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY())));
-
-                // When discrete unit is bigger than distance (distance is less than one pixel),
-                // force distance to one pixel. Or expressed different, do not let the distance
-                // get smaller than one pixel. This is done for screen rendering and compatibility.
-                // This can also be done using DiscreteMetricDependentPrimitive2D as base class
-                // for this class, but specialization is better here for later buffering (only
-                // do this when 'double line with gap')
-                const double fDistance(getBorderLines()[1].getWidth());
-                const double fNewDiscreteDistance(std::max(fDiscreteUnit, fDistance));
-
-                if (!rtl::math::approxEqual(fNewDiscreteDistance, mfDiscreteGapDistance))
+                // Line with potential gap. In this case, we want to be view-dependent.
+                // get the smallest gap
+                double fSmallestGap(0.0);
+
+                if(getSmallestGap(fSmallestGap))
                 {
-                    if (!getBuffered2DDecomposition().empty())
+                    // Get the current DiscreteUnit, look at X and Y and use the maximum
+                    const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
+                    const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY())));
+
+                    // When discrete unit is bigger than distance (distance is less than one pixel),
+                    // force distance to one pixel. Or expressed different, do not let the distance
+                    // get smaller than one pixel. This is done for screen rendering and compatibility.
+                    // This can also be done using DiscreteMetricDependentPrimitive2D as base class
+                    // for this class, but specialization is better here for later buffering (only
+                    // do this when 'double line with gap')
+                    const double fNewDiscreteDistance(std::max(fDiscreteUnit, fSmallestGap));
+
+                    if (!rtl::math::approxEqual(fNewDiscreteDistance, mfSmallestAllowedDiscreteGapDistance))
                     {
-                        // conditions of last local decomposition have changed, delete
-                        const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
-                    }
+                        if (!getBuffered2DDecomposition().empty())
+                        {
+                            // conditions of last local decomposition have changed, delete
+                            const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
+                        }
 
-                    // remember value for usage in create2DDecomposition
-                    const_cast< BorderLinePrimitive2D* >(this)->mfDiscreteGapDistance = fNewDiscreteDistance;
+                        // remember value for usage in create2DDecomposition
+                        const_cast< BorderLinePrimitive2D* >(this)->mfSmallestAllowedDiscreteGapDistance = fNewDiscreteDistance;
+                    }
                 }
             }
 
diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
index ad28a5eeaac2..992347c7dc9b 100644
--- a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
@@ -26,6 +26,8 @@
 #include <basegfx/color/bcolor.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <drawinglayer/attribute/lineattribute.hxx>
+#include <drawinglayer/attribute/strokeattribute.hxx>
 
 enum class SvxBorderLineStyle : sal_Int16;
 
@@ -33,70 +35,53 @@ namespace drawinglayer
 {
     namespace primitive2d
     {
-        /** BorderLineExtend class
-         */
-        class DRAWINGLAYER_DLLPUBLIC BorderLineExtend
-        {
-        private:
-            std::vector<double> mfExtends;
-
-        public:
-            BorderLineExtend();
-            BorderLineExtend(
-                double fStart,
-                double fEnd);
-            BorderLineExtend(
-                double fStartLeft,
-                double fStartRight,
-                double fEndLeft,
-                double fEndRight);
-            ~BorderLineExtend();
-
-            bool equalStart() const;
-            bool equalEnd() const;
-
-            double getStartLeft() const;
-            double getStartRight() const;
-            double getEndLeft() const;
-            double getEndRight() const;
-
-            double getStartAverage() const;
-            double getEndAverage() const;
-
-            /// compare operator
-            bool operator==(const BorderLineExtend& rBorderLineExtend) const;
-        };
-
         /** BorderLine class
-        Helper class holding the style definition for a single part of a full NorderLine definition.
+        Helper class holding the style definition for a single part of a full BorderLine definition.
         Line extends are for start/end and for Left/Right, seen in vector direction. If
         Left != Right that means the line has a diagonal start/end
         */
         class DRAWINGLAYER_DLLPUBLIC BorderLine
         {
         private:
-            // line width
-            double              mfWidth;
-
-            // line color
-            basegfx::BColor     maRGBColor;
+            // line attribute containing Width, Color and others
+            drawinglayer::attribute::LineAttribute  maLineAttribute;
 
             // line extends
-            BorderLineExtend    maBorderLineExtend;
+            double              mfStartLeft;
+            double              mfStartRight;
+            double              mfEndLeft;
+            double              mfEndRight;
+
+            // if this is a gap, this is set to true
+            bool                mbIsGap;
 
         public:
+            // Constructor for visible BorderLine segments
             BorderLine(
-                double fWidth,
-                const basegfx::BColor& rRGBColor,
-                const BorderLineExtend& rBorderLineExtend);
-            BorderLine(
-                double fWidth,
-                const basegfx::BColor& rRGBColor);
+                const drawinglayer::attribute::LineAttribute& rLineAttribute,
+                double fStartLeft = 0.0,
+                double fStartRight = 0.0,
+                double fEndLeft = 0.0,
+                double fEndRight = 0.0);
+
+            // Constructor for gap BorderLine segments
+            BorderLine(double fWidth);
+
             ~BorderLine();
 
-            double getWidth() const { return mfWidth; }
-            const basegfx::BColor& getRGBColor() const { return maRGBColor; }
-            const BorderLineExtend& getBorderLineExtend() const { return maBorderLineExtend; }
+            const drawinglayer::attribute::LineAttribute& getLineAttribute() const { return maLineAttribute; }
+            double getStartLeft() const { return mfStartLeft; }
+            double getStartRight() const { return mfStartRight; }
+            double getEndLeft() const { return mfEndLeft; }
+            double getEndRight() const { return mfEndRight; }
+            bool isGap() const { return mbIsGap; }
+
+            /// helper to get adapted width (maximum)
+            double getAdaptedWidth(double fMinWidth) const;
+
+            /// helper to get average values Start/End
+            double getStartAverage() const { return 0.5 * (mfStartLeft + mfStartRight); }
+            double getEndAverage() const { return 0.5 * (mfEndLeft + mfEndRight); }
 
             /// compare operator
             bool operator==(const BorderLine& rBorderLine) const;
@@ -117,50 +102,39 @@ namespace drawinglayer
             basegfx::B2DPoint                               maStart;
             basegfx::B2DPoint                               maEnd;
 
-            /// the single BorderLine style definition(s), one or three allowed (see constructors)
+            /// the single BorderLine style definition(s), one or three mostly used
             std::vector< BorderLine >                       maBorderLines;
 
-            bool                                            mbHasGapColor;
-
             /// common style definitions
-            SvxBorderLineStyle                              mnStyle;
-            double                                          mfPatternScale;
+            const drawinglayer::attribute::StrokeAttribute  maStrokeAttribute;
 
-            // for view dependent decomposition in the case with distance (gap),
-            // remember the last used concrete mfDistance, see get2DDecomposition
+            // for view dependent decomposition in the case with existing gaps,
+            // remember the smallest allowed concrete gap distance, see get2DDecomposition
             // implementation
-            double                                          mfDiscreteGapDistance;
+            double                                          mfSmallestAllowedDiscreteGapDistance;
 
             /// create local decomposition
             virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override;
 
+            /// helper to find smallest defined gap in maBorderLines
+            bool getSmallestGap(double& rfSmallestGap) const;
+
+            /// helper to get the full width taking mfSmallestAllowedDiscreteGapDistance into account
+            double getFullWidth() const;
+
         public:
             /// simplified constructor for BorderLine with single edge
             BorderLinePrimitive2D(
                 const basegfx::B2DPoint& rStart,
                 const basegfx::B2DPoint& rEnd,
-                const BorderLine& rBorderLine,
-                SvxBorderLineStyle nStyle,
-                double fPatternScale = 1.0);
-
-            /// constructor for full-fledged BorderLine with two edges and gap
-            BorderLinePrimitive2D(
-                const basegfx::B2DPoint& rStart,
-                const basegfx::B2DPoint& rEnd,
-                const BorderLine& rLeft,
-                const BorderLine& rGap,
-                const BorderLine& rRight,
-                bool bHasGapColor,
-                SvxBorderLineStyle nStyle,
-                double fPatternScale = 1.0);
+                const std::vector< BorderLine >& rBorderLines,
+                const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute);
 
             /// data read access
             const basegfx::B2DPoint& getStart() const { return maStart; }
             const basegfx::B2DPoint& getEnd() const { return maEnd; }
             const std::vector< BorderLine >& getBorderLines() const { return maBorderLines; }
-            bool hasGapColor() const { return mbHasGapColor; }
-            SvxBorderLineStyle getStyle() const { return mnStyle; }
-            double getPatternScale() const { return mfPatternScale; }
+            const drawinglayer::attribute::StrokeAttribute& getStrokeAttribute() const { return maStrokeAttribute; }
 
             /// helper to decide if AntiAliasing should be used
             bool isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const;
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index 4869535a76f3..ca66b285f8d4 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -358,404 +358,15 @@ bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder,
 }
 
 // Drawing functions
-// struct OffsetPair
-// {
-//     double          mfLeft;
-//     double          mfRight;
-
-//     OffsetPair(double a, double b) : mfLeft(a), mfRight(b) {}
-// };
-
-// struct OffsetCutSet
-// {
-//     double          mfLeftLeft;
-//     double          mfRightLeft;
-//     double          mfLeftRight;
-//     double          mfRightRight;
-// };
-
-// const OffsetCutSet* getMinMaxCutSet(bool bMin, const std::vector< OffsetCutSet >& myCutSets)
-// {
-//     if (myCutSets.empty())
-//     {
-//         return nullptr;
-//     }
-
-//     if (1 == myCutSets.size())
-//     {
-//         return &myCutSets[0];
-//     }
-
-//     const OffsetCutSet* pRetval = &myCutSets[0];
-//     double fRetval(pRetval->mfLeftLeft + pRetval->mfLeftRight + pRetval->mfRightLeft + pRetval->mfRightRight);
-
-//     for (size_t a(1); a < myCutSets.size(); a++)
-//     {
-//         const OffsetCutSet* pCandidate = &myCutSets[a];
-//         const double fCandidate(pCandidate->mfLeftLeft + pCandidate->mfLeftRight + pCandidate->mfRightLeft + pCandidate->mfRightRight);
-
-//         if ((bMin && fCandidate < fRetval) || (!bMin && fCandidate > fRetval))
-//         {
-//             pRetval = pCandidate;
-//             fRetval = fCandidate;
-//         }
-//     }
-
-//     return pRetval;
-// }
-
-// void getOffsetPairsFromStyle(const Style& rStyle, std::vector< OffsetPair >& offsets)
-// {
-//     if (rStyle.IsUsed())
-//     {
-//         if (rStyle.Dist() && rStyle.Secn())
-//         {
-//             // both lines used (or all three), push four values, from outer to inner
-//             switch (rStyle.GetRefMode())
-//             {
-//             case RefMode::Centered:
-//             {
-//                 const double fHalfFullWidth(rStyle.GetWidth() * 0.5);
-//                 offsets.push_back(OffsetPair(-fHalfFullWidth, rStyle.Prim() - fHalfFullWidth));
-//                 offsets.push_back(OffsetPair((rStyle.Prim() + rStyle.Dist()) - fHalfFullWidth, fHalfFullWidth));
-//                 break;
-//             }
-//             case RefMode::Begin:
-//             {
-//                 offsets.push_back(OffsetPair(0.0, rStyle.Prim()));
-//                 offsets.push_back(OffsetPair(rStyle.Prim() + rStyle.Dist(), rStyle.GetWidth()));
-//                 break;
-//             }
-//             default: // case RefMode::End:
-//             {
-//                 const double fFullWidth(rStyle.GetWidth());
-//                 offsets.push_back(OffsetPair(-fFullWidth, rStyle.Prim() - fFullWidth));
-//                 offsets.push_back(OffsetPair((rStyle.Prim() + rStyle.Dist()) - fFullWidth, 0.0));
-//                 break;
-//             }
-//             }
-//         }
-//         else
-//         {
-//             // one line used, push two values, from outer to inner
-//             switch (rStyle.GetRefMode())
-//             {
-//             case RefMode::Centered:
-//                 offsets.push_back(OffsetPair(rStyle.Prim() * -0.5, rStyle.Prim() * 0.5));
-//                 break;
-//             case RefMode::Begin:
-//                 offsets.push_back(OffsetPair(0.0, rStyle.Prim()));
-//                 break;
-//             default: // case RefMode::End:
-//                 offsets.push_back(OffsetPair(-rStyle.Prim(), 0.0));
-//                 break;
-//             }
-//         }
-//     }
-// }
-
-// void createCutsWithStyle(
-//     const basegfx::B2DPoint& rOrigin,
-//     const basegfx::B2DVector& rOtherVector,
-//     const basegfx::B2DVector& rOtherUnifiedPerpendicular,
-//     const OffsetPair& rOtherOffsets,
-//     const Style& rStyle,
-//     const basegfx::B2DVector& rMyVector,
-//     std::vector< OffsetCutSet>& rOtherCuts)
-// {
-//     if (rStyle.IsUsed())
-//     {
-//         // get values dependent on source vector
-//         const basegfx::B2DVector aMyUnifiedPerpendicular(basegfx::getNormalizedPerpendicular(rMyVector));
-//         const basegfx::B2DPoint aOtherPosLeft(rOrigin + (rOtherUnifiedPerpendicular * rOtherOffsets.mfLeft));
-//         const basegfx::B2DPoint aOtherPosRight(rOrigin + (rOtherUnifiedPerpendicular * rOtherOffsets.mfRight));
-//         std::vector< OffsetPair > myOffsets;
-
-//         // get offsets from outer to inner from target style (one or two)
-//         getOffsetPairsFromStyle(rStyle, myOffsets);
-
-//         for (const auto& myOffset : myOffsets)
-//         {
-//             // get values for new vectors and create all four cuts
-//             const basegfx::B2DPoint aMyPosLeft(rOrigin + (aMyUnifiedPerpendicular * myOffset.mfLeft));
-//             const basegfx::B2DPoint aMyPosRight(rOrigin + (aMyUnifiedPerpendicular * myOffset.mfRight));
-//             OffsetCutSet aNewCuts;
-
-//             basegfx::tools::findCut(
-//                 aOtherPosLeft,
-//                 rOtherVector,
-//                 aMyPosLeft,
-//                 rMyVector,
-//                 CutFlagValue::LINE,
-//                 &aNewCuts.mfLeftLeft);
-
-//             basegfx::tools::findCut(
-//                 aOtherPosLeft,
-//                 rOtherVector,
-//                 aMyPosRight,
-//                 rMyVector,
-//                 CutFlagValue::LINE,
-//                 &aNewCuts.mfLeftRight);
-
-//             basegfx::tools::findCut(
-//                 aOtherPosRight,
-//                 rOtherVector,
-//                 aMyPosLeft,
-//                 rMyVector,
-//                 CutFlagValue::LINE,
-//                 &aNewCuts.mfRightLeft);
-
-//             basegfx::tools::findCut(
-//                 aOtherPosRight,
-//                 rOtherVector,
-//                 aMyPosRight,
-//                 rMyVector,
-//                 CutFlagValue::LINE,
-//                 &aNewCuts.mfRightRight);
-
-//             rOtherCuts.push_back(aNewCuts);
-//         }
-//     }
-// }
-
-// double getSimpleExtendedLineValues(
-//     const basegfx::B2DPoint& rOrigin,
-//     const basegfx::B2DVector& rX,
-//     const basegfx::B2DVector& rY,
-//     const basegfx::B2DVector& rPerpendX,
-//     const OffsetPair& myOffset,
-//     const Style& rFirst,
-//     const Style& rSecond,
-//     bool bEdgeStart,
-//     double fLength)
-// {
-//     std::vector< OffsetCutSet > myCutSets;
-//     createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rFirst, rY, myCutSets);
-//     createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rSecond, rY, myCutSets);
-//     const OffsetCutSet* pResult = getMinMaxCutSet(bEdgeStart, myCutSets);
-
-//     if (pResult)
-//     {
-//         if (bEdgeStart)
-//         {
-//             return (pResult->mfLeftRight + pResult->mfRightRight) * -0.5 * fLength;
-//         }
-//         else
-//         {
-//             return (pResult->mfLeftLeft + pResult->mfRightLeft) * 0.5 * fLength;
-//         }
-//     }
-
-//     return 0.0;
-// }
-
-// double getComplexExtendedLineValues(
-//     const basegfx::B2DPoint& rOrigin,
-//     const basegfx::B2DVector& rX,
-//     const basegfx::B2DVector& rY,
-//     const basegfx::B2DVector& rPerpendX,
-//     const OffsetPair& myOffset,
-//     const Style& rFirst,
-//     const Style& rSecond,
-//     bool bEdgeStart,
-//     double fLength)
-// {
-//     std::vector< OffsetCutSet > myCutSets;
-//     createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rFirst, rY, myCutSets);
-//     const OffsetCutSet* pResult = getMinMaxCutSet(!bEdgeStart, myCutSets);
-
-//     if (!pResult)
-//     {
-//         createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rSecond, rY, myCutSets);
-//         pResult = getMinMaxCutSet(bEdgeStart, myCutSets);
-//     }
-
-//     if (pResult)
-//     {
-//         if (bEdgeStart)
-//         {
-//             return (pResult->mfLeftRight + pResult->mfRightRight) * 0.5 * -fLength;
-//         }
-//         else
-//         {
-//             return (pResult->mfLeftLeft + pResult->mfRightLeft) * 0.5 * fLength;
-//         }
-//     }
-
-//     return 0.0;
-// }
-
-// void CreateBorderPrimitives(
-//     drawinglayer::primitive2d::Primitive2DContainer& rTarget,
-//     const basegfx::B2DPoint& rOrigin,
-//     const basegfx::B2DVector& rX,
-//     const basegfx::B2DVector& rY,
-//     const Style& rBorder,
-//     const Style& /*rLFromTR*/,
-//     const Style& rLFromT,
-//     const Style& /*rLFromL*/,
-//     const Style& rLFromB,
-//     const Style& /*rLFromBR*/,
-//     const Style& /*rRFromTL*/,
-//     const Style& rRFromT,
-//     const Style& /*rRFromR*/,
-//     const Style& rRFromB,
-//     const Style& /*rRFromBL*/,
-//     const Color* pForceColor)
-// {
-//     if (rBorder.IsUsed())
-//     {
-//         const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
-//         const double fLength(rX.getLength());
-
-//         // do not forget RefMode offset, primitive will assume RefMode::Centered
-//         basegfx::B2DVector aRefModeOffset;
-
-//         if (RefMode::Centered != rBorder.GetRefMode())
-//         {
-//             const double fHalfWidth(rBorder.GetWidth() * 0.5);
-
-//             if (RefMode::Begin == rBorder.GetRefMode())
-//             {
-//                 // move aligned below vector
-//                 aRefModeOffset = aPerpendX * fHalfWidth;
-//             }
-//             else if (RefMode::End == rBorder.GetRefMode())
-//             {
-//                 // move aligned above vector
-//                 aRefModeOffset = aPerpendX * -fHalfWidth;
-//             }
-//         }
-
-//         // create start/end (use RefMode)
-//         const basegfx::B2DPoint aStart(rOrigin + aRefModeOffset);
-//         const basegfx::B2DPoint aEnd(aStart + rX);
-
-//         // get offsets for my style (one or two)
-//         std::vector< OffsetPair > myOffsets;
-//         getOffsetPairsFromStyle(rBorder, myOffsets);
-
-//         if (1 == myOffsets.size())
-//         {
-//             // we are a single edge, calculate cuts with edges coming from above/below
-//             // to detect the line start/end extensions
-//             const OffsetPair& myOffset(myOffsets[0]);
-//             double mfExtendStart(0.0);
-//             double mfExtendEnd(0.0);
-
-//             // for start: get cuts with all left target styles and use the minimum
-//             mfExtendStart = getSimpleExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffset, rLFromT, rLFromB, true, fLength);
-
-//             // for end: get cuts with all right target styles and use the maximum
-//             mfExtendEnd = getSimpleExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffset, rRFromT, rRFromB, false, fLength);
-
-//             rTarget.append(
-//                 drawinglayer::primitive2d::Primitive2DReference(
-//                     new drawinglayer::primitive2d::BorderLinePrimitive2D(
-//                         aStart,
-//                         aEnd,
-//                         drawinglayer::primitive2d::BorderLine(
-//                             rBorder.Prim(),
-//                             (pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(),
-//                             drawinglayer::primitive2d::BorderLineExtend(
-//                                 mfExtendStart,
-//                                 mfExtendEnd)),
-//                         rBorder.Type(),
-//                         rBorder.PatternScale())));
-//         }
-//         else if (2 == myOffsets.size())
-//         {
-//             // we are a double edge, calculate cuts with edges coming from above/below
-//             // for both edges to detect the line start/end extensions. In the future this
-//             // needs to be extended to use two values per extension, getComplexExtendedLineValues
-//             // internally prepares these already. drawinglayer::primitive2d::BorderLine will
-//             // then need to take these double entries (maybe a pair) and use them internally.
-//             double mfExtendLeftStart(0.0);
-//             double mfExtendLeftEnd(0.0);
-//             double mfExtendRightStart(0.0);
-//             double mfExtendRightEnd(0.0);
-
-//             // for start of first edge, get cuts with left targets. Start with upper and take maximum when
-//             // cut exists. Else use lower and take minimum when cut exists
-//             mfExtendLeftStart = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[0], rLFromT, rLFromB, true, fLength);
-
-//             // for end of first edge, get cuts with right targets. Start with upper and take minimum when
-//             // cut exists. Else use lower and take maximum when cut exists
-//             mfExtendLeftEnd = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[0], rRFromT, rRFromB, false, fLength);
-
-//             // for start of second edge, get cuts with left targets. Start with lower and take maximum when
-//             // cut exists. Else use upper and take minimum when cut exists
-//             mfExtendRightStart = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[1], rLFromB, rLFromT, true, fLength);
-
-//             // for end of second edge, get cuts with right targets. Start with lower and take minimum when
-//             // cut exists. Else use upper and take maximum when cut exists
-//             mfExtendRightEnd = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[1], rRFromB, rRFromT, false, fLength);
-
-//             // needs to be determined in detail later, for now use the max prolongation
-//             // from left/right, but do not less than half (0.0). This works decently,
-//             // but not perfect (see Writer, use three-color-style, look at upper/lower#
-//             // connections)
-//             const double fGapLeft(std::max(0.0, std::max(mfExtendLeftStart, mfExtendRightStart)));
-//             const double fGapRight(std::max(0.0, std::max(mfExtendLeftEnd, mfExtendRightEnd)));
-
-//             rTarget.append(
-//                 drawinglayer::primitive2d::Primitive2DReference(
-//                     new drawinglayer::primitive2d::BorderLinePrimitive2D(
-//                         aStart,
-//                         aEnd,
-//                         drawinglayer::primitive2d::BorderLine(
-//                             rBorder.Prim(),
-//                             (pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(),
-//                             drawinglayer::primitive2d::BorderLineExtend(
-//                                 mfExtendLeftStart,
-//                                 mfExtendLeftEnd)),
-//                         drawinglayer::primitive2d::BorderLine(
-//                             rBorder.Dist(),
-//                             (pForceColor ? *pForceColor : rBorder.GetColorGap()).getBColor(),
-//                             drawinglayer::primitive2d::BorderLineExtend(
-//                                 fGapLeft,
-//                                 fGapRight)),
-//                         drawinglayer::primitive2d::BorderLine(
-//                             rBorder.Secn(),
-//                             (pForceColor ? *pForceColor : rBorder.GetColorSecn()).getBColor(),
-//                             drawinglayer::primitive2d::BorderLineExtend(
-//                                 mfExtendRightStart,
-//                                 mfExtendRightEnd)),
-//                         rBorder.UseGapColor(),
-//                         rBorder.Type(),
-//                         rBorder.PatternScale())));
-//         }
-//     }
-// }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-struct OffsetWidthColor
+struct OffsetAndHalfWidthAndColor
 {
     double          mfOffset;
-    double          mfWidth;
+    double          mfHalfWidth;
     Color           maColor;
 
-    OffsetWidthColor(double offset, double width, Color color) :
+    OffsetAndHalfWidthAndColor(double offset, double halfWidth, Color color) :
         mfOffset(offset),
-        mfWidth(width),
+        mfHalfWidth(halfWidth),
         maColor(color)
     {}
 };
@@ -768,7 +379,15 @@ struct CutSet
     double          mfORMR;
 };
 
-void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthColor >& offsets)
+struct ExtendSet
+{
+    double          mfExtLeft;
+    double          mfExtRight;
+
+    ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
+};
+
+void getOffsetAndHalfWidthAndColorFromStyle(const Style& rStyle, const Color* pForceColor, std::vector< OffsetAndHalfWidthAndColor >& offsets)
 {
     if (rStyle.IsUsed())
     {
@@ -794,24 +413,36 @@ void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthC
         if (rStyle.Dist() && rStyle.Secn())
         {
             // both or all three lines used
-            const double a(fRefModeOffset - (rStyle.GetWidth() * 0.5));
-            const double b(a + rStyle.Prim());
-            const double c(b + rStyle.Dist());
-            const double d(c + rStyle.Secn());
-
-            if(0xff != rStyle.GetColorPrim().GetTransparency())
-            {
-                offsets.push_back(OffsetWidthColor((a + b) * 0.5, rStyle.Prim(), rStyle.GetColorPrim()));
-            }
-
-            if(0xff != rStyle.GetColorGap().GetTransparency() && rStyle.UseGapColor())
-            {
-                offsets.push_back(OffsetWidthColor((b + c) * 0.5, rStyle.Dist(), rStyle.GetColorGap()));
-            }
+            const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
+            const bool bDistTransparent(!rStyle.UseGapColor() || 0xff == rStyle.GetColorGap().GetTransparency());
+            const bool bSecnTransparent(0xff == rStyle.GetColorSecn().GetTransparency());
 
-            if(0xff != rStyle.GetColorSecn().GetTransparency())
+            if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
             {
-                offsets.push_back(OffsetWidthColor((c + d) * 0.5, rStyle.Secn(), rStyle.GetColorSecn()));
+                const double a(fRefModeOffset - (rStyle.GetWidth() * 0.5));
+                const double b(a + rStyle.Prim());
+                const double c(b + rStyle.Dist());
+                const double d(c + rStyle.Secn());
+
+                offsets.push_back(
+                    OffsetAndHalfWidthAndColor(
+                        (a + b) * 0.5,
+                        rStyle.Prim() * 0.5,
+                        nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim()));
+
+                offsets.push_back(
+                    OffsetAndHalfWidthAndColor(
+                        (b + c) * 0.5,
+                        rStyle.Dist() * 0.5,
+                        rStyle.UseGapColor()
+                            ? (nullptr != pForceColor ? *pForceColor : rStyle.GetColorGap())
+                            : Color(COL_TRANSPARENT)));
+
+                offsets.push_back(
+                    OffsetAndHalfWidthAndColor(
+                        (c + d) * 0.5,
+                        rStyle.Secn() * 0.5,
+                        nullptr != pForceColor ? *pForceColor : rStyle.GetColorSecn()));
             }
         }
         else
@@ -819,69 +450,109 @@ void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthC
             // one line used, push two values, from outer to inner
             if(0xff != rStyle.GetColorPrim().GetTransparency())
             {
-                offsets.push_back(OffsetWidthColor(fRefModeOffset, rStyle.Prim(), rStyle.GetColorPrim()));
+                offsets.push_back(
+                    OffsetAndHalfWidthAndColor(
+                        fRefModeOffset,
+                        rStyle.Prim() * 0.5,
+                        nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim()));
             }
         }
     }
 }
 
-void findCutsWithStyleVectorTable(
-    std::vector< CutSet >& rCutSet,
-    const basegfx::B2DPoint& rOrigin,
+void getCutSet(
+    CutSet& rCutSet,
+    const basegfx::B2DPoint& rLeft,
+    const basegfx::B2DPoint& rRight,
     const basegfx::B2DVector& rX,
-    double fOffset,
-    double fHalfWidth,
-    const StyleVectorTable& rStyleVectorTable)
+    const basegfx::B2DPoint& rOtherLeft,
+    const basegfx::B2DPoint& rOtherRight,
+    const basegfx::B2DVector& rOtherX)
 {
-    const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX));
-    basegfx::B2DPoint aMyLeft(rOrigin + (aY * (fOffset - fHalfWidth)));
-    basegfx::B2DPoint aMyRight(rOrigin + (aY * (fOffset + fHalfWidth)));
+    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);
+}
 
-    for(const auto& style : rStyleVectorTable)
+void getExtends(
+    std::vector<ExtendSet>& rExtendSet,                     // target Left/Right values to fill
+    const basegfx::B2DPoint& rOrigin,                       // own vector start
+    const basegfx::B2DVector& rX,                           // own vector direction and length
+    const basegfx::B2DVector& rPerpendX,                     // normalized perpendicular to rX
+    const std::vector< OffsetAndHalfWidthAndColor >& rOffsets,    // own vector derivations
+    const StyleVectorTable& rStyleVectorTable)              // other vectors emerging in this point
+{
+    if(!rOffsets.empty() && rOffsets.size() == rExtendSet.size())
     {
-        std::vector< OffsetWidthColor > myOffsets;
-        getOffsetWidthColorFromStyle(style.getStyle(), myOffsets);
-        const basegfx::B2DVector aOtherY(basegfx::getNormalizedPerpendicular(style.getB2DVector()));
+        const size_t nOffsets(rOffsets.size());
 
-        for(const auto& offset : myOffsets)
+        for(size_t a(0); a < nOffsets; a++)
         {
-            basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherY * (offset.mfOffset - (offset.mfWidth * 0.5))));
-            basegfx::B2DPoint aOtherRight(rOrigin + (aOtherY * (offset.mfOffset + (offset.mfWidth * 0.5))));
-            CutSet aNewCuts;
-
-            basegfx::tools::findCut(
-                aOtherLeft,
-                style.getB2DVector(),
-                aMyLeft,
-                rX,
-                CutFlagValue::LINE,
-                &aNewCuts.mfOLML);
-
-            basegfx::tools::findCut(
-                aOtherLeft,
-                style.getB2DVector(),
-                aMyRight,
-                rX,
-                CutFlagValue::LINE,
-                &aNewCuts.mfOLMR);
-
-            basegfx::tools::findCut(
-                aOtherRight,
-                style.getB2DVector(),
-                aMyLeft,
-                rX,
-                CutFlagValue::LINE,
-                &aNewCuts.mfORML);
-
-            basegfx::tools::findCut(
-                aOtherRight,
-                style.getB2DVector(),
-                aMyRight,
-                rX,
-                CutFlagValue::LINE,
-                &aNewCuts.mfORMR);
-
-            rCutSet.push_back(aNewCuts);
+            const OffsetAndHalfWidthAndColor& rOffset(rOffsets[a]);
+            ExtendSet& rExt(rExtendSet[a]);
+            bool bExtSet(false);
+            const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (rOffset.mfOffset - rOffset.mfHalfWidth)));
+            const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (rOffset.mfOffset + rOffset.mfHalfWidth)));
+
+            for(const auto& rStyleVectorCombination : rStyleVectorTable)
+            {
+                std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
+                getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, otherOffsets);
+
+                if(!otherOffsets.empty())
+                {
+                    const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector()));
+
+                    for(const auto& rOtherOffset : otherOffsets)
+                    {
+                        const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset - rOtherOffset.mfHalfWidth)));
+                        const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset + rOtherOffset.mfHalfWidth)));
+                        CutSet aCutSet;
+
+                        getCutSet(aCutSet, aLeft, aRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());
+
+                        if(!bExtSet)
+                        {
+                            rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
+                            rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
+                            bExtSet = true;
+                        }
+                        else
+                        {
+                            rExt.mfExtLeft = std::min(rExt.mfExtLeft , std::min(aCutSet.mfOLML, aCutSet.mfORML));
+                            rExt.mfExtRight = std::min(rExt.mfExtRight , std::min(aCutSet.mfOLMR, aCutSet.mfORMR));
+                        }
+                    }
+                }
+            }
         }
     }
 }
@@ -896,79 +567,71 @@ void CreateBorderPrimitives(
     const Color* pForceColor)
 {
     // get offset color pairs for  style, one per visible line
-    std::vector< OffsetWidthColor > myOffsets;
-    getOffsetWidthColorFromStyle(rBorder, myOffsets);
+    std::vector< OffsetAndHalfWidthAndColor > myOffsets;
+    getOffsetAndHalfWidthAndColorFromStyle(rBorder, pForceColor, myOffsets);
+    const size_t nOffsets(myOffsets.size());
 
-    if(!myOffsets.empty())
+    if(nOffsets)
     {
         const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
         const bool bHasStartStyles(!rStartStyleVectorTable.empty());
         const bool bHasEndStyles(!rEndStyleVectorTable.empty());
+        std::vector<ExtendSet> aExtendSetStart(nOffsets);
+        std::vector<ExtendSet> aExtendSetEnd(nOffsets);
 
-        if(bHasStartStyles || bHasEndStyles)
+        if(bHasStartStyles)
         {
-            // we have start/end styles, get offset values
-            double fExtStartLeft(0.0);
-            double fExtStartRight(0.0);
-            double fExtEndLeft(0.0);
-            double fExtEndRight(0.0);
+            // create extends for line starts, use given point/vector and offsets
+            getExtends(aExtendSetStart, rOrigin, rX, aPerpendX, myOffsets, rStartStyleVectorTable);
+        }
 
-            for(const auto& offset : myOffsets)
-            {
-                const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset));
-                const basegfx::B2DPoint aEnd(aStart + rX);
+        if(bHasEndStyles)
+        {
+            // create extends for line ends, use inverse point/vector and inverse offsets
+            std::reverse(myOffsets.begin(), myOffsets.end());
+            getExtends(aExtendSetEnd, rOrigin + rX, -rX, -aPerpendX, myOffsets, rEndStyleVectorTable);
+        }
 
-                if(bHasStartStyles)
-                {
-                    // create extends for line starts
-                    std::vector< CutSet > aStartCutSet;
-                    findCutsWithStyleVectorTable(aStartCutSet, rOrigin, rX, offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
-                }
+        std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
+        const double fNegLength(-rX.getLength());
 
-                if(bHasEndStyles)
-                {
-                    // create extends for line ends
-                    std::vector< CutSet > aEndCutSet;
-                    findCutsWithStyleVectorTable(aEndCutSet, rOrigin + rX, -rX, -offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
-                }
+        for(size_t a(0); a < nOffsets; a++)
+        {
+            const OffsetAndHalfWidthAndColor& rOffset(myOffsets[a]);
+            const ExtendSet& rExtStart(aExtendSetStart[a]);
+            const ExtendSet& rExtEnd(aExtendSetEnd[a]);
 
-                rTarget.append(
-                    drawinglayer::primitive2d::Primitive2DReference(
-                        new drawinglayer::primitive2d::BorderLinePrimitive2D(
-                            aStart,
-                            aEnd,
-                            drawinglayer::primitive2d::BorderLine(
-                                offset.mfWidth,
-                                (pForceColor ? *pForceColor : offset.maColor).getBColor(),
-                                drawinglayer::primitive2d::BorderLineExtend(
-                                    fExtStartLeft,
-                                    fExtStartRight,
-                                    fExtEndLeft,
-                                    fExtEndRight)),
-                            rBorder.Type(),
-                            rBorder.PatternScale())));
+            if(0xff == rOffset.maColor.GetTransparency())
+            {
+                aBorderlines.push_back(
+                    drawinglayer::primitive2d::BorderLine(
+                        rOffset.mfHalfWidth * 2.0));
             }
-        }
-        else
-        {
-            // no start/end styles, just create simple BorderLinePrimitive2D
-            // for each local partial line
-            for(const auto& offset : myOffsets)
+            else
             {
-                const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset));
-                const basegfx::B2DPoint aEnd(aStart + rX);
-                rTarget.append(
-                    drawinglayer::primitive2d::Primitive2DReference(
-                        new drawinglayer::primitive2d::BorderLinePrimitive2D(
-                            aStart,
-                            aEnd,
-                            drawinglayer::primitive2d::BorderLine(
-                                offset.mfWidth,
-                                (pForceColor ? *pForceColor : offset.maColor).getBColor()),
-                            rBorder.Type(),
-                            rBorder.PatternScale())));
+                aBorderlines.push_back(
+                    drawinglayer::primitive2d::BorderLine(
+                        drawinglayer::attribute::LineAttribute(
+                            rOffset.maColor.getBColor(),
+                            rOffset.mfHalfWidth * 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);
+
+        rTarget.append(
+            drawinglayer::primitive2d::Primitive2DReference(
+                new drawinglayer::primitive2d::BorderLinePrimitive2D(
+                    rOrigin,
+                    rOrigin + rX,
+                    aBorderlines,
+                    aStrokeAttribute)));
     }
 }
 
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index f8897b7c0a77..6052c23f3e8a 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -85,7 +85,7 @@ typedef std::vector< Cell >     CellVec;
 
 size_t Cell::GetCellIndex(const Array& rArray) const
 {
-    if(-1 == maCellIndex)
+    if(static_cast<size_t>(-1) == maCellIndex)
     {
         rArray.AddCellIndices();
     }
@@ -102,7 +102,7 @@ basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray) const
 
     const size_t nCellIndex(GetCellIndex(rArray));
 
-    if(-1 != nCellIndex)
+    if(static_cast<size_t>(-1) != nCellIndex)
     {
         const basegfx::B2DRange aRange(rArray.GetCellRange(nCellIndex));
 
@@ -976,7 +976,7 @@ void HelperCreateHorizontalEntry(
 
     CreateBorderPrimitives(
         rSequence,
-        bUpper ? rOrigin : rOrigin + rY,
+        bUpper ? rOrigin : basegfx::B2DPoint(rOrigin + rY),
         rX,
         rStyle,
         aStart,
@@ -1021,7 +1021,7 @@ void HelperCreateVerticalEntry(
 
     CreateBorderPrimitives(
         rSequence,
-        bLeft ? rOrigin : rOrigin + rX,
+        bLeft ? rOrigin : basegfx::B2DPoint(rOrigin + rX),
         rY,
         rStyle,
         aStart,
@@ -1038,7 +1038,7 @@ void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::p
     {
         const size_t nCellIndex(pCell->GetCellIndex(rArray));
 
-        if(-1 != nCellIndex)
+        if(static_cast<size_t>(-1) != nCellIndex)
         {
             size_t col(nCellIndex % rArray.GetColCount());
             size_t row(nCellIndex / rArray.GetColCount());
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 74eb8e34d70b..9d1928d2bf76 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -111,7 +111,6 @@ using namespace ::editeng;
 using namespace ::com::sun::star;
 using ::drawinglayer::primitive2d::BorderLinePrimitive2D;
 using ::drawinglayer::primitive2d::BorderLine;
-using ::drawinglayer::primitive2d::BorderLineExtend;
 using std::pair;
 using std::make_pair;
 
@@ -519,56 +518,37 @@ lcl_MergeBorderLines(
     basegfx::B2DPoint const& rStart,
     basegfx::B2DPoint const& rEnd)
 {
-    const BorderLine& rLineLeft = rLine.getBorderLines()[0];
-    const BorderLine& rOtherLeft(rOther.getBorderLines()[0]);
-
-    if (1 == rLine.getBorderLines().size())
-    {
-        return new BorderLinePrimitive2D(
-            rStart,
-            rEnd,
-            BorderLine(
-                rLineLeft.getWidth(),
-                rLineLeft.getRGBColor(),
-                BorderLineExtend(
-                    rLineLeft.getBorderLineExtend().getStartLeft(),
-                    rLineLeft.getBorderLineExtend().getStartRight(),
-                    rOtherLeft.getBorderLineExtend().getEndLeft(),
-                    rOtherLeft.getBorderLineExtend().getEndRight())),
-            rLine.getStyle());
-    }
-    else
+    const std::vector< BorderLine >& rLineLeft(rLine.getBorderLines());
+    const std::vector< BorderLine >& rOtherLeft(rOther.getBorderLines());
+    const size_t aSize(std::min(rLineLeft.size(), rOtherLeft.size()));
+    std::vector< BorderLine > aNew;
+
+    for(size_t a(0); a < aSize; a++)
     {
-        const BorderLine& rLineGap(rLine.getBorderLines()[1]);
-        // const BorderLine& rOtherGap(rOther.getBorderLines()[1]);
-        const BorderLine& rLineRight(rLine.getBorderLines()[2]);
-        const BorderLine& rOtherRight(rOther.getBorderLines()[2]);
-
-        return new BorderLinePrimitive2D(
-            rStart,
-            rEnd,
-            BorderLine(
-                rLineLeft.getWidth(),
-                rLineLeft.getRGBColor(),
-                BorderLineExtend(
-                    rLineLeft.getBorderLineExtend().getStartLeft(),
-                    rLineLeft.getBorderLineExtend().getStartRight(),
-                    rOtherLeft.getBorderLineExtend().getEndLeft(),
-                    rOtherLeft.getBorderLineExtend().getEndRight())),
-            BorderLine(
-                rLineGap.getWidth(),
-                rLineGap.getRGBColor()),
-            BorderLine(
-                rLineRight.getWidth(),
-                rLineRight.getRGBColor(),
-                BorderLineExtend(
-                    rLineRight.getBorderLineExtend().getStartLeft(),
-                    rLineRight.getBorderLineExtend().getStartRight(),
-                    rOtherRight.getBorderLineExtend().getEndLeft(),
-                    rOtherRight.getBorderLineExtend().getEndRight())),
-            rLine.hasGapColor(),
-            rLine.getStyle());
+        const BorderLine& la(rLineLeft[a]);
+        const BorderLine& lb(rOtherLeft[a]);
+
+        if(la.isGap() || lb.isGap())
+        {
+            aNew.push_back(la);
+        }
+        else
+        {
+            aNew.push_back(
+                BorderLine(
+                    la.getLineAttribute(),
+                    la.getStartLeft(),
+                    la.getStartRight(),
+                    lb.getEndLeft(),
+                    lb.getEndRight()));
+        }
     }
+
+    return new BorderLinePrimitive2D(
+        rStart,
+        rEnd,
+        aNew,
+        rLine.getStrokeAttribute());
 }
 
 /**
@@ -601,36 +581,24 @@ lcl_TryMergeBorderLine(BorderLinePrimitive2D const& rThis,
     double otherWidth  = rOther.getEnd().getX() -  rOther.getStart().getX();
 
     // check for same orientation, same line width, same style and matching colors
-    bool bSameStuff(false);
-    const BorderLine& rThisLeft(rThis.getBorderLines()[0]);
-    const BorderLine& rOtherLeft(rOther.getBorderLines()[0]);
+    bool bSameStuff(
+        ((thisHeight > thisWidth) == (otherHeight > otherWidth))
+        && rThis.getStrokeAttribute() == rOther.getStrokeAttribute());
 
-    if (1 == rThis.getBorderLines().size())
-    {
-        bSameStuff = ((thisHeight > thisWidth) == (otherHeight > otherWidth))
-            && (rtl::math::approxEqual(rThisLeft.getWidth(), rOtherLeft.getWidth()))
-            && (rThis.getStyle() == rOther.getStyle())
-            && (rThisLeft.getRGBColor() == rOtherLeft.getRGBColor());
-    }
-    else
+    if(bSameStuff)
     {
-        const BorderLine& rThisGap(rThis.getBorderLines()[1]);
-        const BorderLine& rOtherGap(rOther.getBorderLines()[1]);
-        const BorderLine& rThisRight(rThis.getBorderLines()[2]);
-        const BorderLine& rOtherRight(rOther.getBorderLines()[2]);
+        const std::vector< BorderLine >& rLineLeft(rThis.getBorderLines());
+        const std::vector< BorderLine >& rOtherLeft(rOther.getBorderLines());
+        const size_t aSize(std::min(rLineLeft.size(), rOtherLeft.size()));
 
-        bSameStuff = ((thisHeight > thisWidth) == (otherHeight > otherWidth))
-            && (rtl::math::approxEqual(rThisLeft.getWidth(), rOtherLeft.getWidth()))
-            && (rtl::math::approxEqual(rThisGap.getWidth(), rOtherGap.getWidth()))
-            && (rtl::math::approxEqual(rThisRight.getWidth(), rOtherRight.getWidth()))
-            && (rThis.getStyle() == rOther.getStyle())
-            && (rThisLeft.getRGBColor() == rOtherLeft.getRGBColor())
-            && (rThisRight.getRGBColor() == rOtherRight.getRGBColor())
-            && (rThis.hasGapColor() == rOther.hasGapColor())
-            && (!rThis.hasGapColor() ||
-            (rThisGap.getRGBColor() == rOtherGap.getRGBColor()));
-    }
+        for(size_t a(0); bSameStuff && a < aSize; a++)
+        {
+            const BorderLine& la(rLineLeft[a]);
+            const BorderLine& lb(rOtherLeft[a]);
 
+            bSameStuff = la == lb;
+        }
+    }
 
     if (bSameStuff)
     {
@@ -4894,45 +4862,44 @@ static void lcl_MakeBorderLine(SwRect const& rRect,
     double const nRightWidth = rBorder.GetInWidth();
     Color const aLeftColor = rBorder.GetColorOut(isLeftOrTopBorder);
     Color const aRightColor = rBorder.GetColorIn(isLeftOrTopBorder);
+    const std::vector<double> aDashing(svtools::GetLineDashing(rBorder.GetBorderLineStyle(), 10.0));
+    const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
+    std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
 
-    rtl::Reference<BorderLinePrimitive2D> xLine;
-
-    if (basegfx::fTools::equalZero(nRightWidth))
-    {
-        xLine = new BorderLinePrimitive2D(
-            aStart,
-            aEnd,
-            BorderLine(
-                nLeftWidth,
+    aBorderlines.push_back(
+        drawinglayer::primitive2d::BorderLine(
+            drawinglayer::attribute::LineAttribute(
                 aLeftColor.getBColor(),
-                BorderLineExtend(
-                    nExtentLeftStart,
-                    nExtentLeftEnd)),
-            rBorder.GetBorderLineStyle());
-    }
-    else
-    {
-        xLine = new BorderLinePrimitive2D(
+                nLeftWidth),
+            nExtentLeftStart,
+            nExtentLeftStart,
+            nExtentLeftEnd,
+            nExtentLeftEnd));
+
+    if (!basegfx::fTools::equalZero(nRightWidth))
+    {
+        drawinglayer::primitive2d::BorderLine(
+            drawinglayer::attribute::LineAttribute(
+                rBorder.GetColorGap().getBColor(),
+                rBorder.GetDistance()));
+
+        aBorderlines.push_back(
+            drawinglayer::primitive2d::BorderLine(
+                drawinglayer::attribute::LineAttribute(
+                    aRightColor.getBColor(),
+                    nRightWidth),
+                nExtentRightStart,
+                nExtentRightStart,
+                nExtentRightEnd,
+                nExtentRightEnd));
+    }
+
+    rtl::Reference<BorderLinePrimitive2D> xLine(
+        new BorderLinePrimitive2D(
             aStart,
             aEnd,
-            BorderLine(
-                nLeftWidth,
-                aLeftColor.getBColor(),
-                BorderLineExtend(
-                    nExtentLeftStart,
-                    nExtentLeftEnd)),
-            BorderLine(
-                rBorder.GetDistance(),
-                rBorder.GetColorGap().getBColor()),
-            BorderLine(
-                nRightWidth,
-                aRightColor.getBColor(),
-                BorderLineExtend(
-                    nExtentRightStart,
-                    nExtentRightEnd)),
-            rBorder.HasGapColor(),
-            rBorder.GetBorderLineStyle());
-    }
+            aBorderlines,
+            aStrokeAttribute));
 
     properties.pBLines->AddBorderLine(xLine.get(), properties);
 }


More information about the Libreoffice-commits mailing list