borderline: Adapt ViewContactOfTableObj

Adapted to usage of svx::frame::Style helpers for primitive
creation, need much less SvxBorderLine classes and less
overhead. Class SdrBorderlinePrimitive2D completely removed.
Working on Array::DrawRange to get it using the Coodinate
Systems which are available and include the rotation.
Solved problems in BorderLinePrimitive creation in DrawRange
and DrawArray by completely restucturing these. Also changed
to now return a sequence of primitives to the caller instead
of handing over a primitive renderer and using it for each
single primitve. This is a preparation for later buffering
these and not re-create for each paint.
Have now a working version that uses the Cell used by the Style
and creates all info on the fly, so that the correct coordinate
systems will be used. Works in Calc and it's dialogs with
one or multiple cells.
diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index b2e0da9..9ebb4c8 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -123,7 +123,6 @@ private:
        double              mfSecn;     /// Width of secondary (right or bottom) line.
        double              mfPatternScale; /// Scale used for line pattern spacing.
        SvxBorderLineStyle  mnType;
        const Cell*         mpUsingCell;

    public:
        /** Constructs an invisible frame style. */
@@ -137,21 +136,24 @@ private:
            mfDist(0.0),
            mfSecn(0.0),
            mfPatternScale(1.0),
            mnType(SvxBorderLineStyle::SOLID),
            mpUsingCell(nullptr)
            mnType(SvxBorderLineStyle::SOLID)
        {}
    };

    /// the impl class holding the data
    std::shared_ptr< implStyle >        maImplStyle;

    /// pointer to Cell using this style. Not member of the
    /// impl class since multiple Cells may use the same style
    const Cell*                         mpUsingCell;

    /// call to set maImplStyle on demand
    void implEnsureImplStyle();

    /// need information which cell this style info comes from due to needed
    /// rotation info (which is in the cell). Rotation depends on the cell.
    friend class Cell;
    void SetUsingCell(const Cell* pCell);
    void SetUsingCell(const Cell* pCell) { mpUsingCell = pCell; }

public:
    /** Constructs an invisible frame style. */
@@ -160,7 +162,7 @@ public:
    explicit Style( double nP, double nD, double nS, SvxBorderLineStyle nType );
    /** Constructs a frame style with passed color and line widths. */
    explicit Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType );
    /** Constructs a frame style from the passed SvxBorderLine struct. Clears the style, if pBorder is 0. */
    /** Constructs a frame style from the passed SvxBorderLine struct. */
    explicit Style( const editeng::SvxBorderLine* pBorder, double fScale = 1.0 );

    RefMode GetRefMode() const { if(!maImplStyle) return RefMode::Centered; return maImplStyle->meRefMode; }
@@ -171,7 +173,7 @@ public:
    double Prim() const { if(!maImplStyle) return 0.0; return maImplStyle->mfPrim; }
    double Dist() const { if(!maImplStyle) return 0.0; return maImplStyle->mfDist; }
    double Secn() const { if(!maImplStyle) return 0.0; return maImplStyle->mfSecn; }
    double PatternScale() const { if(!maImplStyle) return 0.0; return maImplStyle->mfPatternScale;}
    double PatternScale() const { if(!maImplStyle) return 1.0; return maImplStyle->mfPatternScale;}
    void SetPatternScale( double fScale );
    SvxBorderLineStyle Type() const { if(!maImplStyle) return SvxBorderLineStyle::SOLID; return maImplStyle->mnType; }

@@ -188,9 +190,7 @@ public:
    void Set( double nP, double nD, double nS );
    /** Sets the frame style to the passed line widths. */
    void Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS );
    /** Sets the frame style to the passed SvxBorderLine struct. */
    void Set( const editeng::SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWidth = SAL_MAX_UINT16 );
    /** Sets the frame style to the passed SvxBorderLine struct. Clears the style, if pBorder is 0. */
    /** Sets the frame style to the passed SvxBorderLine struct. If nullptr, resets the style */
    void Set( const editeng::SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth = SAL_MAX_UINT16 );

    /** Sets a new reference point handling mode, does not modify other settings. */
@@ -205,12 +205,13 @@ public:
    Style& MirrorSelf();

    /** return the Cell using this style (if set) */
    const Cell* GetUsingCell() const;
    const Cell* GetUsingCell() const { return mpUsingCell; }

    bool operator==( const Style& rOther) const;
    bool operator<( const Style& rOther) const;
};

bool operator==( const Style& rL, const Style& rR );
SVX_DLLPUBLIC bool operator<( const Style& rL, const Style& rR );
inline bool operator>( const Style& rL, const Style& rR ) { return rR < rL; }
inline bool operator>( const Style& rL, const Style& rR ) { return rR.operator<(rL); }

// Various helper functions

@@ -258,66 +259,6 @@ SVX_DLLPUBLIC bool CheckFrameBorderConnectable(

// Drawing functions


/** Draws a horizontal frame border, regards all connected frame styles.

    The frame style to draw is passed as parameter rBorder. The function
    calculates the adjustment in X direction for left and right end of primary
    and secondary line of the frame border (the style may present a double
    line). The line ends may differ according to the connected frame styles
    coming from top, bottom, left, right, and/or diagonal.

    Thick frame styles are always drawn centered (in width) to the passed
    reference points. The Y coordinates of both reference points must be equal
    (the line cannot be drawn slanted).

    The function preserves all settings of the passed output device.

    All parameters starting with "rL" refer to the left end of the processed
    frame border, all parameters starting with "rR" refer to the right end.
    The following part of the parameter name starting with "From" specifies
    where the frame border comes from. Example: "rLFromTR" means the frame
    border coming from top-right, connected to the left end of rBorder (and
    therefore a diagonal frame border).

    The following picture shows the meaning of all passed parameters:

                 rLFromT      /                   \      rRFromT
                    |       /                       \       |
                    |   rLFromTR               rRFromTL     |
                    |   /                               \   |
                    | /                                   \ |
    --- rLFromL ---   ============== rBorder ==============   --- rRFromR ---
                    | \                                   / |
                    |   \                               /   |
                    |   rLFromBR               rRFromBL     |
                    |       \                       /       |
                 rLFromB      \                   /      rRFromB
 */
SVX_DLLPUBLIC void CreateBorderPrimitives(
    drawinglayer::primitive2d::Primitive2DContainer&    rTarget,        /// target for created primitives

    const basegfx::B2DPoint&    rOrigin,    /// start point of borderline
    const basegfx::B2DVector&   rX,         /// X-Axis with length
    const basegfx::B2DVector&   rY,         /// Y-Axis for perpendicular, normalized. Does *not* need to be perpendicular, but may express a rotation

    const Style&        rBorder,        /// Style of the processed frame border.

    const Style&        rLFromTR,       /// Diagonal frame border from top-right to left end of rBorder.
    const Style&        rLFromT,        /// Vertical frame border from top to left end of rBorder.
    const Style&        rLFromL,        /// Horizontal frame border from left to left end of rBorder.
    const Style&        rLFromB,        /// Vertical frame border from bottom to left end of rBorder.
    const Style&        rLFromBR,       /// Diagonal frame border from bottom-right to left end of rBorder.

    const Style&        rRFromTL,       /// Diagonal frame border from top-left to right end of rBorder.
    const Style&        rRFromT,        /// Vertical frame border from top to right end of rBorder.
    const Style&        rRFromR,        /// Horizontal frame border from right to right end of rBorder.
    const Style&        rRFromB,        /// Vertical frame border from bottom to right end of rBorder.
    const Style&        rRFromBL,       /// Diagonal frame border from bottom-left to right end of rBorder.

    const Color*        pForceColor     /// If specified, overrides frame border color.
);

class SAL_WARN_UNUSED SVX_DLLPUBLIC StyleVectorCombination
{
private:
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 78b95c8..83b6c28 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -239,7 +239,7 @@ public:
    /** Sets a clipping range.
        @descr
            No cell borders outside of this clipping range will be drawn. In
            difference to simply using the DrawRange() function with the same
            difference to simply using the CreateB2DPrimitiveRange() function with the same
            range, a clipping range causes the drawing functions to completely
            ignore the frame styles connected from outside. This is used i.e.
            in Calc to print single pages and to draw the print preview.
@@ -304,13 +304,13 @@ public:
    /** Draws the part of the specified range, that is inside the clipping range.
        @param pForceColor
            If not NULL, only this color will be used to draw all frame borders. */
    void                DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
                            size_t nFirstCol, size_t nFirstRow,
                            size_t nLastCol, size_t nLastRow,
                            const Color* pForceColor ) const;
    drawinglayer::primitive2d::Primitive2DContainer CreateB2DPrimitiveRange(
        size_t nFirstCol, size_t nFirstRow,
        size_t nLastCol, size_t nLastRow,
        const Color* pForceColor ) const;

    /** Draws the part of the array, that is inside the clipping range. */
    void                DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) const;
    drawinglayer::primitive2d::Primitive2DContainer CreateB2DPrimitiveArray() const;

    // fill the Cell::maCellIndex entries to allow referencing back from Cell to Array Col/Row coordinates
    void AddCellIndices() const;
diff --git a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
index 5123b81..d2a1662 100644
--- a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
+++ b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
@@ -38,16 +38,15 @@
#define PRIMITIVE2D_ID_SDRBLOCKTEXTPRIMITIVE2D          (PRIMITIVE2D_ID_RANGE_SVX| 12)
#define PRIMITIVE2D_ID_SDRSTRETCHTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 13)
#define PRIMITIVE2D_ID_SDRCELLPRIMITIVE2D               (PRIMITIVE2D_ID_RANGE_SVX| 14)
#define PRIMITIVE2D_ID_SDRBORDERLINEPRIMITIVE2D         (PRIMITIVE2D_ID_RANGE_SVX| 15)
#define PRIMITIVE2D_ID_OVERLAYBITMAPEXPRIMITIVE         (PRIMITIVE2D_ID_RANGE_SVX| 16)
#define PRIMITIVE2D_ID_OVERLAYCROSSHAIRPRIMITIVE        (PRIMITIVE2D_ID_RANGE_SVX| 17)
#define PRIMITIVE2D_ID_OVERLAYRECTANGLEPRIMITIVE        (PRIMITIVE2D_ID_RANGE_SVX| 18)
#define PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE  (PRIMITIVE2D_ID_RANGE_SVX| 19)
#define PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE (PRIMITIVE2D_ID_RANGE_SVX| 20)
#define PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D            (PRIMITIVE2D_ID_RANGE_SVX| 21)
#define PRIMITIVE2D_ID_SDROLECONTENTPRIMITIVE2D         (PRIMITIVE2D_ID_RANGE_SVX| 22)
#define PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 23)
#define PRIMITIVE2D_ID_SDRCHAINEDTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 24)
#define PRIMITIVE2D_ID_OVERLAYBITMAPEXPRIMITIVE         (PRIMITIVE2D_ID_RANGE_SVX| 15)
#define PRIMITIVE2D_ID_OVERLAYCROSSHAIRPRIMITIVE        (PRIMITIVE2D_ID_RANGE_SVX| 16)
#define PRIMITIVE2D_ID_OVERLAYRECTANGLEPRIMITIVE        (PRIMITIVE2D_ID_RANGE_SVX| 17)
#define PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE  (PRIMITIVE2D_ID_RANGE_SVX| 18)
#define PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE (PRIMITIVE2D_ID_RANGE_SVX| 19)
#define PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D            (PRIMITIVE2D_ID_RANGE_SVX| 20)
#define PRIMITIVE2D_ID_SDROLECONTENTPRIMITIVE2D         (PRIMITIVE2D_ID_RANGE_SVX| 21)
#define PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 22)
#define PRIMITIVE2D_ID_SDRCHAINEDTEXTPRIMITIVE2D        (PRIMITIVE2D_ID_RANGE_SVX| 23)


