SwFrameBorder: Replaced BorderGeometry creation partially

Replaced BorderGeometry creation in SwFrame::PaintSwFrameShadowAndBorder,
moved to tooling method CreateBorderLinePrimitivesForRectangle. Preparing
using that tooling method also in PaintCharacterBorder to make borders
work in TextPassages, too

Change-Id: I73fe3d04597bd0e6dc83ac719548a44d0637b622
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index ad733b8..882c9a4 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -4752,143 +4752,6 @@ static void lcl_MakeBorderLine(SwRect const& rRect,
    properties.pBLines->AddBorderLine(aLine);
}

/**
 * OD 19.05.2003 #109667# - merge <lcl_PaintLeftLine> and <lcl_PaintRightLine>
 * into new method <lcl_PaintLeftRightLine(..)>
 */
static void lcl_PaintLeftRightLine( const bool         _bLeft,
                             const SwFrame&           _rFrame,
                             const SwRect&          _rOutRect,
                             const SwBorderAttrs&   _rAttrs,
                             const SwRectFn&        _rRectFn,
                             SwPaintProperties& properties)
{
    const SvxBoxItem& rBox = _rAttrs.GetBox();
    const bool bR2L = _rFrame.IsCellFrame() && _rFrame.IsRightToLeft();
    const SvxBorderLine* pLeftRightBorder = nullptr;
    const SvxBorderLine* pTopBorder = rBox.GetTop();
    const SvxBorderLine* pBottomBorder = rBox.GetBottom();

    if ( _bLeft )
    {
        pLeftRightBorder = bR2L ? rBox.GetRight() : rBox.GetLeft();
    }
    else
    {
        pLeftRightBorder = bR2L ? rBox.GetLeft() : rBox.GetRight();
    }

    if ( !pLeftRightBorder )
    {
        return;
    }

    SwRect aRect( _rOutRect );
    if ( _bLeft )
    {
        (aRect.*_rRectFn->fnAddRight)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ), properties ) -
                                       (aRect.*_rRectFn->fnGetWidth)() );

        // Shift the left border to the left.
        Point aCurPos = aRect.Pos();
        const sal_uInt16 nOffset = pLeftRightBorder->GetDistance();
        aCurPos.X() -= nOffset;
        aCurPos.Y() -= nOffset;
        aRect.Pos(aCurPos);
        Size aCurSize = aRect.SSize();
        aCurSize.Height() += nOffset * 2;
        aRect.SSize(aCurSize);
    }
    else
    {
        (aRect.*_rRectFn->fnSubLeft)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ), properties ) -
                                      (aRect.*_rRectFn->fnGetWidth)() );
    }

    if ( _rFrame.IsContentFrame() )
    {
        ::lcl_ExtendLeftAndRight( aRect, _rFrame, _rAttrs, _rRectFn );

        // No Top / bottom borders for joint borders
        if ( _rAttrs.JoinedWithPrev( _rFrame ) ) pTopBorder = nullptr;
        if ( _rAttrs.JoinedWithNext( _rFrame ) ) pBottomBorder = nullptr;
    }

    if ( !pLeftRightBorder->GetInWidth() )
    {
        // OD 06.05.2003 #107169# - init boolean indicating printer output device.
        const bool bPrtOutputDev =
                ( OUTDEV_PRINTER == properties.pSGlobalShell->GetOut()->GetOutDevType() );

        // OD 06.05.2003 #107169# - add 6th parameter
        ::lcl_SubTopBottom( aRect, rBox, _rAttrs, _rFrame, _rRectFn, bPrtOutputDev, properties);
    }

    if ( lcl_GetLineWidth( pLeftRightBorder ) > 0 )
    {
        lcl_MakeBorderLine(
            aRect, true, _bLeft, aRect.Height() > aRect.Width(),
            *pLeftRightBorder, pTopBorder, pBottomBorder, properties);
    }
}

/**
 * OD 19.05.2003 #109667# - merge <lcl_PaintTopLine> and <lcl_PaintBottomLine>
 * into <lcl_PaintTopLine>
 */
