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 194c86a..fa2f715 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 a070f9c..e56a40d 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 47da04a..9421ed8 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -37,128 +37,29 @@ 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
        {
            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
        {
            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
        {
            if (mfExtends.empty())
                return 0.0;
            if (2 == mfExtends.size())
                return mfExtends[0];
            return (mfExtends[0] + mfExtends[1]) * 0.5;
        }

        double BorderLineExtend::getEndAverage() const
        {
            if (mfExtends.empty())
                return 0.0;
            if (2 == mfExtends.size())
                return mfExtends[1];
            return (mfExtends[2] + mfExtends[3]) * 0.5;
        }

        bool BorderLineExtend::operator==(const BorderLineExtend& rBorderLineExtend) const
        {
            if (mfExtends.size() == rBorderLineExtend.mfExtends.size())
            {
                return mfExtends == rBorderLineExtend.mfExtends;
            }

            return false;
        }

        BorderLine::BorderLine(
            double fWidth,
            const basegfx::BColor& rRGBColor,
            const BorderLineExtend& rBorderLineExtend)
            : mfWidth(fWidth),
            maRGBColor(rRGBColor),
            maBorderLineExtend(rBorderLineExtend)
        :   maLineAttribute(rLineAttribute),
            mfStartLeft(fStartLeft),
            mfStartRight(fStartRight),
            mfEndLeft(fEndLeft),
            mfEndRight(fEndRight),
            mbIsGap(false)
        {
        }

        BorderLine::BorderLine(
            double fWidth,
            const basegfx::BColor& rRGBColor)
            : mfWidth(fWidth),
            maRGBColor(rRGBColor),
            maBorderLineExtend()
            double fWidth)
        :   maLineAttribute(basegfx::BColor(), fWidth),
            mfStartLeft(0.0),
            mfStartRight(0.0),
            mfEndLeft(0.0),
            mfEndRight(0.0),
            mbIsGap(true)
        {
        }

@@ -168,9 +69,24 @@ namespace drawinglayer

        bool BorderLine::operator==(const BorderLine& rBorderLine) const
        {
            return getWidth() == rBorderLine.getWidth()
                && getRGBColor() == rBorderLine.getRGBColor()
                && getBorderLineExtend() == rBorderLine.getBorderLineExtend();
            return getLineAttribute() == rBorderLine.getLineAttribute()
                && getStartLeft() == rBorderLine.getStartLeft()
                && getStartRight() == rBorderLine.getStartRight()
                && getEndLeft() == rBorderLine.getEndLeft()
                && getEndRight() == rBorderLine.getEndRight()
                && isGap() == rBorderLine.isGap();
        }

        double BorderLine::getAdaptedWidth(double fMinWidth) const
        {
            if(isGap())
            {
                return std::max(getLineAttribute().getWidth(), fMinWidth);
            }
            else
            {
                return getLineAttribute().getWidth();
            }
        }

        // 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)
            const std::vector< BorderLine >& rBorderLines,
            const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute)
        :   BufferedDecompositionPrimitive2D(),
            maStart(rStart),
            maEnd(rEnd),
            maBorderLines(),
            mbHasGapColor(false),
            mnStyle(nStyle),
            mfPatternScale(fPatternScale),
            mfDiscreteGapDistance(0.0)
            maBorderLines(rBorderLines),
            maStrokeAttribute(rStrokeAttribute),
            mfSmallestAllowedDiscreteGapDistance(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)
        :   BufferedDecompositionPrimitive2D(),
            maStart(rStart),
            maEnd(rEnd),
            maBorderLines(),
            mbHasGapColor(bHasGapColor),
            mnStyle(nStyle),
            mfPatternScale(fPatternScale),
            mfDiscreteGapDistance(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())));
                // Line with potential gap. In this case, we want to be view-dependent.
                // get the smallest gap
                double fSmallestGap(0.0);

                // 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))
                if(getSmallestGap(fSmallestGap))
                {
                    if (!getBuffered2DDecomposition().empty())
                    {
                        // conditions of last local decomposition have changed, delete
                        const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
                    }
                    // 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())));

                    // remember value for usage in create2DDecomposition
                    const_cast< BorderLinePrimitive2D* >(this)->mfDiscreteGapDistance = fNewDiscreteDistance;
                    // 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))
                    {
                        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)->mfSmallestAllowedDiscreteGapDistance = fNewDiscreteDistance;
                    }
                }
            }

diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
index ad28a5e..992347c 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 4869535..ca66b28 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());
            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.GetColorPrim().GetTransparency())
            if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
            {
                offsets.push_back(OffsetWidthColor((a + b) * 0.5, rStyle.Prim(), rStyle.GetColorPrim()));
            }
                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.GetColorGap().GetTransparency() && rStyle.UseGapColor())
            {
                offsets.push_back(OffsetWidthColor((b + c) * 0.5, rStyle.Dist(), rStyle.GetColorGap()));
            }
                offsets.push_back(
                    OffsetAndHalfWidthAndColor(
                        (a + b) * 0.5,
                        rStyle.Prim() * 0.5,
                        nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim()));

            if(0xff != rStyle.GetColorSecn().GetTransparency())
            {
                offsets.push_back(OffsetWidthColor((c + d) * 0.5, rStyle.Secn(), rStyle.GetColorSecn()));
                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);

    for(const auto& style : rStyleVectorTable)
    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 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;
            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)));

            basegfx::tools::findCut(
                aOtherLeft,
                style.getB2DVector(),
                aMyLeft,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfOLML);
            for(const auto& rStyleVectorCombination : rStyleVectorTable)
            {
                std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
                getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, otherOffsets);

            basegfx::tools::findCut(
                aOtherLeft,
                style.getB2DVector(),
                aMyRight,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfOLMR);
                if(!otherOffsets.empty())
                {
                    const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector()));

            basegfx::tools::findCut(
                aOtherRight,
                style.getB2DVector(),
                aMyLeft,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfORML);
                    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;

            basegfx::tools::findCut(
                aOtherRight,
                style.getB2DVector(),
                aMyRight,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfORMR);
                        getCutSet(aCutSet, aLeft, aRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());

            rCutSet.push_back(aNewCuts);
                        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)
        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);
        }

        std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
        const double fNegLength(-rX.getLength());

        for(size_t a(0); a < nOffsets; a++)
        {
            const OffsetAndHalfWidthAndColor& rOffset(myOffsets[a]);
            const ExtendSet& rExtStart(aExtendSetStart[a]);
            const ExtendSet& rExtEnd(aExtendSetEnd[a]);

            if(0xff == rOffset.maColor.GetTransparency())
            {
                const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset));
                const basegfx::B2DPoint aEnd(aStart + rX);

                if(bHasStartStyles)
                {
                    // create extends for line starts
                    std::vector< CutSet > aStartCutSet;
                    findCutsWithStyleVectorTable(aStartCutSet, rOrigin, rX, offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
                }

                if(bHasEndStyles)
                {
                    // create extends for line ends
                    std::vector< CutSet > aEndCutSet;
                    findCutsWithStyleVectorTable(aEndCutSet, rOrigin + rX, -rX, -offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
                }

                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())));
                aBorderlines.push_back(
                    drawinglayer::primitive2d::BorderLine(
                        rOffset.mfHalfWidth * 2.0));
            }
            else
            {
                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));
            }
        }
        else
        {
            // no start/end styles, just create simple BorderLinePrimitive2D
            // for each local partial line
            for(const auto& offset : myOffsets)
            {
                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())));
            }
        }

        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 f8897b7..6052c23 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 63b5064..ac2d3ba 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]);
    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;

    if (1 == rLine.getBorderLines().size())
    for(size_t a(0); a < aSize; a++)
    {
        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 BorderLine& rLineGap(rLine.getBorderLines()[1]);
        // const BorderLine& rOtherGap(rOther.getBorderLines()[1]);
        const BorderLine& rLineRight(rLine.getBorderLines()[2]);
        const BorderLine& rOtherRight(rOther.getBorderLines()[2]);
        const BorderLine& la(rLineLeft[a]);
        const BorderLine& lb(rOtherLeft[a]);

        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());
        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())
    if(bSameStuff)
    {
        bSameStuff = ((thisHeight > thisWidth) == (otherHeight > otherWidth))
            && (rtl::math::approxEqual(rThisLeft.getWidth(), rOtherLeft.getWidth()))
            && (rThis.getStyle() == rOther.getStyle())
            && (rThisLeft.getRGBColor() == rOtherLeft.getRGBColor());
    }
    else
    {
        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;
    aBorderlines.push_back(
        drawinglayer::primitive2d::BorderLine(
            drawinglayer::attribute::LineAttribute(
                aLeftColor.getBColor(),
                nLeftWidth),
            nExtentLeftStart,
            nExtentLeftStart,
            nExtentLeftEnd,
            nExtentLeftEnd));

    if (basegfx::fTools::equalZero(nRightWidth))
    if (!basegfx::fTools::equalZero(nRightWidth))
    {
        xLine = new BorderLinePrimitive2D(
        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)),
            rBorder.GetBorderLineStyle());
    }
    else
    {
        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);
}