#endif // INCLUDED_SVX_SDR_PRIMITIVE2D_SVX_PRIMITIVETYPES2D_HXX
diff --git a/sc/source/ui/miscdlgs/autofmt.cxx b/sc/source/ui/miscdlgs/autofmt.cxx
index 40b8da7..a8ed0d2 100644
--- a/sc/source/ui/miscdlgs/autofmt.cxx
+++ b/sc/source/ui/miscdlgs/autofmt.cxx
@@ -410,7 +410,7 @@ void ScAutoFmtPreview::PaintCells(vcl::RenderContext& rRenderContext)

            if (pProcessor2D)
            {
                maArray.DrawArray(*pProcessor2D.get());
                pProcessor2D->process(maArray.CreateB2DPrimitiveArray());
                pProcessor2D.reset();
            }
        }
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index 98f8822..da4c342 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -1457,7 +1457,7 @@ void ScOutputData::DrawFrame(vcl::RenderContext& rRenderContext)
    std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(CreateProcessor2D());
    if (!pProcessor)
        return;

    drawinglayer::primitive2d::Primitive2DContainer aPrimitives;
    while( nRow1 <= nLastRow )
    {
        while( (nRow1 <= nLastRow) && !pRowInfo[ nRow1 ].bChanged ) ++nRow1;
@@ -1465,10 +1465,13 @@ void ScOutputData::DrawFrame(vcl::RenderContext& rRenderContext)
        {
            size_t nRow2 = nRow1;
            while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2;
            rArray.DrawRange( *pProcessor.get(), nFirstCol, nRow1, nLastCol, nRow2, pForceColor );
            aPrimitives.append(
                rArray.CreateB2DPrimitiveRange(
                    nFirstCol, nRow1, nLastCol, nRow2, pForceColor ));
            nRow1 = nRow2 + 1;
        }
    }
    pProcessor->process(aPrimitives);
    pProcessor.reset();

    rRenderContext.SetDrawMode(nOldDrawMode);
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index d3f4aef..4869535 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -50,26 +50,38 @@ void Style::implEnsureImplStyle()
    }
}

Style::Style() : maImplStyle()
Style::Style() :
    maImplStyle(),
    mpUsingCell(nullptr)
{
}

Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType ) : maImplStyle(new implStyle())
Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType ) :
    maImplStyle(new implStyle()),
    mpUsingCell(nullptr)
{
    maImplStyle->mnType = nType;
    Set( nP, nD, nS );
}

Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType ) : maImplStyle(new implStyle())
Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType ) :
    maImplStyle(new implStyle()),
    mpUsingCell(nullptr)
{
    maImplStyle->mnType = nType;
    Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
}

Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) : maImplStyle(new implStyle())
Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
    maImplStyle(),
    mpUsingCell(nullptr)
{
    maImplStyle->mfPatternScale = fScale;
    Set( pBorder, fScale );
    if(nullptr != pBorder)
    {
        maImplStyle.reset(new implStyle());
        maImplStyle->mfPatternScale = fScale;
        Set( pBorder, fScale );
    }
}

void Style::SetPatternScale( double fScale )
@@ -91,8 +103,7 @@ void Style::Clear()
{
    if(maImplStyle)
    {
        Set( Color(), Color(), Color(), false, 0, 0, 0 );
        maImplStyle->mnType = SvxBorderLineStyle::SOLID;
        maImplStyle.reset();
    }
}

@@ -123,20 +134,27 @@ void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& 
    Set( nP, nD, nS );
}

void Style::Set( const SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWidth )
void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
{
    if(nullptr == pBorder)
    {
        Clear();
        return;
    }

    implEnsureImplStyle();
    implStyle* pTarget = maImplStyle.get();
    pTarget->maColorPrim = rBorder.GetColorOut();
    pTarget->maColorSecn = rBorder.GetColorIn();
    pTarget->maColorGap = rBorder.GetColorGap();
    pTarget->mbUseGapColor = rBorder.HasGapColor();
    pTarget->maColorPrim = pBorder->GetColorOut();
    pTarget->maColorSecn = pBorder->GetColorIn();
    pTarget->maColorGap = pBorder->GetColorGap();
    pTarget->mbUseGapColor = pBorder->HasGapColor();

    sal_uInt16 nPrim = rBorder.GetOutWidth();
    sal_uInt16 nDist = rBorder.GetDistance();
    sal_uInt16 nSecn = rBorder.GetInWidth();
    const sal_uInt16 nPrim(pBorder->GetOutWidth());
    const sal_uInt16 nDist(pBorder->GetDistance());
    const sal_uInt16 nSecn(pBorder->GetInWidth());

    pTarget->mnType = rBorder.GetBorderLineStyle();
    pTarget->mnType = pBorder->GetBorderLineStyle();

    if( !nSecn )    // no or single frame border
    {
        Set( std::min<double>(nPrim * fScale, nMaxWidth), 0, 0 );
@@ -185,18 +203,6 @@ void Style::Set( const SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWid
    }
}

void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
{
    if( pBorder )
    {
        Set( *pBorder, fScale, nMaxWidth );
    }
    else
    {
        Clear();
    }
}

void Style::SetRefMode( RefMode eRefMode )
{
    if(!maImplStyle)
@@ -279,54 +285,50 @@ Style& Style::MirrorSelf()
    return *this;
}

const Cell* Style::GetUsingCell() const
bool Style::operator==( const Style& rOther) const
{
    if(!maImplStyle)
    if(!maImplStyle && !rOther.maImplStyle)
    {
        return nullptr;
        return true;
    }

    return maImplStyle->mpUsingCell;
}

void Style::SetUsingCell(const Cell* pCell)
{
    if(!maImplStyle)
    if(maImplStyle && rOther.maImplStyle && maImplStyle.get() == rOther.maImplStyle.get())
    {
        if(nullptr == pCell)
        {
            return;
        }

        implEnsureImplStyle();
        return true;
    }

    maImplStyle->mpUsingCell = pCell;
    return (Prim() == rOther.Prim()
        && Dist() == rOther.Dist()
        && Secn() == rOther.Secn()
        && GetColorPrim() == rOther.GetColorPrim()
        && GetColorSecn() == rOther.GetColorSecn()
        && GetColorGap() == rOther.GetColorGap()
        && GetRefMode() == rOther.GetRefMode()
        && UseGapColor() == rOther.UseGapColor()
        && Type() == rOther.Type());
}

bool operator==( const Style& rL, const Style& rR )
bool Style::operator<( const Style& rOther) const
{
    return (rL.Prim() == rR.Prim()) && (rL.Dist() == rR.Dist()) && (rL.Secn() == rR.Secn()) &&
        (rL.GetColorPrim() == rR.GetColorPrim()) && (rL.GetColorSecn() == rR.GetColorSecn()) &&
        (rL.GetColorGap() == rR.GetColorGap()) && (rL.GetRefMode() == rR.GetRefMode()) &&
        (rL.UseGapColor() == rR.UseGapColor() ) && (rL.Type() == rR.Type());
}
    if(!maImplStyle && !rOther.maImplStyle)
    {
        // are equal
        return false;
    }

bool operator<( const Style& rL, const Style& rR )
{
    // different total widths -> rL<rR, if rL is thinner
    double nLW = rL.GetWidth();
    double nRW = rR.GetWidth();
    // different total widths -> this<rOther, if this is thinner
    double nLW = GetWidth();
    double nRW = rOther.GetWidth();
    if( !rtl::math::approxEqual(nLW, nRW) ) return nLW < nRW;

    // one line double, the other single -> rL<rR, if rL is single
    if( (rL.Secn() == 0) != (rR.Secn() == 0) ) return rL.Secn() == 0;
    // one line double, the other single -> this<rOther, if this is single
    if( (Secn() == 0) != (rOther.Secn() == 0) ) return Secn() == 0;

    // both lines double with different distances -> rL<rR, if distance of rL greater
    if( (rL.Secn() && rR.Secn()) && !rtl::math::approxEqual(rL.Dist(), rR.Dist()) ) return rL.Dist() > rR.Dist();
    // both lines double with different distances -> this<rOther, if distance of this greater
    if( (Secn() && rOther.Secn()) && !rtl::math::approxEqual(Dist(), rOther.Dist()) ) return Dist() > rOther.Dist();

    // both lines single and 1 unit thick, only one is dotted -> rL<rR, if rL is dotted
    if( (nLW == 1) && (rL.Type() != rR.Type()) ) return rL.Type() != SvxBorderLineStyle::SOLID;
    // both lines single and 1 unit thick, only one is dotted -> this<rOther, if this is dotted
    if( (nLW == 1) && (Type() != rOther.Type()) ) return Type() != SvxBorderLineStyle::SOLID;

    // seem to be equal
    return false;
@@ -355,374 +357,531 @@ bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder,
        );
}


// Drawing functions
struct OffsetPair
{
    double          mfLeft;
    double          mfRight;
// struct OffsetPair
// {
//     double          mfLeft;
//     double          mfRight;