static void lcl_PaintTopBottomLine( const bool         _bTop,
                             const SwRect&          _rOutRect,
                             const SwBorderAttrs&   _rAttrs,
                             const SwRectFn&        _rRectFn,
                             SwPaintProperties& properties)
{
    const SvxBoxItem& rBox = _rAttrs.GetBox();
    const SvxBorderLine* pTopBottomBorder = nullptr;

    if ( _bTop )
    {
        pTopBottomBorder = rBox.GetTop();
    }
    else
    {
        pTopBottomBorder = rBox.GetBottom();
    }

    if ( !pTopBottomBorder )
    {
        return;
    }

    SwRect aRect( _rOutRect );
    if ( _bTop )
    {
        (aRect.*_rRectFn->fnAddBottom)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ), properties ) -
                                        (aRect.*_rRectFn->fnGetHeight)() );

        // Push the top border up a bit.
        const sal_uInt16 nOffset = pTopBottomBorder->GetDistance();
        Point aCurPos = aRect.Pos();
        aCurPos.X() -= nOffset;
        aCurPos.Y() -= nOffset;
        aRect.Pos(aCurPos);
        Size aCurSize = aRect.SSize();
        aCurSize.Width() += nOffset * 2;
        aRect.SSize(aCurSize);
    }
    else
    {
        (aRect.*_rRectFn->fnSubTop)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ), properties ) -
                                     (aRect.*_rRectFn->fnGetHeight)() );
    }

    if ( lcl_GetLineWidth( pTopBottomBorder ) > 0 )
    {
        lcl_MakeBorderLine(
            aRect, false, _bTop, aRect.Height() > aRect.Width(),
            *pTopBottomBorder, rBox.GetLeft(), rBox.GetRight(), properties);
    }
}

void PaintCharacterBorder(
    const SwFont& rFont,
    const SwRect& rPaintArea,
@@ -5240,9 +5103,162 @@ void SwFrame::ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DCon
    }
}

namespace
{
    void CreateBorderLinePrimitivesForRectangle(
        drawinglayer::primitive2d::Primitive2DContainer& rBorderLineTarget,
        const svx::frame::Style& rStyleLeft,
        const svx::frame::Style& rStyleRight,
        const svx::frame::Style& rStyleTop,
        const svx::frame::Style& rStyleBottom,
        basegfx::B2DPoint aTopLeft,
        basegfx::B2DPoint aTopRight,
        basegfx::B2DPoint aBottomLeft,
        basegfx::B2DPoint aBottomRight)
    {
        if(rStyleTop.IsUsed())
        {
            // move top left/right inwards half border width
            aTopLeft.setY(aTopLeft.getY() + (rStyleTop.GetWidth() * 0.5));
            aTopRight.setY(aTopRight.getY() + (rStyleTop.GetWidth() * 0.5));
        }

        if(rStyleBottom.IsUsed())
        {
            // move bottom left/right inwards half border width
            aBottomLeft.setY(aBottomLeft.getY() - (rStyleBottom.GetWidth() * 0.5));
            aBottomRight.setY(aBottomRight.getY() - (rStyleBottom.GetWidth() * 0.5));
        }

        if(rStyleLeft.IsUsed())
        {
            // move left top/bottom inwards half border width
            aTopLeft.setX(aTopLeft.getX() + (rStyleLeft.GetWidth() * 0.5));
            aBottomLeft.setX(aBottomLeft.getX() + (rStyleLeft.GetWidth() * 0.5));
        }

        if(rStyleRight.IsUsed())
        {
            // move right top/bottom inwards half border width
            aTopRight.setX(aTopRight.getX() - (rStyleRight.GetWidth() * 0.5));
            aBottomRight.setX(aBottomRight.getX() - (rStyleRight.GetWidth() * 0.5));
        }

        if(rStyleTop.IsUsed())
        {
            // create BorderPrimitive(s) for top border
            const basegfx::B2DVector aVector(aTopRight - aTopLeft);
            svx::frame::StyleVectorTable aStartStyleVectorTable;
            svx::frame::StyleVectorTable aEndStyleVectorTable;

            if(rStyleLeft.IsUsed())
            {
                aStartStyleVectorTable.add(rStyleLeft, aVector, basegfx::B2DVector(aBottomLeft - aTopLeft), false);
            }

            if(rStyleRight.IsUsed())
            {
                aEndStyleVectorTable.add(rStyleRight, -aVector, basegfx::B2DVector(aBottomRight - aTopRight), false);
            }

            CreateBorderPrimitives(
                rBorderLineTarget,
                aTopLeft,
                aVector,
                rStyleTop,
                aStartStyleVectorTable,
                aEndStyleVectorTable,
                nullptr);
        }

        if(rStyleBottom.IsUsed())
        {
            // create BorderPrimitive(s) for bottom border
            const basegfx::B2DVector aVector(aBottomRight - aBottomLeft);
            svx::frame::StyleVectorTable aStartStyleVectorTable;
            svx::frame::StyleVectorTable aEndStyleVectorTable;

            if(rStyleLeft.IsUsed())
            {
                aStartStyleVectorTable.add(rStyleLeft, aVector, basegfx::B2DVector(aTopLeft - aBottomLeft), true);
            }

            if(rStyleRight.IsUsed())
            {
                aEndStyleVectorTable.add(rStyleRight, -aVector, basegfx::B2DVector(aTopRight - aBottomRight), true);
            }

            CreateBorderPrimitives(
                rBorderLineTarget,
                aBottomLeft,
                aVector,
                rStyleBottom,
                aStartStyleVectorTable,
                aEndStyleVectorTable,
                nullptr);
        }

        if(rStyleLeft.IsUsed())
        {
            // create BorderPrimitive(s) for left border
            const basegfx::B2DVector aVector(aBottomLeft - aTopLeft);
            svx::frame::StyleVectorTable aStartStyleVectorTable;
            svx::frame::StyleVectorTable aEndStyleVectorTable;

            if(rStyleTop.IsUsed())
            {
                aStartStyleVectorTable.add(rStyleTop, aVector, basegfx::B2DVector(aTopRight - aTopLeft), false);
            }

            if(rStyleBottom.IsUsed())
            {
                aEndStyleVectorTable.add(rStyleBottom, -aVector, basegfx::B2DVector(aBottomRight - aBottomLeft), false);
            }

            CreateBorderPrimitives(
                rBorderLineTarget,
                aTopLeft,
                aVector,
                rStyleLeft,
                aStartStyleVectorTable,
                aEndStyleVectorTable,
                nullptr);
        }

        if(rStyleRight.IsUsed())
        {
            // create BorderPrimitive(s) for right border
            const basegfx::B2DVector aVector(aBottomRight - aTopRight);
            svx::frame::StyleVectorTable aStartStyleVectorTable;
            svx::frame::StyleVectorTable aEndStyleVectorTable;

            if(rStyleTop.IsUsed())
            {
                aStartStyleVectorTable.add(rStyleTop, aVector, basegfx::B2DVector(aTopLeft - aTopRight), true);
            }

            if(rStyleBottom.IsUsed())
            {
                aEndStyleVectorTable.add(rStyleBottom, -aVector, basegfx::B2DVector(aBottomLeft - aBottomRight), true);
            }

            CreateBorderPrimitives(
                rBorderLineTarget,
                aTopRight,
                aVector,
                rStyleRight,
                aStartStyleVectorTable,
                aEndStyleVectorTable,
                nullptr);
        }
    }
} // end of anonymous namespace