    OffsetPair(double a, double b) : mfLeft(a), mfRight(b) {}
//     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
{
    double          mfOffset;
    double          mfWidth;
    Color           maColor;

    OffsetWidthColor(double offset, double width, Color color) :
        mfOffset(offset),
        mfWidth(width),
        maColor(color)
    {}
};

struct OffsetCutSet
struct CutSet
{
    double          mfLeftLeft;
    double          mfRightLeft;
    double          mfLeftRight;
    double          mfRightRight;
    double          mfOLML;
    double          mfORML;
    double          mfOLMR;
    double          mfORMR;
};

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)
void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthColor >& offsets)
{
    if (rStyle.IsUsed())
    {
        // do not forget RefMode offset, primitive is free of it
        double fRefModeOffset(0.0);

        if (RefMode::Centered != rStyle.GetRefMode())
        {
            const double fHalfWidth(rStyle.GetWidth() * 0.5);

            if (RefMode::Begin == rStyle.GetRefMode())
            {
                // move aligned below vector
                fRefModeOffset = fHalfWidth;
            }
            else if (RefMode::End == rStyle.GetRefMode())
            {
                // move aligned above vector
                fRefModeOffset = -fHalfWidth;
            }
        }

        if (rStyle.Dist() && rStyle.Secn())
        {
            // both lines used (or all three), push four values, from outer to inner
            switch (rStyle.GetRefMode())
            // 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())
            {
            case RefMode::Centered:
            {
                const double fHalfFullWidth(rStyle.GetWidth() * 0.5);
                offsets.emplace_back(-fHalfFullWidth, rStyle.Prim() - fHalfFullWidth);
                offsets.emplace_back((rStyle.Prim() + rStyle.Dist()) - fHalfFullWidth, fHalfFullWidth);
                break;
                offsets.push_back(OffsetWidthColor((a + b) * 0.5, rStyle.Prim(), rStyle.GetColorPrim()));
            }
            case RefMode::Begin:

            if(0xff != rStyle.GetColorGap().GetTransparency() && rStyle.UseGapColor())
            {
                offsets.emplace_back(0.0, rStyle.Prim());
                offsets.emplace_back(rStyle.Prim() + rStyle.Dist(), rStyle.GetWidth());
                break;
                offsets.push_back(OffsetWidthColor((b + c) * 0.5, rStyle.Dist(), rStyle.GetColorGap()));
            }
            default: // case RefMode::End:

            if(0xff != rStyle.GetColorSecn().GetTransparency())
            {
                const double fFullWidth(rStyle.GetWidth());
                offsets.emplace_back(-fFullWidth, rStyle.Prim() - fFullWidth);
                offsets.emplace_back((rStyle.Prim() + rStyle.Dist()) - fFullWidth, 0.0);
                break;
            }
                offsets.push_back(OffsetWidthColor((c + d) * 0.5, rStyle.Secn(), rStyle.GetColorSecn()));
            }
        }
        else
        {
            // one line used, push two values, from outer to inner
            switch (rStyle.GetRefMode())
            if(0xff != rStyle.GetColorPrim().GetTransparency())
            {
            case RefMode::Centered:
                offsets.emplace_back(rStyle.Prim() * -0.5, rStyle.Prim() * 0.5);
                break;
            case RefMode::Begin:
                offsets.emplace_back(0.0, rStyle.Prim());
                break;
            default: // case RefMode::End:
                offsets.emplace_back(-rStyle.Prim(), 0.0);
                break;
                offsets.push_back(OffsetWidthColor(fRefModeOffset, rStyle.Prim(), rStyle.GetColorPrim()));
            }
        }
    }
}

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(
void findCutsWithStyleVectorTable(
    std::vector< CutSet >& rCutSet,
    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)
    double fOffset,
    double fHalfWidth,
    const StyleVectorTable& rStyleVectorTable)
{
    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);
    const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX));
    basegfx::B2DPoint aMyLeft(rOrigin + (aY * (fOffset - fHalfWidth)));
    basegfx::B2DPoint aMyRight(rOrigin + (aY * (fOffset + fHalfWidth)));

    if (pResult)
    for(const auto& style : rStyleVectorTable)
    {
        if (bEdgeStart)
        std::vector< OffsetWidthColor > myOffsets;
        getOffsetWidthColorFromStyle(style.getStyle(), myOffsets);
        const basegfx::B2DVector aOtherY(basegfx::getNormalizedPerpendicular(style.getB2DVector()));

        for(const auto& offset : myOffsets)
        {
            return (pResult->mfLeftRight + pResult->mfRightRight) * -0.5 * fLength;
        }
        else
        {
            return (pResult->mfLeftLeft + pResult->mfRightLeft) * 0.5 * fLength;
        }
    }
            basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherY * (offset.mfOffset - (offset.mfWidth * 0.5))));
            basegfx::B2DPoint aOtherRight(rOrigin + (aOtherY * (offset.mfOffset + (offset.mfWidth * 0.5))));
            CutSet aNewCuts;

    return 0.0;
}
            basegfx::tools::findCut(
                aOtherLeft,
                style.getB2DVector(),
                aMyLeft,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfOLML);

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

    if (!pResult)
    {
        createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rSecond, rY, myCutSets);
        pResult = getMinMaxCutSet(bEdgeStart, myCutSets);
    }
            basegfx::tools::findCut(
                aOtherRight,
                style.getB2DVector(),
                aMyLeft,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfORML);

    if (pResult)
    {
        if (bEdgeStart)
        {
            return (pResult->mfLeftRight + pResult->mfRightRight) * 0.5 * -fLength;
        }
        else
        {
            return (pResult->mfLeftLeft + pResult->mfRightLeft) * 0.5 * fLength;
        }
    }
            basegfx::tools::findCut(
                aOtherRight,
                style.getB2DVector(),
                aMyRight,
                rX,
                CutFlagValue::LINE,
                &aNewCuts.mfORMR);

    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())));
            rCutSet.push_back(aNewCuts);
        }
    }
}
@@ -736,32 +895,80 @@ void CreateBorderPrimitives(
    const StyleVectorTable& rEndStyleVectorTable,
    const Color* pForceColor)
{
    /// rough mapping for testing
    if (rBorder.IsUsed())
    // get offset color pairs for  style, one per visible line
    std::vector< OffsetWidthColor > myOffsets;
    getOffsetWidthColorFromStyle(rBorder, myOffsets);

    if(!myOffsets.empty())
    {
        const size_t nStart(rStartStyleVectorTable.size());
        const size_t nEnd(rEndStyleVectorTable.size());
        const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
        const bool bHasStartStyles(!rStartStyleVectorTable.empty());
        const bool bHasEndStyles(!rEndStyleVectorTable.empty());

        CreateBorderPrimitives(
            rTarget,
            rOrigin,
            rX,
            basegfx::getNormalizedPerpendicular(rX),
            rBorder,
        if(bHasStartStyles || bHasEndStyles)
        {
            // we have start/end styles, get offset values
            double fExtStartLeft(0.0);
            double fExtStartRight(0.0);
            double fExtEndLeft(0.0);
            double fExtEndRight(0.0);

            2 == nStart ? rStartStyleVectorTable[0].getStyle() : 5 == nStart ? rStartStyleVectorTable[0].getStyle() : Style(),
            5 == nStart ? rStartStyleVectorTable[1].getStyle() : Style(),
            5 == nStart ? rStartStyleVectorTable[2].getStyle() : Style(),
            5 == nStart ? rStartStyleVectorTable[3].getStyle() : Style(),
            2 == nStart ? rStartStyleVectorTable[1].getStyle() : 5 == nStart ? rStartStyleVectorTable[4].getStyle() : Style(),
            for(const auto& offset : myOffsets)
            {
                const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset));
                const basegfx::B2DPoint aEnd(aStart + rX);

            2 == nEnd ? rEndStyleVectorTable[0].getStyle() : 5 == nEnd ? rEndStyleVectorTable[0].getStyle() : Style(),
            5 == nEnd ? rEndStyleVectorTable[1].getStyle() : Style(),
            5 == nEnd ? rEndStyleVectorTable[2].getStyle() : Style(),
            5 == nEnd ? rEndStyleVectorTable[3].getStyle() : Style(),
            2 == nEnd ? rEndStyleVectorTable[1].getStyle() : 5 == nEnd ? rEndStyleVectorTable[4].getStyle() : Style(),
                if(bHasStartStyles)
                {
                    // create extends for line starts
                    std::vector< CutSet > aStartCutSet;
                    findCutsWithStyleVectorTable(aStartCutSet, rOrigin, rX, offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
                }

            pForceColor);
                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())));
            }
        }
        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())));
            }
        }
    }
}

diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index c8520d5..f8897b7 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -77,11 +77,22 @@ public:
    void                MirrorSelfX();

    basegfx::B2DHomMatrix CreateCoordinateSystem(const Array& rArray) const;
    size_t GetCellIndex(const Array& rArray) const;
};

typedef std::vector< long >     LongVec;
typedef std::vector< Cell >     CellVec;

size_t Cell::GetCellIndex(const Array& rArray) const
{
    if(-1 == maCellIndex)
    {
        rArray.AddCellIndices();
    }

    return maCellIndex;
}

basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray) const
{
    if(!maCoordinateSystem.isIdentity())
@@ -89,14 +100,11 @@ basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray) const
        return maCoordinateSystem;
    }

    if(-1 == maCellIndex)
    {
        rArray.AddCellIndices();
    }
    const size_t nCellIndex(GetCellIndex(rArray));

    if(-1 != maCellIndex)
    if(-1 != nCellIndex)
    {
        const basegfx::B2DRange aRange(rArray.GetCellRange(maCellIndex));
        const basegfx::B2DRange aRange(rArray.GetCellRange(nCellIndex));

        if(!aRange.isEmpty())
        {
@@ -932,401 +940,294 @@ void Array::MirrorSelfX()
}

// drawing
void HelperCreateHorizontalBorderPrimitives(
    const basegfx::B2DHomMatrix& rCoordinateSystem, drawinglayer::primitive2d::Primitive2DContainer& rSequence, bool bUpper, const Style& rBorder,
    const Style& rStartFromTR, const Style& rStartLFromT, const Style& rStartLFromL, const Style& rStartLFromB, const Style& rStartFromBR,
    const Style& rEndFromTL, const Style& rEndRFromT, const Style& rEndRFromR, const Style& rEndRFromB, const Style& rEndFromBL,
    const Color* pForceColor)
void HelperCreateHorizontalEntry(
    const Array& rArray, const Style& rStyle, size_t col, size_t row,
    const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const basegfx::B2DVector& rY,
    drawinglayer::primitive2d::Primitive2DContainer& rSequence,
    bool bUpper, const Color* pForceColor)
{
    const basegfx::B2DVector aX(basegfx::tools::getColumn(rCoordinateSystem, 0));
    const basegfx::B2DVector aY(basegfx::tools::getColumn(rCoordinateSystem, 1));
    // get involved styles at start
    const Style& rStartFromTR(rArray.GetCellStyleBL( col, row - 1 ));
    const Style& rStartLFromT(rArray.GetCellStyleLeft( col, row - 1 ));
    const Style& rStartLFromL(rArray.GetCellStyleTop( col - 1, row ));
    const Style& rStartLFromB(rArray.GetCellStyleLeft( col, row ));
    const Style& rStartFromBR(rArray.GetCellStyleTL( col, row ));
    StyleVectorTable aStart;

    if(!aX.equalZero() && !aY.equalZero())
    if(rStartFromTR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromTR, rX - rY));
    if(rStartLFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromT, -rY));
    if(rStartLFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromL, -rX));
    if(rStartLFromB.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromB, rY));
    if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY));

    // get involved styles at end
    const Style& rEndFromTL(rArray.GetCellStyleBR( col, row - 1 ));
    const Style& rEndRFromT(rArray.GetCellStyleRight( col, row - 1 ));
    const Style& rEndRFromR(rArray.GetCellStyleTop( col + 1, row ));
    const Style& rEndRFromB(rArray.GetCellStyleRight( col, row ));
    const Style& rEndFromBL(rArray.GetCellStyleTR( col, row ));
    StyleVectorTable aEnd;

    if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, -rX -rY));
    if(rEndRFromT.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromT, -rY));
    if(rEndRFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromR, rX));
    if(rEndRFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromB, rY));
    if(rEndFromBL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromBL, rY - rX));

    CreateBorderPrimitives(
        rSequence,
        bUpper ? rOrigin : rOrigin + rY,
        rX,
        rStyle,
        aStart,
        aEnd,
        pForceColor
    );
}

void HelperCreateVerticalEntry(
    const Array& rArray, const Style& rStyle, size_t col, size_t row,
    const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const basegfx::B2DVector& rY,
    drawinglayer::primitive2d::Primitive2DContainer& rSequence,
    bool bLeft, const Color* pForceColor)
{
    // get involved styles at start
    const Style& rStartFromBL(rArray.GetCellStyleTR( col - 1, row ));
    const Style& rStartTFromL(rArray.GetCellStyleTop( col - 1, row ));
    const Style& rStartTFromT(rArray.GetCellStyleLeft( col, row - 1 ));
    const Style& rStartTFromR(rArray.GetCellStyleTop( col, row ));
    const Style& rStartFromBR(rArray.GetCellStyleTL( col, row ));
    StyleVectorTable aStart;

    if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY));
    if(rStartTFromR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromR, rX));
    if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, rY));
    if(rStartTFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromL, -rX));
    if(rStartFromBL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBL, rY - rX));

    // get involved styles at end
    const Style& rEndFromTL(rArray.GetCellStyleBR( col - 1, row ));
    const Style& rEndBFromL(rArray.GetCellStyleBottom( col - 1, row ));
    const Style& rEndBFromB(rArray.GetCellStyleLeft( col, row + 1 ));
    const Style& rEndBFromR(rArray.GetCellStyleBottom( col, row ));
    const Style& rEndFromTR(rArray.GetCellStyleBL( col, row ));
    StyleVectorTable aEnd;

    if(rEndFromTR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTR, rX - rY));
    if(rEndBFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromR, rX));
    if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, -rY));
    if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, rX));
    if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, rX + rY));

    CreateBorderPrimitives(
        rSequence,
        bLeft ? rOrigin : rOrigin + rX,
        rY,
        rStyle,
        aStart,
        aEnd,
        pForceColor
    );
}

void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::primitive2d::Primitive2DContainer& rSequence, const Color* pForceColor)
{
    const Cell* pCell = rStyle.GetUsingCell();

    if(nullptr != pCell)
    {
        const basegfx::B2DPoint aOrigin(basegfx::tools::getColumn(rCoordinateSystem, 2));
        StyleVectorTable aStart;
        StyleVectorTable aEnd;
        const size_t nCellIndex(pCell->GetCellIndex(rArray));

        if(rStartFromTR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromTR, aX - aY));
        if(rStartLFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromT, -aY));
        if(rStartLFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromL, -aX));
        if(rStartLFromB.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromB, aY));
        if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, aX + aY));
        if(-1 != nCellIndex)
        {
            size_t col(nCellIndex % rArray.GetColCount());
            size_t row(nCellIndex / rArray.GetColCount());
            const bool bL(&rStyle == &pCell->GetStyleLeft());
            const bool bR(&rStyle == &pCell->GetStyleRight());
            const bool bT(&rStyle == &pCell->GetStyleTop());
            const bool bB(&rStyle == &pCell->GetStyleBottom());

        if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, -aX -aY));
        if(rEndRFromT.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromT, -aY));
        if(rEndRFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromR, aX));
        if(rEndRFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromB, aY));
        if(rEndFromBL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromBL, aY - aX));
            if(bL || bR || bT || bB)
            {
                const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(rArray));
                const basegfx::B2DVector aX(basegfx::tools::getColumn(aCoordinateSystem, 0));
                const basegfx::B2DVector aY(basegfx::tools::getColumn(aCoordinateSystem, 1));
                const basegfx::B2DPoint aOrigin(basegfx::tools::getColumn(aCoordinateSystem, 2));

        CreateBorderPrimitives(
            rSequence,
            bUpper ? aOrigin : aOrigin + aY,
            aX,
            rBorder,
            aStart,
            aEnd,
            pForceColor
        );
                if(bL || bR)
                {
                    // left/right
                    HelperCreateVerticalEntry(rArray, rStyle, bL ? col : col + 1, row, aOrigin, aX, aY, rSequence, bL, pForceColor);
                }
                else if(bT || bB)
                {
                    // top/bottom
                    HelperCreateHorizontalEntry(rArray, rStyle, col, bT ? row : row + 1, aOrigin, aX, aY, rSequence, bT, pForceColor);
                }
            }
        }
    }
}

void HelperCreateVerticalBorderPrimitives(
    const basegfx::B2DHomMatrix& rCoordinateSystem, drawinglayer::primitive2d::Primitive2DContainer& rSequence, bool bLeft, const Style& rBorder,
    const Style& rStartFromBR, const Style& rStartTFromR, const Style& rStartTFromT, const Style& rStartTFromL, const Style& rStartFromBL,
    const Style& rEndFromTR, const Style& rEndBFromR, const Style& rEndBFromB, const Style& rEndBFromL, const Style& rEndFromTL,
    const Color* pForceColor)
drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
    size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
    const Color* pForceColor ) const
{
    const basegfx::B2DVector aX(basegfx::tools::getColumn(rCoordinateSystem, 0));
    const basegfx::B2DVector aY(basegfx::tools::getColumn(rCoordinateSystem, 1));
    DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "CreateB2DPrimitiveRange" );
    DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "CreateB2DPrimitiveRange" );

    if(!aX.equalZero() && !aY.equalZero())
    // various primitive sequences to collect the different border types
    drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
    drawinglayer::primitive2d::Primitive2DContainer aVerticalSequence;
    drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;

    for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow)
    {
        const basegfx::B2DPoint aOrigin(basegfx::tools::getColumn(rCoordinateSystem, 2));
        StyleVectorTable aStart;
        StyleVectorTable aEnd;

        if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, aX + aY));
        if(rStartTFromR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromR, aX));
        if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, aY));
        if(rStartTFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromL, -aX));
        if(rStartFromBL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBL, aY - aX));

        if(rEndFromTR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTR, aX - aY));
        if(rEndBFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromR, aX));
        if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, -aY));
        if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, aX));
        if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, aX + aY));

        CreateBorderPrimitives(
            rSequence,
            bLeft ? aOrigin : aOrigin + aX,
            aY,
            rBorder,
            aStart,
            aEnd,
            pForceColor
        );
    }
}