/// Paints shadows and borders
void SwFrame::PaintSwFrameShadowAndBorder( const SwRect& rRect, const SwPageFrame *pPage,
                         const SwBorderAttrs &rAttrs ) const
void SwFrame::PaintSwFrameShadowAndBorder(
    const SwRect& rRect,
    const SwPageFrame *pPage,
    const SwBorderAttrs &rAttrs) const
{
    // There's nothing (Row,Body,Footnote,Root,Column,NoText) need to do here
    if (GetType() & (SwFrameType::NoTxt|SwFrameType::Row|SwFrameType::Body|SwFrameType::Ftn|SwFrameType::Column|SwFrameType::Root))
@@ -5320,61 +5336,96 @@ void SwFrame::PaintSwFrameShadowAndBorder( const SwRect& rRect, const SwPageFram
        }
    }

    if ( !pPage )
        pPage = FindPageFrame();

    ::lcl_CalcBorderRect( aRect, this, rAttrs, true, gProp );
    rAttrs.SetGetCacheLine( true );
    if ( bShadow )
        PaintShadow( rRect, aRect, rAttrs );

    if(bShadow)
    {
        PaintShadow(rRect, aRect, rAttrs);
    }

    // OD 27.09.2002 #103636# - suspend drawing of border
    // add condition < NOT bDrawOnlyShadowForTransparentFrame > - see above
    // - add condition <bFoundCellForTopOrBorderAttrs>
    //-hack.
    if ( ( bLine || bFoundCellForTopOrBorderAttrs ) &&
         !bDrawOnlyShadowForTransparentFrame )
    if((bLine || bFoundCellForTopOrBorderAttrs) && !bDrawOnlyShadowForTransparentFrame)
    {
        const SwFrame* pDirRefFrame = IsCellFrame() ? FindTabFrame() : this;
        SwRectFnSet aRectFnSet(pDirRefFrame);
        ::lcl_PaintLeftRightLine ( true, *(this), aRect, rAttrs, aRectFnSet.FnRect(), gProp);
        ::lcl_PaintLeftRightLine ( false, *(this), aRect, rAttrs, aRectFnSet.FnRect(), gProp);
        if ( !IsContentFrame() || rAttrs.GetTopLine( *(this) ) )
        // define SvxBorderLine(s) to use
        const SvxBoxItem& rBox(rAttrs.GetBox());
        const SvxBorderLine* pLeftBorder(rBox.GetLeft());
        const SvxBorderLine* pRightBorder(rBox.GetRight());
        const SvxBorderLine* pTopBorder(rBox.GetTop());
        const SvxBorderLine* pBottomBorder(rBox.GetBottom());

        // if R2L, exchange Right/Left
        const bool bR2L(IsCellFrame() && IsRightToLeft());

        if(bR2L)
        {
            // -
            //-hack
            // paint is found, paint its top border.
            if ( IsCellFrame() && pCellFrameForTopBorderAttrs != this )
            std::swap(pLeftBorder, pRightBorder);
        }

        // if ContentFrame and joined Prev/Next, reset top/bottom as needed
        if(IsContentFrame())
        {
            if(rAttrs.JoinedWithPrev(*this))
            {
                SwBorderAttrAccess aAccess( SwFrame::GetCache(),
                                            pCellFrameForTopBorderAttrs );
                const SwBorderAttrs &rTopAttrs = *aAccess.Get();
                ::lcl_PaintTopBottomLine( true, aRect, rTopAttrs, aRectFnSet.FnRect(), gProp);
                    pTopBorder = nullptr;
            }
            else

            if(rAttrs.JoinedWithNext(*this))
            {
                ::lcl_PaintTopBottomLine( true, aRect, rAttrs, aRectFnSet.FnRect(), gProp );
                    pBottomBorder = nullptr;
            }
        }
        if ( !IsContentFrame() || rAttrs.GetBottomLine( *(this) ) )

        // necessary to replace TopBorder?
        if((!IsContentFrame() || rAttrs.GetTopLine(*this)) && IsCellFrame() && pCellFrameForTopBorderAttrs != this)
        {
            // -
            //-hack
            // paint is found, paint its bottom border.
            if ( IsCellFrame() && pCellFrameForBottomBorderAttrs != this )
            SwBorderAttrAccess aAccess(SwFrame::GetCache(), pCellFrameForTopBorderAttrs);
            pTopBorder = aAccess.Get()->GetBox().GetTop();
        }

        // necessary to replace BottomBorder?
        if((!IsContentFrame() || rAttrs.GetBottomLine(*this)) && IsCellFrame() && pCellFrameForBottomBorderAttrs != this)
        {
            SwBorderAttrAccess aAccess(SwFrame::GetCache(), pCellFrameForBottomBorderAttrs);
            pBottomBorder = aAccess.Get()->GetBox().GetBottom();
        }

        if(nullptr != pLeftBorder || nullptr != pRightBorder || nullptr != pTopBorder || nullptr != pBottomBorder)
        {
            // now we have all SvxBorderLine(s) sorted out, create geometry
            const svx::frame::Style aStyleLeft(pLeftBorder, 1.0);
            const svx::frame::Style aStyleRight(pRightBorder, 1.0);
            const svx::frame::Style aStyleTop(pTopBorder, 1.0);
            const svx::frame::Style aStyleBottom(pBottomBorder, 1.0);
            drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget;

            CreateBorderLinePrimitivesForRectangle(
                aBorderLineTarget,
                aStyleLeft,
                aStyleRight,
                aStyleTop,
                aStyleBottom,
                basegfx::B2DPoint(aRect.Left(), aRect.Top()),       // TopLeft
                basegfx::B2DPoint(aRect.Right(), aRect.Top()),      // TopRight
                basegfx::B2DPoint(aRect.Left(), aRect.Bottom()),    // BottomLeft
                basegfx::B2DPoint(aRect.Right(), aRect.Bottom()));  // BottomRight

            if(!aBorderLineTarget.empty())
            {
                SwBorderAttrAccess aAccess( SwFrame::GetCache(),
                                            pCellFrameForBottomBorderAttrs );
                const SwBorderAttrs &rBottomAttrs = *aAccess.Get();
                ::lcl_PaintTopBottomLine(false, aRect, rBottomAttrs, aRectFnSet.FnRect(), gProp);
                for(drawinglayer::primitive2d::Primitive2DContainer::const_iterator it(aBorderLineTarget.begin()); it != aBorderLineTarget.end(); ++it)
                {
                    gProp.pBLines->AddBorderLine(*it);
                }
            }
            else
            {
                ::lcl_PaintTopBottomLine(false, aRect, rAttrs, aRectFnSet.FnRect(), gProp);
            }

            bool bBla = true;
        }
    }
    rAttrs.SetGetCacheLine( false );

    rAttrs.SetGetCacheLine( false );
}

/**