void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
        size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
        const Color* pForceColor ) const
{
    DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
    DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );

    size_t nCol, nRow;

    // *** diagonal frame borders ***
    for (nRow = nFirstRow; nRow <= nLastRow; ++nRow)
    {
        for (nCol = nFirstCol; nCol <= nLastCol; ++nCol)
        for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
        {
            const Cell& rCell = CELL(nCol, nRow);
            bool bOverlapX = rCell.mbOverlapX;
            bool bOverlapY = rCell.mbOverlapY;
            bool bFirstCol = nCol == nFirstCol;
            bool bFirstRow = nRow == nFirstRow;
            const basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this));
            const basegfx::B2DVector aX(basegfx::tools::getColumn(aCoordinateSystem, 0));
            const basegfx::B2DVector aY(basegfx::tools::getColumn(aCoordinateSystem, 1));

            if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) || (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
            if(!aX.equalZero() && !aY.equalZero())
            {
                size_t _nFirstCol = mxImpl->GetMergedFirstCol(nCol, nRow);
                size_t _nFirstRow = mxImpl->GetMergedFirstRow(nCol, nRow);
                const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
                const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
                size_t _nLastCol = mxImpl->GetMergedLastCol(nCol, nRow);
                size_t _nLastRow = mxImpl->GetMergedLastRow(nCol, nRow);
                const basegfx::B2DPoint aOrigin(basegfx::tools::getColumn(aCoordinateSystem, 2));

                if (rTLBR.GetWidth() || rBLTR.GetWidth())
                const bool bOverlapX(rCell.mbOverlapX);
                const bool bOverlapY(rCell.mbOverlapY);
                const bool bFirstCol(nCol == nFirstCol);
                const bool bLastCol(nCol == nLastCol);
                const bool bFirstRow(nRow == nFirstRow);
                const bool bLastRow(nRow == nLastRow);

                if (!bOverlapX || bFirstRow)
                {
                    basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this));
                    const basegfx::B2DVector aX(basegfx::tools::getColumn(aCoordinateSystem, 0));
                    const basegfx::B2DVector aY(basegfx::tools::getColumn(aCoordinateSystem, 1));
                    const Style& rTop = GetCellStyleTop(_nFirstCol, _nFirstRow);

                    if(!aX.equalZero() && !aY.equalZero())
                    if(rTop.IsUsed())
                    {
                        size_t _nLastCol = mxImpl->GetMergedLastCol(nCol, nRow);
                        size_t _nLastRow = mxImpl->GetMergedLastRow(nCol, nRow);
                        const basegfx::B2DPoint aOrigin(basegfx::tools::getColumn(aCoordinateSystem, 2));
                        drawinglayer::primitive2d::Primitive2DContainer aSequence;
                        HelperCreateEntry(*this, rTop, aHorizontalSequence, pForceColor);
                    }
                }

                        if(rTLBR.GetWidth())
                        {
                            /// top-left and bottom-right Style Tables
                            StyleVectorTable aStart;
                            StyleVectorTable aEnd;
                if (bLastRow)
                {
                    const Style& rBottom = GetCellStyleBottom(_nFirstCol, _nFirstRow);

                            /// Fill top-left Style Table
                            const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
                            if(rTLFromRight.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromRight, aX));
                            const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
                            if(rTLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromBottom, aY));
                    if(rBottom.IsUsed())
                    {
                        HelperCreateEntry(*this, rBottom, aHorizontalSequence, pForceColor);
                    }
                }

                            /// Fill bottom-right Style Table
                            const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
                            if(rBRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromBottom, -aY));
                            const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
                            if(rBRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromLeft, -aX));
                if (!bOverlapY || bFirstCol)
                {
                    const Style& rLeft(GetCellStyleLeft(_nFirstCol, _nFirstRow));

                            CreateBorderPrimitives(
                                aSequence,
                                aOrigin,
                                aX + aY,
                                rTLBR,
                                aStart,
                                aEnd,
                                pForceColor
                            );
                        }
                    if(rLeft.IsUsed())
                    {
                        HelperCreateEntry(*this, rLeft, aVerticalSequence, pForceColor);
                    }
                }

                        if(rBLTR.GetWidth())
                        {
                            /// bottom-left and top-right Style Tables
                            StyleVectorTable aStart;
                            StyleVectorTable aEnd;
                if (bLastCol)
                {
                    const Style& rRight(GetCellStyleRight(_nFirstCol, _nFirstRow));

                            /// Fill bottom-left Style Table
                            const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
                            if(rBLFromTop.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromTop, -aY));
                            const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
                            if(rBLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromBottom, aX));
                    if(rRight.IsUsed())
                    {
                        HelperCreateEntry(*this, rRight, aVerticalSequence, pForceColor);
                    }
                }

                            /// Fill top-right Style Table
                            const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
                            if(rTRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromBottom, -aY));
                            const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
                            if(rTRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromLeft, -aX));
                if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) || (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
                {
                    const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
                    if(rTLBR.IsUsed())
                    {
                        /// top-left and bottom-right Style Tables
                        StyleVectorTable aStart;
                        StyleVectorTable aEnd;

                            CreateBorderPrimitives(
                                aSequence,
                                aOrigin + aY,
                                aX - aY,
                                rBLTR,
                                aStart,
                                aEnd,
                                pForceColor
                            );
                        }
                        /// Fill top-left Style Table
                        const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
                        if(rTLFromRight.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromRight, aX));
                        const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
                        if(rTLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromBottom, aY));

                        rProcessor.process(aSequence);
                        /// Fill bottom-right Style Table
                        const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
                        if(rBRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromBottom, -aY));
                        const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
                        if(rBRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromLeft, -aX));

                        CreateBorderPrimitives(
                            aCrossSequence,
                            aOrigin,
                            aX + aY,
                            rTLBR,
                            aStart,
                            aEnd,
                            pForceColor
                        );
                    }

                    const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
                    if(rBLTR.IsUsed())
                    {
                        /// bottom-left and top-right Style Tables
                        StyleVectorTable aStart;
                        StyleVectorTable aEnd;

                        /// Fill bottom-left Style Table
                        const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
                        if(rBLFromTop.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromTop, -aY));
                        const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
                        if(rBLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromBottom, aX));

                        /// Fill top-right Style Table
                        const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
                        if(rTRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromBottom, -aY));
                        const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
                        if(rTRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromLeft, -aX));

                        CreateBorderPrimitives(
                            aCrossSequence,
                            aOrigin + aY,
                            aX - aY,
                            rBLTR,
                            aStart,
                            aEnd,
                            pForceColor
                        );
                    }
                }
            }
        }
    }

    // *** horizontal frame borders ***
    for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
    {
        // *Start*** variables store the data of the left end of the cached frame border
        basegfx::B2DPoint aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
        const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
        Style aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ));
        const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
        const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
        const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
        Style aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ));
    // to stay compatible, create order as it was formally
    aCrossSequence.append(aHorizontalSequence);
    aCrossSequence.append(aVerticalSequence);

        // *End*** variables store the data of the right end of the cached frame border
        Style aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ));
        const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
        const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
        const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
        Style aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ));

        for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
        {
            const Style& rCurr = *pEndRFromR;

            Style aLFromTR( GetCellStyleBL( nCol, nRow - 1 ));
            const Style& rLFromT = *pEndRFromT;
            const Style& rLFromL = *pStart;
            const Style& rLFromB = *pEndRFromB;
            Style aLFromBR( GetCellStyleTL( nCol, nRow ));

            Style aRFromTL( GetCellStyleBR( nCol, nRow - 1 ));
            const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
            const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
            const Style& rRFromB = GetCellStyleRight( nCol, nRow );
            Style aRFromBL( GetCellStyleTR( nCol, nRow ));

            // check if current frame border can be connected to cached frame border
            if( !CheckFrameBorderConnectable( *pStart, rCurr, aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
            {
                // draw previous frame border
                basegfx::B2DPoint aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.getY() );

                if (pStart->IsUsed() && (aStartPos.getX() <= aEndPos.getX()))
                {
                    // prepare defaults for borderline coordinate system
                    const Cell* pCell = pStart->GetUsingCell();

                    if(pCell)
                    {
                        const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
                        drawinglayer::primitive2d::Primitive2DContainer aSequence;
                        const bool bUpper(&pCell->GetStyleTop() == pStart);

                        HelperCreateHorizontalBorderPrimitives(
                            aCoordinateSystem, aSequence, bUpper, *pStart,
                            aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
                            aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor);

                        rProcessor.process(aSequence);
                    }
                }

                // re-init "*Start***" variables
                aStartPos = aEndPos;
                pStart = &rCurr;
                aStartLFromTR = aLFromTR;
                pStartLFromT = &rLFromT;
                pStartLFromL = &rLFromL;
                pStartLFromB = &rLFromB;
                aStartLFromBR = aLFromBR;
            }

            // store current styles in "*End***" variables
            aEndRFromTL = aRFromTL;
            pEndRFromT = &rRFromT;
            pEndRFromR = &rRFromR;
            pEndRFromB = &rRFromB;
            aEndRFromBL = aRFromBL;
        }

        // draw last frame border
        basegfx::B2DPoint aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.getY() );
        if (pStart->IsUsed() && (aStartPos.getX() <= aEndPos.getX()))
        {
            // for description of involved coordinate systems have a look at
            // the first CreateBorderPrimitives call above
            const Cell* pCell = pStart->GetUsingCell();

            if(pCell)
            {
                const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
                drawinglayer::primitive2d::Primitive2DContainer aSequence;
                const bool bUpper(&pCell->GetStyleTop() == pStart);

                HelperCreateHorizontalBorderPrimitives(
                    aCoordinateSystem, aSequence, bUpper, *pStart,
                    aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
                    aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor);

                rProcessor.process(aSequence);
            }
        }
    }

    // *** vertical frame borders ***
    for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
    {
        // *Start*** variables store the data of the top end of the cached frame border
        basegfx::B2DPoint aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
        const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
        Style aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ));
        const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
        const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
        const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
        Style aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ));

        // *End*** variables store the data of the bottom end of the cached frame border
        Style aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ));
        const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
        const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
        const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
        Style aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ));

        for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
        {
            const Style& rCurr = *pEndBFromB;

            Style aTFromBL( GetCellStyleTR( nCol - 1, nRow ));
            const Style& rTFromL = *pEndBFromL;
            const Style& rTFromT = *pStart;
            const Style& rTFromR = *pEndBFromR;
            Style aTFromBR( GetCellStyleTL( nCol, nRow ));

            Style aBFromTL( GetCellStyleBR( nCol - 1, nRow ));
            const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
            const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
            const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
            Style aBFromTR( GetCellStyleBL( nCol, nRow ));

            // check if current frame border can be connected to cached frame border
            if( !CheckFrameBorderConnectable( *pStart, rCurr,
                    aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
            {
                // draw previous frame border
                basegfx::B2DPoint aEndPos( aStartPos.getX(), mxImpl->GetRowPosition( nRow ) );
                if (pStart->IsUsed() && (aStartPos.getY() <= aEndPos.getY()))
                {
                    // for description of involved coordinate systems have a look at
                    // the first CreateBorderPrimitives call above. Additionally adapt to vertical
                    const Cell* pCell = pStart->GetUsingCell();

                    if(pCell)
                    {
                        const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
                        drawinglayer::primitive2d::Primitive2DContainer aSequence;
                        const bool bLeft(&pCell->GetStyleLeft() == pStart);

                        HelperCreateVerticalBorderPrimitives(
                            aCoordinateSystem, aSequence, bLeft, *pStart,
                            aStartTFromBR, *pStartTFromR, *pStartTFromT, *pStartTFromL, aStartTFromBL,
                            aEndBFromTR, *pEndBFromR, *pEndBFromB, *pEndBFromL, aEndBFromTL, pForceColor);

                        rProcessor.process(aSequence);
                    }
                }

                // re-init "*Start***" variables
                aStartPos = aEndPos;
                pStart = &rCurr;
                aStartTFromBL = aTFromBL;
                pStartTFromL = &rTFromL;
                pStartTFromT = &rTFromT;
                pStartTFromR = &rTFromR;
                aStartTFromBR = aTFromBR;
            }

            // store current styles in "*End***" variables
            aEndBFromTL = aBFromTL;
            pEndBFromL = &rBFromL;
            pEndBFromB = &rBFromB;
            pEndBFromR = &rBFromR;
            aEndBFromTR = aBFromTR;
        }

        // draw last frame border
        basegfx::B2DPoint aEndPos( aStartPos.getX(), mxImpl->GetRowPosition( nRow ) );
        if (pStart->IsUsed() && (aStartPos.getY() <= aEndPos.getY()))
        {
            // for description of involved coordinate systems have a look at
            // the first CreateBorderPrimitives call above, adapt to vertical
            const Cell* pCell = pStart->GetUsingCell();

            if(pCell)
            {
                const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
                drawinglayer::primitive2d::Primitive2DContainer aSequence;
                const bool bLeft(&pCell->GetStyleLeft() == pStart);

                HelperCreateVerticalBorderPrimitives(
                    aCoordinateSystem, aSequence, bLeft, *pStart,
                    aStartTFromBR, *pStartTFromR, *pStartTFromT, *pStartTFromL, aStartTFromBL,
                    aEndBFromTR, *pEndBFromR, *pEndBFromB, *pEndBFromL, aEndBFromTL, pForceColor);

                rProcessor.process(aSequence);
            }
        }
    }
    return aCrossSequence;
}

void Array::DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) const
drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveArray() const
{
    drawinglayer::primitive2d::Primitive2DContainer aPrimitives;

    if (mxImpl->mnWidth && mxImpl->mnHeight)
        DrawRange(rProcessor, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, nullptr);
    {
        aPrimitives = CreateB2DPrimitiveRange(0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, nullptr);
    }

    return aPrimitives;
}

void Array::AddCellIndices() const
diff --git a/svx/source/dialog/frmsel.cxx b/svx/source/dialog/frmsel.cxx
index c3b58e0..9678339 100644
--- a/svx/source/dialog/frmsel.cxx
+++ b/svx/source/dialog/frmsel.cxx
@@ -132,8 +132,8 @@ void FrameBorder::SetCoreStyle( const SvxBorderLine* pStyle )
        maCoreStyle = SvxBorderLine();

    // from twips to points
    maUIStyle.Set( maCoreStyle, 0.05, FRAMESEL_GEOM_WIDTH );
    meState = maUIStyle.Prim() ? FrameBorderState::Show : FrameBorderState::Hide;
    maUIStyle.Set( &maCoreStyle, 0.05, FRAMESEL_GEOM_WIDTH );
    meState = maUIStyle.IsUsed() ? FrameBorderState::Show : FrameBorderState::Hide;
}

void FrameBorder::SetState( FrameBorderState eState )
@@ -689,7 +689,7 @@ void FrameSelectorImpl::DrawAllFrameBorders()

    if (pProcessor2D)
    {
        maArray.DrawArray(*pProcessor2D.get());
        pProcessor2D->process(maArray.CreateB2DPrimitiveArray());
        pProcessor2D.reset();
    }
}
diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 0ee9574..d696569 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -37,6 +37,7 @@
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <svx/framelink.hxx>

#include "cell.hxx"
#include "tablelayouter.hxx"
@@ -142,415 +143,18 @@ namespace drawinglayer
    } // end of namespace primitive2d
} // end of namespace drawinglayer


namespace drawinglayer
{
    namespace primitive2d
    {
        class SdrBorderlinePrimitive2D : public BufferedDecompositionPrimitive2D
        {
        private:
            basegfx::B2DHomMatrix                       maTransform;
            SvxBorderLine                               maLeftLine;
            SvxBorderLine                               maBottomLine;
            SvxBorderLine                               maRightLine;
            SvxBorderLine                               maTopLine;

            // Neighbor cells' borders
            SvxBorderLine                               maLeftFromTLine;
            SvxBorderLine                               maLeftFromBLine;
            SvxBorderLine                               maRightFromTLine;
            SvxBorderLine                               maRightFromBLine;
            SvxBorderLine                               maTopFromLLine;
            SvxBorderLine                               maTopFromRLine;
            SvxBorderLine                               maBottomFromLLine;
            SvxBorderLine                               maBottomFromRLine;

            bool                                        mbLeftIsOutside : 1;
            bool                                        mbBottomIsOutside : 1;
            bool                                        mbRightIsOutside : 1;
            bool                                        mbTopIsOutside : 1;

        protected:
            // local decomposition.
            virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& aViewInformation) const override;

        public:
            SdrBorderlinePrimitive2D(
                const basegfx::B2DHomMatrix& rTransform,
                const SvxBorderLine& rLeftLine,
                const SvxBorderLine& rBottomLine,
                const SvxBorderLine& rRightLine,
                const SvxBorderLine& rTopLine,
                const SvxBorderLine& rLeftFromTLine,
                const SvxBorderLine& rLeftFromBLine,
                const SvxBorderLine& rRightFromTLine,
                const SvxBorderLine& rRightFromBLine,
                const SvxBorderLine& rTopFromLLine,
                const SvxBorderLine& rTopFromRLine,
                const SvxBorderLine& rBottomFromLLine,
                const SvxBorderLine& rBottomFromRLine,
                bool bLeftIsOutside,
                bool bBottomIsOutside,
                bool bRightIsOutside,
                bool bTopIsOutside)
            :   BufferedDecompositionPrimitive2D(),
                maTransform(rTransform),
                maLeftLine(rLeftLine),
                maBottomLine(rBottomLine),
                maRightLine(rRightLine),
                maTopLine(rTopLine),
                maLeftFromTLine(rLeftFromTLine),
                maLeftFromBLine(rLeftFromBLine),
                maRightFromTLine(rRightFromTLine),
                maRightFromBLine(rRightFromBLine),
                maTopFromLLine(rTopFromLLine),
                maTopFromRLine(rTopFromRLine),
                maBottomFromLLine(rBottomFromLLine),
                maBottomFromRLine(rBottomFromRLine),
                mbLeftIsOutside(bLeftIsOutside),
                mbBottomIsOutside(bBottomIsOutside),
                mbRightIsOutside(bRightIsOutside),
                mbTopIsOutside(bTopIsOutside)
            {
            }

            // data access
            const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
            const SvxBorderLine& getLeftLine() const { return maLeftLine; }
            const SvxBorderLine& getBottomLine() const { return maBottomLine; }
            const SvxBorderLine& getRightLine() const { return maRightLine; }
            const SvxBorderLine& getTopLine() const { return maTopLine; }

            // compare operator
            virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;

            // provide unique ID
            DeclPrimitive2DIDBlock()
        };

        sal_uInt16 getBorderLineOutWidth(const SvxBorderLine& rLineA)
        {
            return (1 == rLineA.GetOutWidth() ? 0 : rLineA.GetOutWidth());
        }

        sal_uInt16 getBorderLineDistance(const SvxBorderLine& rLineA)
        {
            return (1 == rLineA.GetDistance() ? 0 : rLineA.GetDistance());
        }

        sal_uInt16 getBorderLineInWidth(const SvxBorderLine& rLineA)
        {
            return (1 == rLineA.GetInWidth() ? 0 : rLineA.GetInWidth());
        }

        sal_uInt16 getBorderLineWidth(const SvxBorderLine& rLineA)
        {
            return getBorderLineOutWidth(rLineA) + getBorderLineDistance(rLineA) + getBorderLineInWidth(rLineA);
        }

        double getExtend(const SvxBorderLine& rLineSide, const SvxBorderLine& rLineOpposite)
        {
            double nExtend = 0.0;
            if(!rLineSide.isEmpty())
            {
                // reduce to inner edge of associated matching line
                nExtend = -(getBorderLineWidth(rLineSide) / 2.0);
            }
            else
            {
                nExtend = (getBorderLineWidth(rLineOpposite) / 2.0);
            }

            return nExtend;
        }

        double getChangedValue(sal_uInt16 nValue, bool bChangeToMM)
        {
            if(1 == nValue)
                return 1.0;

            if(bChangeToMM)
                return nValue * (127.0 / 72.0);

            return (double)nValue;
        }

        void SdrBorderlinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*aViewInformation*/) const
        {
            const double fTwipsToMM(127.0 / 72.0);

            if(!getLeftLine().isEmpty())
            {
                // create left line from top to bottom
                basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 0.0));
                basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(0.0, 1.0));

                // Move the left border to the left.
                double fOffset = getChangedValue(getLeftLine().GetDistance(), true/*InTwips*/);
                aStart += basegfx::B2DPoint(-fOffset,-fOffset);
                aEnd += basegfx::B2DPoint(-fOffset,fOffset);

                if(!aStart.equal(aEnd))
                {
                    const double fExtendIS(getExtend(getTopLine(), maTopFromLLine) * fTwipsToMM);
                    const double fExtendIE(getExtend(getBottomLine(), maBottomFromLLine) * fTwipsToMM);

                    if (basegfx::fTools::equalZero(getLeftLine().GetInWidth()))
                    {
                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getLeftLine().GetOutWidth(), true/*InTwips*/),
                                    getLeftLine().GetColorOut().getBColor(),
                                    BorderLineExtend(
                                        fExtendIS,
                                        fExtendIE)),
                                getLeftLine().GetBorderLineStyle()));
                    }
                    else
                    {
                        const double fExtendOS(getExtend(maTopFromLLine, getTopLine()) * fTwipsToMM);
                        const double fExtendOE(getExtend(maBottomFromLLine, getBottomLine()) * fTwipsToMM);

                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getLeftLine().GetOutWidth(), true/*InTwips*/),
                                    getLeftLine().GetColorOut().getBColor(),
                                    BorderLineExtend(
                                        fExtendIS,
                                        fExtendIE)),
                                BorderLine(
                                    getChangedValue(getLeftLine().GetDistance(), true/*InTwips*/),
                                    getLeftLine().GetColorGap().getBColor()),
                                BorderLine(getChangedValue(
                                    getLeftLine().GetInWidth(), true/*InTwips*/),
                                    getLeftLine().GetColorIn().getBColor(),
                                    BorderLineExtend(
                                        fExtendOS,
                                        fExtendOE)),
                                getLeftLine().HasGapColor(),
                                getLeftLine().GetBorderLineStyle()));
                    }
                }
            }

            if(!getBottomLine().isEmpty() && mbBottomIsOutside)
            {
                // create bottom line from left to right
                const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 1.0));
                const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 1.0));

                if(!aStart.equal(aEnd))
                {
                    const double fExtendIS(getExtend(getLeftLine(), maLeftFromBLine) * fTwipsToMM);
                    const double fExtendIE(getExtend(getRightLine(), maRightFromBLine) * fTwipsToMM);

                    if (basegfx::fTools::equalZero(getBottomLine().GetInWidth()))
                    {
                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getBottomLine().GetOutWidth(), true/*InTwips*/),
                                    getBottomLine().GetColorOut(false).getBColor(),
                                    BorderLineExtend(
                                        fExtendIS,
                                        fExtendIE)),
                                getBottomLine().GetBorderLineStyle()));
                    }
                    else
                    {
                        const double fExtendOS(getExtend(maLeftFromBLine, getLeftLine()) * fTwipsToMM);
                        const double fExtendOE(getExtend(maRightFromBLine, getRightLine()) * fTwipsToMM);

                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getBottomLine().GetOutWidth(), true/*InTwips*/),
                                    getBottomLine().GetColorOut(false).getBColor(),
                                    BorderLineExtend(
                                        fExtendIS,
                                        fExtendIE)),
                                BorderLine(
                                    getChangedValue(getBottomLine().GetDistance(), true/*InTwips*/),
                                    getBottomLine().GetColorGap().getBColor()),
                                BorderLine(
                                    getChangedValue(getBottomLine().GetInWidth(), true/*InTwips*/),
                                    getBottomLine().GetColorIn(false).getBColor(),
                                    BorderLineExtend(
                                        fExtendOS,
                                        fExtendOE)),
                                getBottomLine().HasGapColor(),
                                getBottomLine().GetBorderLineStyle()));
                    }
                }
            }

            if(!getRightLine().isEmpty())
            {
                // create right line from top to bottom
                const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(1.0, 0.0));
                const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 1.0));

                if(!aStart.equal(aEnd))
                {
                    const double fExtendOS(getExtend(maTopFromRLine, getTopLine()) * fTwipsToMM);
                    const double fExtendOE(getExtend(maBottomFromRLine, getBottomLine()) * fTwipsToMM);

                    if (basegfx::fTools::equalZero(getRightLine().GetInWidth()))
                    {
                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getRightLine().GetOutWidth(), true/*InTwips*/),
                                    getRightLine().GetColorOut().getBColor(),
                                    BorderLineExtend(
                                        fExtendOS,
                                        fExtendOE)),
                                getRightLine().GetBorderLineStyle()));
                    }
                    else
                    {
                        const double fExtendIS(getExtend(getTopLine(), maTopFromRLine) * fTwipsToMM);
                        const double fExtendIE(getExtend(getBottomLine(), maBottomFromRLine) * fTwipsToMM);

                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getRightLine().GetOutWidth(), true/*InTwips*/),
                                    getRightLine().GetColorOut().getBColor(),
                                    BorderLineExtend(
                                        fExtendOS,
                                        fExtendOE)),
                                BorderLine(
                                    getChangedValue(getRightLine().GetDistance(), true/*InTwips*/),
                                    getRightLine().GetColorGap().getBColor()),
                                BorderLine(
                                    getChangedValue(getRightLine().GetInWidth(), true/*InTwips*/),
                                    getRightLine().GetColorIn().getBColor(),
                                    BorderLineExtend(
                                        fExtendIS,
                                        fExtendIE)),
                                getRightLine().HasGapColor(),
                                getRightLine().GetBorderLineStyle()));
                    }
                }
            }

            if(!getTopLine().isEmpty())
            {
                // create top line from left to right
                basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 0.0));
                basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 0.0));

                // Move the top border up a bit.
                double fOffset = getChangedValue(getTopLine().GetDistance(), true/*InTwips*/);
                aStart += basegfx::B2DPoint(-fOffset,-fOffset);
                aEnd += basegfx::B2DPoint(fOffset,-fOffset);

                if(!aStart.equal(aEnd))
                {
                    const double fExtendOS(getExtend(maLeftFromTLine, getLeftLine()) * fTwipsToMM);
                    const double fExtendOE(getExtend(maRightFromTLine, getRightLine()) * fTwipsToMM);

                    if (basegfx::fTools::equalZero(getTopLine().GetInWidth()))
                    {
                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getTopLine().GetOutWidth(), true/*InTwips*/),
                                    getTopLine().GetColorOut(false).getBColor(),
                                    BorderLineExtend(
                                        fExtendOS,
                                        fExtendOE)),
                                getTopLine().GetBorderLineStyle()));
                    }
                    else
                    {
                        const double fExtendIS(getExtend(getLeftLine(), maLeftFromTLine) * fTwipsToMM);
                        const double fExtendIE(getExtend(getRightLine(), maRightFromTLine) * fTwipsToMM);

                        rContainer.push_back(
                            new BorderLinePrimitive2D(
                                aStart,
                                aEnd,
                                BorderLine(
                                    getChangedValue(getTopLine().GetOutWidth(), true/*InTwips*/),
                                    getTopLine().GetColorOut(false).getBColor(),
                                    BorderLineExtend(
                                        fExtendOS,
                                        fExtendOE)),
                                BorderLine(
                                    getChangedValue(getTopLine().GetDistance(), true/*InTwips*/),
                                    getTopLine().GetColorGap().getBColor()),
                                BorderLine(
                                    getChangedValue(getTopLine().GetInWidth(), true/*InTwips*/),
                                    getTopLine().GetColorIn(false).getBColor(),
                                    BorderLineExtend(
                                        fExtendIS,
                                        fExtendIE)),
                                getTopLine().HasGapColor(),
                                getTopLine().GetBorderLineStyle()));
                    }
                }
            }
        }

        bool SdrBorderlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
        {
            if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
            {
                const SdrBorderlinePrimitive2D& rCompare = static_cast<const SdrBorderlinePrimitive2D&>(rPrimitive);

                return (getTransform() == rCompare.getTransform()
                    && getLeftLine() == rCompare.getLeftLine()
                    && getBottomLine() == rCompare.getBottomLine()
                    && getRightLine() == rCompare.getRightLine()
                    && getTopLine() == rCompare.getTopLine()
                    && maLeftFromTLine == rCompare.maLeftFromTLine
                    && maLeftFromBLine == rCompare.maLeftFromBLine
                    && maRightFromTLine == rCompare.maRightFromTLine
                    && maRightFromBLine == rCompare.maRightFromBLine
                    && maTopFromLLine == rCompare.maTopFromLLine
                    && maTopFromRLine == rCompare.maTopFromRLine
                    && maBottomFromLLine == rCompare.maBottomFromLLine
                    && maBottomFromRLine == rCompare.maBottomFromRLine
                    && mbLeftIsOutside == rCompare.mbLeftIsOutside
                    && mbBottomIsOutside == rCompare.mbBottomIsOutside
                    && mbRightIsOutside == rCompare.mbRightIsOutside
                    && mbTopIsOutside == rCompare.mbTopIsOutside);
            }

            return false;
        }

        // provide unique ID
        ImplPrimitive2DIDBlock(SdrBorderlinePrimitive2D, PRIMITIVE2D_ID_SDRBORDERLINEPRIMITIVE2D)

    } // end of namespace primitive2d
} // end of namespace drawinglayer


namespace sdr
{
    namespace contact
    {
        void impGetLine(SvxBorderLine& aLine, const sdr::table::TableLayouter& rLayouter, sal_Int32 nX, sal_Int32 nY, bool bHorizontal, sal_Int32 nColCount, sal_Int32 nRowCount, bool bIsRTL)
        svx::frame::Style impGetLineStyle(
            const sdr::table::TableLayouter& rLayouter,
            sal_Int32 nX,
            sal_Int32 nY,
            bool bHorizontal,
            sal_Int32 nColCount,
            sal_Int32 nRowCount,
            bool bIsRTL)
        {
            if(nX >= 0 && nX <= nColCount && nY >= 0 && nY <= nRowCount)
            {
@@ -559,7 +163,7 @@ namespace sdr
                if(pLine)
                {
                    // copy line content
                    aLine = *pLine;
                    SvxBorderLine aLine(*pLine);

                    // check for mirroring. This shall always be done when it is
                    // not a top- or rightmost line
@@ -584,13 +188,45 @@ namespace sdr
                        aLine.SetMirrorWidths( );
                    }

                    return;
                    const double fTwipsToMM(127.0 / 72.0);
                    return svx::frame::Style(&aLine, fTwipsToMM);
                }
            }

            // no success, copy empty line
            const SvxBorderLine aEmptyLine;
            aLine = aEmptyLine;
            return svx::frame::Style();
        }

        void createForVector(drawinglayer::primitive2d::Primitive2DContainer& rContainer, const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX,
            const svx::frame::Style& rLine,
            const svx::frame::Style& rLeftA, const svx::frame::Style& rLeftB, const svx::frame::Style& rLeftC,
            const svx::frame::Style& rRightA, const svx::frame::Style& rRightB, const svx::frame::Style& rRightC)
        {
            /// top-left and bottom-right Style Tables
            svx::frame::StyleVectorTable aStart;
            svx::frame::StyleVectorTable aEnd;
            const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX));
            const double fTwipsToMM(127.0 / 72.0);

            /// Fill top-left Style Table
            if(rLeftA.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftA, -aY));
            if(rLeftB.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftB, -rX));
            if(rLeftC.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftC, aY));

            /// Fill bottom-right Style Table
            if(rRightA.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightA, -aY));
            if(rRightB.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightB, rX));
            if(rRightC.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightC, aY));

            CreateBorderPrimitives(
                rContainer,
                rOrigin,
                rX,
                rLine,
                aStart,
                aEnd,
                nullptr
            );
        }

        drawinglayer::primitive2d::Primitive2DContainer ViewContactOfTableObj::createViewIndependentPrimitive2DSequence() const
@@ -600,8 +236,10 @@ namespace sdr

            if(xTable.is())
            {
                // create primitive representation for table
                drawinglayer::primitive2d::Primitive2DContainer xRetval;
                // create primitive representation for table. Cell info goes
                // directly to aRetval, Border info to aBorderSequence and added
                // later to get the correct overlapping
                drawinglayer::primitive2d::Primitive2DContainer aRetval;
                const sal_Int32 nRowCount(xTable->getRowCount());
                const sal_Int32 nColCount(xTable->getColumnCount());
                const sal_Int32 nAllCount(nRowCount * nColCount);
@@ -621,25 +259,7 @@ namespace sdr

                    // for each cell we need potentially a cell primitive and a border primitive
                    // (e.g. single cell). Prepare sequences and input counters
                    drawinglayer::primitive2d::Primitive2DContainer xCellSequence(nAllCount);
                    drawinglayer::primitive2d::Primitive2DContainer xBorderSequence(nAllCount);
                    sal_uInt32 nCellInsert(0);
                    sal_uInt32 nBorderInsert(0);

                    // variables for border lines
                    SvxBorderLine aLeftLine;
                    SvxBorderLine aBottomLine;
                    SvxBorderLine aRightLine;
                    SvxBorderLine aTopLine;

                    SvxBorderLine aLeftFromTLine;
                    SvxBorderLine aLeftFromBLine;
                    SvxBorderLine aRightFromTLine;
                    SvxBorderLine aRightFromBLine;
                    SvxBorderLine aTopFromLLine;
                    SvxBorderLine aTopFromRLine;
                    SvxBorderLine aBottomFromLLine;
                    SvxBorderLine aBottomFromRLine;
                    drawinglayer::primitive2d::Primitive2DContainer aBorderSequence;

                    // create single primitives per cell
                    for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
@@ -693,7 +313,7 @@ namespace sdr
                                        const drawinglayer::primitive2d::Primitive2DReference xCellReference(
                                            new drawinglayer::primitive2d::SdrCellPrimitive2D(
                                                aCellMatrix, aAttribute));
                                        xCellSequence[nCellInsert++] = xCellReference;
                                        aRetval.append(xCellReference);
                                    }

                                    // handle cell borders
@@ -707,58 +327,69 @@ namespace sdr
                                    const sal_Int32 nYBottom(nY + nYSpan);

                                    // get basic lines
                                    impGetLine(aLeftLine, rTableLayouter, nX, nY, false, nColCount, nRowCount, bIsRTL);
                                    const svx::frame::Style aLeftLine(impGetLineStyle(rTableLayouter, nX, nY, false, nColCount, nRowCount, bIsRTL));
                                    //To resolve the bug fdo#59117
                                    //In RTL table as BottomLine & TopLine are drawn from Left Side to Right, nX should be nX-1
                                    impGetLine(aBottomLine, rTableLayouter, bIsRTL?nX-1:nX, nYBottom, true, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aRightLine, rTableLayouter, nXRight, nY, false, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aTopLine, rTableLayouter, bIsRTL?nX-1:nX, nY, true, nColCount, nRowCount, bIsRTL);
                                    const svx::frame::Style aBottomLine(impGetLineStyle(rTableLayouter, bIsRTL?nX-1:nX, nYBottom, true, nColCount, nRowCount, bIsRTL));
                                    const svx::frame::Style aRightLine(impGetLineStyle(rTableLayouter, nXRight, nY, false, nColCount, nRowCount, bIsRTL));
                                    const svx::frame::Style aTopLine(impGetLineStyle(rTableLayouter, bIsRTL?nX-1:nX, nY, true, nColCount, nRowCount, bIsRTL));

                                    // get the neighbor cells' borders
                                    impGetLine(aLeftFromTLine, rTableLayouter, nX, nY - 1, false, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aLeftFromBLine, rTableLayouter, nX, nYBottom + 1, false, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aRightFromTLine, rTableLayouter, nXRight, nY - 1, false, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aRightFromBLine, rTableLayouter, nXRight, nYBottom + 1, false, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aTopFromLLine, rTableLayouter, nX - 1, nY, true, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aTopFromRLine, rTableLayouter, nXRight + 1, nY, true, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aBottomFromLLine, rTableLayouter, nX - 1, nYBottom, true, nColCount, nRowCount, bIsRTL);
                                    impGetLine(aBottomFromRLine, rTableLayouter, nXRight + 1, nYBottom, true, nColCount, nRowCount, bIsRTL);
                                    if(aLeftLine.IsUsed() || aBottomLine.IsUsed() || aRightLine.IsUsed() || aTopLine.IsUsed())
                                    {
                                        // get the neighbor cells' borders
                                        const svx::frame::Style aLeftFromTLine(impGetLineStyle(rTableLayouter, nX, nY - 1, false, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aLeftFromBLine(impGetLineStyle(rTableLayouter, nX, nYBottom + 1, false, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aRightFromTLine(impGetLineStyle(rTableLayouter, nXRight, nY - 1, false, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aRightFromBLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom + 1, false, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aTopFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nY, true, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aTopFromRLine(impGetLineStyle(rTableLayouter, nXRight + 1, nY, true, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aBottomFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nYBottom, true, nColCount, nRowCount, bIsRTL));
                                        const svx::frame::Style aBottomFromRLine(impGetLineStyle(rTableLayouter, nXRight + 1, nYBottom, true, nColCount, nRowCount, bIsRTL));

                                    // create the primtive containing all data for one cell with borders
                                    xBorderSequence[nBorderInsert++] = drawinglayer::primitive2d::Primitive2DReference(
                                        new drawinglayer::primitive2d::SdrBorderlinePrimitive2D(
                                            aCellMatrix,
                                            aLeftLine,
                                            aBottomLine,
                                            aRightLine,
                                            aTopLine,
                                            aLeftFromTLine,
                                            aLeftFromBLine,
                                            aRightFromTLine,
                                            aRightFromBLine,
                                            aTopFromLLine,
                                            aTopFromRLine,
                                            aBottomFromLLine,
                                            aBottomFromRLine,
                                            bIsRTL ? nX == nColCount : 0 == nX,
                                            nRowCount == nYBottom,
                                            bIsRTL ? 0 == nXRight : nXRight == nColCount,
                                            0 == nY));
                                        // get cell coordinate system
                                        const basegfx::B2DPoint aOrigin(aCellMatrix * basegfx::B2DPoint(0.0, 0.0));
                                        const basegfx::B2DVector aX(aCellMatrix * basegfx::B2DVector(1.0, 0.0));
                                        const basegfx::B2DVector aY(aCellMatrix * basegfx::B2DVector(0.0, 1.0));
                                        const double fTwipsToMM(127.0 / 72.0);

                                        if(aLeftLine.IsUsed())
                                        {
                                            createForVector(aBorderSequence, aOrigin, aY, aLeftLine,
                                                aTopLine, aLeftFromTLine, aTopFromLLine,
                                                aBottomLine, aLeftFromBLine, aBottomFromLLine);
                                        }

                                        if(aBottomLine.IsUsed())
                                        {
                                            createForVector(aBorderSequence, aOrigin + aY, aX, aBottomLine,
                                                aLeftLine, aBottomFromLLine, aLeftFromBLine,
                                                aRightLine, aBottomFromRLine, aRightFromBLine);
                                        }

                                        if(aRightLine.IsUsed())
                                        {
                                            createForVector(aBorderSequence, aOrigin + aX, aY, aRightLine,
                                                aTopFromRLine, aRightFromTLine, aTopLine,
                                                aBottomFromRLine, aRightFromBLine, aBottomLine);
                                        }

                                        if(aTopLine.IsUsed())
                                        {
                                            createForVector(aBorderSequence, aOrigin, aX, aTopLine,
                                                aLeftFromTLine, aTopFromLLine, aLeftLine,
                                                aRightFromTLine, aTopFromRLine, aRightLine);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // no empty references; reallocate sequences by used count
                    xCellSequence.resize(nCellInsert);
                    xBorderSequence.resize(nBorderInsert);

                    // append to target. We want fillings and text first
                    xRetval = xCellSequence;
                    xRetval.append(xBorderSequence);
                    // append Border info to target. We want fillings and text first
                    aRetval.append(aBorderSequence);
                }

                if(!xRetval.empty())
                if(!aRetval.empty())
                {
                    // check and create evtl. shadow for created content
                    const SfxItemSet& rObjectItemSet = rTableObj.GetMergedItemSet();
@@ -767,11 +398,11 @@ namespace sdr

                    if(!aNewShadowAttribute.isDefault())
                    {
                        xRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive(xRetval, aNewShadowAttribute);
                        aRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive(aRetval, aNewShadowAttribute);
                    }
                }

                return xRetval;
                return aRetval;
            }
            else
            {
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index e43e60f..63b5064 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2745,7 +2745,7 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
                    aPaintEnd.Y() = aUpperAligned.Bottom_();
            }

            if(aStyles[0].Prim())
            if(aStyles[0].IsUsed())
            {
                drawinglayer::primitive2d::Primitive2DContainer aSequence;

@@ -2760,13 +2760,13 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
                        svx::frame::StyleVectorTable aStartTable;
                        svx::frame::StyleVectorTable aEndTable;

                        if(aStyles[ 1 ].Prim()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], -aY)); // aLFromT
                        if(aStyles[ 2 ].Prim()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX)); // aLFromL
                        if(aStyles[ 3 ].Prim()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], aY)); // aLFromB
                        if(aStyles[ 1 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], -aY)); // aLFromT
                        if(aStyles[ 2 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX)); // aLFromL
                        if(aStyles[ 3 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], aY)); // aLFromB

                        if(aStyles[ 4 ].Prim()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], -aY)); // aRFromT
                        if(aStyles[ 5 ].Prim()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX)); // aRFromR
                        if(aStyles[ 6 ].Prim()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], aY)); // aRFromB
                        if(aStyles[ 4 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], -aY)); // aRFromT
                        if(aStyles[ 5 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX)); // aRFromR
                        if(aStyles[ 6 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], aY)); // aRFromB

                        CreateBorderPrimitives(
                            aSequence,
@@ -2790,13 +2790,13 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
                        svx::frame::StyleVectorTable aStartTable;
                        svx::frame::StyleVectorTable aEndTable;

                        if(aStyles[ 3 ].Prim()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], -aY)); // aTFromR
                        if(aStyles[ 2 ].Prim()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX)); // aTFromT
                        if(aStyles[ 1 ].Prim()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], aY)); // aTFromL
                        if(aStyles[ 3 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], -aY)); // aTFromR
                        if(aStyles[ 2 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX)); // aTFromT
                        if(aStyles[ 1 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], aY)); // aTFromL

                        if(aStyles[ 6 ].Prim()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], -aY)); // aBFromR
                        if(aStyles[ 5 ].Prim()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX)); // aBFromB
                        if(aStyles[ 4 ].Prim()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], aY)); // aBFromL
                        if(aStyles[ 6 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], -aY)); // aBFromR
                        if(aStyles[ 5 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX)); // aBFromB
                        if(aStyles[ 4 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], aY)); // aBFromL

                        CreateBorderPrimitives(
                            aSequence,
@@ -2965,14 +2965,14 @@ void SwTabFramePainter::Insert( const SwFrame& rFrame, const SvxBoxItem& rBoxIte
    const Fraction& rFracX = rMapMode.GetScaleX();
    const Fraction& rFracY = rMapMode.GetScaleY();

    svx::frame::Style aL(rBoxItem.GetLeft());
    aL.SetPatternScale(double(rFracY));
    svx::frame::Style aR(rBoxItem.GetRight());
    aR.SetPatternScale(double(rFracY));
    svx::frame::Style aT(rBoxItem.GetTop());
    aT.SetPatternScale(double(rFracX));
    svx::frame::Style aB(rBoxItem.GetBottom());
    aB.SetPatternScale(double(rFracX));
    svx::frame::Style aL(rBoxItem.GetLeft(), rFracY);
//    aL.SetPatternScale(rFracY);
    svx::frame::Style aR(rBoxItem.GetRight(), rFracY);
//    aR.SetPatternScale(rFracY);
    svx::frame::Style aT(rBoxItem.GetTop(), rFracX);
//    aT.SetPatternScale(rFracX);
    svx::frame::Style aB(rBoxItem.GetBottom(), rFracX);
//    aB.SetPatternScale(rFracX);

    aR.MirrorSelf();
    aB.MirrorSelf();
diff --git a/sw/source/ui/table/tautofmt.cxx b/sw/source/ui/table/tautofmt.cxx
index ab2650d..bac50df 100644
--- a/sw/source/ui/table/tautofmt.cxx
+++ b/sw/source/ui/table/tautofmt.cxx
@@ -836,7 +836,7 @@ void AutoFormatPreview::PaintCells(vcl::RenderContext& rRenderContext)

        if (pProcessor2D)
        {
            maArray.DrawArray(*pProcessor2D.get());
            pProcessor2D->process(maArray.CreateB2DPrimitiveArray());
            pProcessor2D.reset();
        }
    }