[Libreoffice-commits] core.git: 9 commits - include/svx sc/source svx/Library_svxcore.mk svx/Library_svx.mk svx/source sw/source

Armin Le Grand Armin.Le.Grand at cib.de
Mon Jan 29 09:23:52 UTC 2018


 include/svx/framelink.hxx                  |   12 
 include/svx/framelinkarray.hxx             |    8 
 sc/source/ui/inc/output.hxx                |    7 
 sc/source/ui/miscdlgs/autofmt.cxx          |    4 
 sc/source/ui/view/gridwin4.cxx             |    4 
 sc/source/ui/view/output.cxx               |    3 
 svx/Library_svx.mk                         |    1 
 svx/Library_svxcore.mk                     |    1 
 svx/source/dialog/framelink.cxx            |   12 
 svx/source/dialog/framelinkarray.cxx       |  472 +++++++++++++++--------------
 svx/source/dialog/frmsel.cxx               |    4 
 svx/source/table/viewcontactoftableobj.cxx |  197 +++++-------
 sw/source/core/layout/paintfrm.cxx         |   22 +
 sw/source/ui/table/tautofmt.cxx            |    4 
 14 files changed, 378 insertions(+), 373 deletions(-)

New commits:
commit 75802ae40ae67737ae9e4f1a38434e0587affff6
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Sun Jan 28 12:19:00 2018 +0100

    BorderlineFix: Corrected wrong indexing in Array initialization
    
    Change-Id: I4222ef1c82620a05cea9f6db1a0664196cfb3bd4

diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 4a5741cd0545..91b55bb5e8b4 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -234,7 +234,7 @@ namespace sdr
                     svx::frame::Array aArray;
 
                     // initialize CellBorderArray for primitive creation
-                    aArray.Initialize(nRowCount, nColCount);
+                    aArray.Initialize(nColCount, nRowCount);
 
                     // create single primitives per cell
                     for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
commit 753b35b27e3657db39f5d398a733879ef23b7c51
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Jan 24 15:25:40 2018 +0100

    BorderlineFix: Use svx::frame::Array tooling in Draw/Impress
    
    For creating the needed BorderPrimitives for TableCells for the
    Tables used in Draw/Impress, adapt the ViewContactOfTableObj doing
    this to use svx::frame::Array tooling now. This will correct the
    error for not taking the neighboured connects for merged cells
    into account and unify one more space to the same tooling.
    
    Change-Id: I2e6f732985e9b963359f156628bd29ddfec1a80c

diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk
index 6bdbadaf2e3b..ad1b1dc3a423 100644
--- a/svx/Library_svx.mk
+++ b/svx/Library_svx.mk
@@ -128,7 +128,6 @@ $(eval $(call gb_Library_add_exception_objects,svx,\
     svx/source/dialog/fntctrl \
     svx/source/dialog/fontlb \
     svx/source/dialog/fontwork \
-    svx/source/dialog/framelinkarray \
     svx/source/dialog/frmdirlbox \
     svx/source/dialog/frmsel \
     svx/source/dialog/graphctl \
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 5bfbf899034d..603860d7f11b 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -116,6 +116,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
     svx/source/dialog/dlgutil \
     svx/source/dialog/hexcolorcontrol \
     svx/source/dialog/framelink \
+    svx/source/dialog/framelinkarray \
     svx/source/dialog/langbox \
     svx/source/dialog/pagenumberlistbox \
     svx/source/dialog/papersizelistbox \
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index bc8a50a3d3cf..7cd4b26027dc 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -21,6 +21,7 @@
 
 #include <math.h>
 #include <vector>
+#include <set>
 #include <algorithm>
 #include <vcl/outdev.hxx>
 #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 448a0b407f2a..4a5741cd0545 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -36,8 +36,10 @@
 #include <drawinglayer/attribute/sdrlineattribute.hxx>
 #include <drawinglayer/attribute/sdrshadowattribute.hxx>
 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <svx/framelink.hxx>
+#include <svx/framelinkarray.hxx>
 
 #include <cell.hxx>
 #include "tablelayouter.hxx"
@@ -196,42 +198,6 @@ namespace sdr
             return svx::frame::Style();
         }
 
-        void createForVector(bool bHor, 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
-            const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX));
-
-            /// Fill top-left Style Table
-            svx::frame::StyleVectorTable aStart;
-
-            aStart.add(rLeftA, rX, -aY, bHor); // bHor ? true : false));
-            aStart.add(rLeftB, rX, -rX, true); // bHor ? true : true));
-            aStart.add(rLeftC, rX, aY, !bHor); // bHor ? false : true));
-            aStart.sort();
-
-            /// Fill bottom-right Style Table
-            svx::frame::StyleVectorTable aEnd;
-            const basegfx::B2DVector aAxis(-rX);
-
-            aEnd.add(rRightA, aAxis, -aY, bHor); // bHor ? true : false));
-            aEnd.add(rRightB, aAxis, rX, false); // bHor ? false : false));
-            aEnd.add(rRightC, aAxis, aY, !bHor); // bHor ? false : true));
-            aEnd.sort();
-
-            CreateBorderPrimitives(
-                rContainer,
-                rOrigin,
-                rX,
-                rLine,
-                aStart,
-                aEnd,
-                nullptr
-            );
-        }
-
         drawinglayer::primitive2d::Primitive2DContainer ViewContactOfTableObj::createViewIndependentPrimitive2DSequence() const
         {
             const sdr::table::SdrTableObj& rTableObj = static_cast<const sdr::table::SdrTableObj&>(GetSdrObject());
@@ -249,7 +215,7 @@ namespace sdr
 
                 if(nAllCount)
                 {
-                    const sdr::table::TableLayouter& rTableLayouter = rTableObj.getTableLayouter();
+                    const sdr::table::TableLayouter& rTableLayouter(rTableObj.getTableLayouter());
                     const bool bIsRTL(css::text::WritingMode_RL_TB == rTableObj.GetWritingMode());
                     sdr::table::CellPos aCellPos;
                     sdr::table::CellRef xCurrentCell;
@@ -258,19 +224,59 @@ namespace sdr
                     // create range using the model data directly. This is in SdrTextObj::aRect which i will access using
                     // GetGeoRect() to not trigger any calculations. It's the unrotated geometry.
                     const tools::Rectangle& rObjectRectangle(rTableObj.GetGeoRect());
-                    const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom());
+                    const basegfx::B2DRange aObjectRange(
+                        rObjectRectangle.Left(), rObjectRectangle.Top(),
+                        rObjectRectangle.Right(), rObjectRectangle.Bottom());
+
+                    // To create the CellBorderPrimitives, use the tolling from svx::frame::Array
+                    // which is capable of creating the needed visualization. Fill it during the
+                    // anyways needed run over the table.
+                    svx::frame::Array aArray;
 
-                    // 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 aBorderSequence;
+                    // initialize CellBorderArray for primitive creation
+                    aArray.Initialize(nRowCount, nColCount);
 
                     // create single primitives per cell
                     for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
                     {
+                        // add RowHeight to CellBorderArray for primitive creation
+                        aArray.SetRowHeight(aCellPos.mnRow, rTableLayouter.getRowHeight(aCellPos.mnRow));
+
                         for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++)
                         {
+                            // add ColWidth to CellBorderArray for primitive creation, only
+                            // needs to be done in the 1st run
+                            if(0 == aCellPos.mnRow)
+                            {
+                                aArray.SetColWidth(aCellPos.mnCol, rTableLayouter.getColumnWidth(aCellPos.mnCol));
+                            }
+
+                            // access the cell
                             xCurrentCell.set(dynamic_cast< sdr::table::Cell* >(xTable->getCellByPosition(aCellPos.mnCol, aCellPos.mnRow).get()));
 
+                            if(xCurrentCell.is())
+                            {
+                                // copy styles for current cell to CellBorderArray for primitive creation
+                                aArray.SetCellStyleLeft(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleRight(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol + 1, aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleTop(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, true, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleBottom(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow + 1, true, nColCount, nRowCount, bIsRTL));
+
+                                // ignore merged cells (all except the top-left of a merged cell)
+                                if(!xCurrentCell->isMerged())
+                                {
+                                    // check if we are the top-left of a merged cell
+                                    const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
+                                    const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
+
+                                    if(nXSpan > 1 || nYSpan > 1)
+                                    {
+                                        // if merged, set so at CellBorderArray for primitive creation
+                                        aArray.SetMergedRange(aCellPos.mnCol, aCellPos.mnRow, aCellPos.mnCol + nXSpan - 1, aCellPos.mnRow + nYSpan - 1);
+                                    }
+                                }
+                            }
+
                             if(xCurrentCell.is() && !xCurrentCell->isMerged())
                             {
                                 if(rTableLayouter.getCellArea(xCurrentCell, aCellPos, aCellArea))
@@ -318,77 +324,54 @@ namespace sdr
                                                 aCellMatrix, aAttribute));
                                         aRetval.append(xCellReference);
                                     }
-
-                                    // handle cell borders
-                                    const sal_Int32 nX(bIsRTL ? nColCount - aCellPos.mnCol : aCellPos.mnCol);
-                                    const sal_Int32 nY(aCellPos.mnRow);
-
-                                    // get access values for X,Y at the cell's end
-                                    const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
-                                    const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
-                                    const sal_Int32 nXRight(bIsRTL ? nX - nXSpan : nX + nXSpan);
-                                    const sal_Int32 nYBottom(nY + nYSpan);
-
-                                    // get basic lines
-                                    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
-                                    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));
-
-                                    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, 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, 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, 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, nYBottom, true, nColCount, nRowCount, bIsRTL));
-
-                                        // 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));
-
-                                        if(aLeftLine.IsUsed())
-                                        {
-                                            createForVector(false, aBorderSequence, aOrigin, aY, aLeftLine,
-                                                aTopLine, aLeftFromTLine, aTopFromLLine,
-                                                aBottomLine, aLeftFromBLine, aBottomFromLLine);
-                                        }
-
-                                        if(aBottomLine.IsUsed())
-                                        {
-                                            createForVector(true, aBorderSequence, aOrigin + aY, aX, aBottomLine,
-                                                aLeftLine, aBottomFromLLine, aLeftFromBLine,
-                                                aRightLine, aBottomFromRLine, aRightFromBLine);
-                                        }
-
-                                        if(aRightLine.IsUsed())
-                                        {
-                                            createForVector(false, aBorderSequence, aOrigin + aX, aY, aRightLine,
-                                                aTopFromRLine, aRightFromTLine, aTopLine,
-                                                aBottomFromRLine, aRightFromBLine, aBottomLine);
-                                        }
-
-                                        if(aTopLine.IsUsed())
-                                        {
-                                            createForVector(true, aBorderSequence, aOrigin, aX, aTopLine,
-                                                aLeftFromTLine, aTopFromLLine, aLeftLine,
-                                                aRightFromTLine, aTopFromRLine, aRightLine);
-                                        }
-                                    }
                                 }
                             }
                         }
                     }
 
-                    // append Border info to target. We want fillings and text first
-                    aRetval.append(aBorderSequence);
+                    // now create all CellBorderPrimitives
+                    const drawinglayer::primitive2d::Primitive2DContainer aCellBorderPrimitives(aArray.CreateB2DPrimitiveArray());
+
+                    if(!aCellBorderPrimitives.empty())
+                    {
+                        // this is already scaled (due to Table in non-uniform coordinates), so
+                        // first transform removing scale
+                        basegfx::B2DHomMatrix aTransform(
+                            basegfx::utils::createScaleB2DHomMatrix(
+                                1.0 / aObjectRange.getWidth(),
+                                1.0 / aObjectRange.getHeight()));
+
+                        // If RTL, mirror the whole unified table in X and move right.
+                        // This is much easier than taking this into account for the whole
+                        // index calcualtions
+                        if(bIsRTL)
+                        {
+                            aTransform.scale(-1.0, 1.0);
+                            aTransform.translate(1.0, 0.0);
+                        }
+
+                        // create object matrix
+                        const GeoStat& rGeoStat(rTableObj.GetGeoStat());
+                        const double fShearX(rGeoStat.nShearAngle ? tan((36000 - rGeoStat.nShearAngle) * F_PI18000) : 0.0);
+                        const double fRotate(rGeoStat.nRotationAngle ? (36000 - rGeoStat.nRotationAngle) * F_PI18000 : 0.0);
+                        const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+                            aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
+                            aObjectRange.getMinX(), aObjectRange.getMinY()));
+
+                        // add object matrix to transform. By doing so theoretically
+                        // CellBorders could be also rotated/sheared for the first time ever.
+                        // To completely make that work, the primitives already created in
+                        // aRetval would also have to be based on ObjectMatrix, not only on
+                        // ObjectRange as it currently is.
+                        aTransform *= aObjectMatrix;
+
+                        // create a transform primitive with this and embed CellBorders
+                        // and append to retval
+                        aRetval.append(
+                            new drawinglayer::primitive2d::TransformPrimitive2D(
+                                aTransform,
+                                aCellBorderPrimitives));
+                    }
                 }
 
                 if(!aRetval.empty())
commit c4e6f6cfa1b189159245cb544959f800d126a78c
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Jan 24 12:05:19 2018 +0100

    BorderlineFix: Corrected Draw/Impress TableStyle accesses
    
    In Draw/Impress the indices for accessing the correct
    neighbouring TableStyles were wrong and thus created wrong
    visualizations, corrected that.
    
    Change-Id: Iebc5f294adb62fa4c6358e2f8c27d29cc3163fbc

diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 7ca200fc0e6e..448a0b407f2a 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -341,13 +341,13 @@ namespace sdr
                                     {
                                         // 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 aLeftFromBLine(impGetLineStyle(rTableLayouter, nX, nYBottom, 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 aRightFromBLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom, 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 aTopFromRLine(impGetLineStyle(rTableLayouter, nXRight, 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));
+                                        const svx::frame::Style aBottomFromRLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom, true, nColCount, nRowCount, bIsRTL));
 
                                         // get cell coordinate system
                                         const basegfx::B2DPoint aOrigin(aCellMatrix * basegfx::B2DPoint(0.0, 0.0));
commit 9a03edf7f6ed1ae933ce73f26599bc4251662e9d
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Jan 23 17:38:34 2018 +0100

    BorderlineFix: Fix WriterPaint if scrolling CellTableBorders
    
    Similar to CalcBorders in Writer the overlap regions for
    FrameBorders have to be taken into account when repainting the
    CellBordes of WriterTables
    
    Change-Id: I488ba158e1de579bfb06b9c8353adaa2cac706c6

diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 70781515d300..dc2837e2eed9 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2439,11 +2439,33 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
             {
                 aRepaintRect.Height( 2 * nRepaintRectSize );
                 aRepaintRect.Pos().Y() -= nRepaintRectSize;
+
+                // To decide on visibility it is also necessary to expand the RepaintRect
+                // to left/right according existing BorderLine overlap matchings, else there
+                // will be repaint errors when scrolling in e.t TripleLine BorderLines.
+                // aStyles[1] == aLFromT, aStyles[3] == aLFromB, aStyles[4] == aRFromT, aStyles[6] == aRFromB
+                if(aStyles[1].IsUsed() || aStyles[3].IsUsed() || aStyles[4].IsUsed() || aStyles[6].IsUsed())
+                {
+                    const double fLineWidthMaxLeft(std::max(aStyles[1].GetWidth(), aStyles[3].GetWidth()));
+                    const double fLineWidthMaxRight(std::max(aStyles[4].GetWidth(), aStyles[6].GetWidth()));
+                    aRepaintRect.Width(aRepaintRect.Width() + (fLineWidthMaxLeft + fLineWidthMaxRight));
+                    aRepaintRect.Pos().X() -= fLineWidthMaxLeft;
+                }
             }
             else
             {
                 aRepaintRect.Width( 2 * nRepaintRectSize );
                 aRepaintRect.Pos().X() -= nRepaintRectSize;
+
+                // Accordingly to horizontal case, but for top/bottom
+                // aStyles[3] == aTFromR, aStyles[1] == aTFromL, aStyles[6] == aBFromR, aStyles[4] == aBFromL
+                if(aStyles[3].IsUsed() || aStyles[1].IsUsed() || aStyles[6].IsUsed() || aStyles[4].IsUsed())
+                {
+                    const double fLineWidthMaxTop(std::max(aStyles[3].GetWidth(), aStyles[1].GetWidth()));
+                    const double fLineWidthMaxBottom(std::max(aStyles[6].GetWidth(), aStyles[4].GetWidth()));
+                    aRepaintRect.Height(aRepaintRect.Height() + (fLineWidthMaxTop + fLineWidthMaxBottom));
+                    aRepaintRect.Pos().Y() -= fLineWidthMaxTop;
+                }
             }
 
             if (!rRect.IsOver(aRepaintRect))
commit 07609f3ae2890ace29c249fac2fb60b0f0332af6
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Jan 23 16:06:19 2018 +0100

    BorderlineFix: Fixed visual updates when scrolling
    
    For Cells with DoubleLine the connections to perpendicular
    DoubleLine-Styles may have to be displayed in a Cell which
    is 'around' the orig cell in a Cell-Border of one. To represent
    that and to avoid repaint errors when scrolling in, the preparation
    of Primitives has to take accordingly more neighbour cells into
    account. Tested this change with the usages in Calc, UI (Dialogs)
    and Calc exports Print/PrintPreview/PDF. This does not affect
    Tables in Writer and/or Draw/Impress.
    
    Change-Id: I3bcc68cdf7b4fc1825a87a9773892c359421024e

diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ab6db75799e3..bc8a50a3d3cf 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -1061,18 +1061,39 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "CreateB2DPrimitiveRange" );
     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "CreateB2DPrimitiveRange" );
 
+    // It may be necessary to extend the loop ranges by one cell to the outside,
+    // when possible. This is needed e.g. when there is in Calc a Cell with an
+    // upper CellBorder using DoubleLine and that is right/left connected upwards
+    // to also DoubleLine. These upper DoubleLines will be extended to meet the
+    // lower of the upper CellBorder and thus have graphical parts that are
+    // displayed one cell below and right/left of the target cell - analog to
+    // other examples in all other directions.
+    // It would be possible to explicitely test this (if possible by indices at all)
+    // looping and testing the styles in the outer cells to detect this, but since
+    // for other usages (e.g. UI) usually nFirstRow==0 and nLastRow==GetRowCount()-1
+    // (and analog for Col) it is okay to just expand the range when available.
+    // Do *not* change nFirstRow/nLastRow due to these needed to the boolean tests
+    // below (!)
+    // Checked usages, this method is used in Calc EditView/Print/Export stuff and
+    // in UI (Dialog), not for Writer Tables and Draw/Impress tables. All usages
+    // seem okay with this change, so I will add it.
+    const size_t nStartRow(nFirstRow > 0 ? nFirstRow - 1 : nFirstRow);
+    const size_t nEndRow(nLastRow < GetRowCount() - 1 ? nLastRow + 1 : nLastRow);
+    const size_t nStartCol(nFirstCol > 0 ? nFirstCol - 1 : nFirstCol);
+    const size_t nEndCol(nLastCol < GetColCount() - 1 ? nLastCol + 1 : nLastCol);
+
     // various primitive sequences to collect the different border types
     drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
-    std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nLastCol - nFirstCol + 1);
+    std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nEndCol - nStartCol + 1);
     drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
 
     // remember for which merged cells crossed lines were already created. To
     // do so, hold the size_t cell index in a set for fast check
     std::set< size_t > aMergedCells;
 
-    for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow)
+    for (size_t nRow(nStartRow); nRow <= nEndRow; ++nRow)
     {
-        for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
+        for (size_t nCol(nStartCol); nCol <= nEndCol; ++nCol)
         {
             // get Cell and CoordinateSystem (*only* for this Cell, do *not* expand for
             // merged cells (!)), check if used (non-empty vectors)
@@ -1139,7 +1160,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rLeft.IsUsed())
                     {
-                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], true, pForceColor);
+                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], true, pForceColor);
                     }
                 }
 
@@ -1151,7 +1172,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rRight.IsUsed())
                     {
-                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], false, pForceColor);
+                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], false, pForceColor);
                     }
                 }
 
commit c5a3cae89660164f68565ee391ed8cf931f1d4da
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Jan 23 10:29:44 2018 +0100

    BorderlineFix: Corrected handling for 'rotated' CellBorders
    
    CellBorders can be rotated (including their Text) and need special
    visualization that is based on an own sheared/rotated coordinate
    system. Currently only possible for single cells (not merged ones)
    and needs to handle all borders (also bottom-right directly in the
    rotated cell, not in the neighboured ones to have the geometry,
    plus avoiding these in the non-rotated neighbour cells.
    Also corrected adding CellRotation data to svx::frame::Array
    in calc using SetCellRotations() which now gets called in the
    ScOutputData constructor to ensure it gets called in all places
    where it is used.
    
    Change-Id: I47bdfc29ba5ca76bbc07d98cb64733f867b1ee20

diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index f23dabae3de0..c41433609b9e 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -255,6 +255,11 @@ private:
     long SetEngineTextAndGetWidth( DrawEditParam& rParam, const OUString& rSetString,
                                    long& rNeededPixel, long nAddWidthPixels );
 
+    // Check for and set cell rotations at OutputData to have it available
+    // in the svx tooling to render the borders. Moved to private section
+    // and the single call to end of constructor to be sure this always happens
+    void    SetCellRotations();
+
 public:
     /**
      * @param nNewScrX: X-Offset in the output device for the table
@@ -311,8 +316,6 @@ public:
 
                     // with logic MapMode set!
     void    DrawEdit(bool bPixelToLogic);
-
-    void    SetCellRotations();
     void    DrawRotated(bool bPixelToLogic);        // logical
 
     void    DrawClear();
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 22e07763decb..64cd440e9902 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -696,10 +696,6 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
         pContentDev->SetMapMode(aCurrentMapMode);
     }
 
-    // check for and set cell rotations at OutputData to have it available
-    // in the svx tooling to render the borders
-    aOutputData.SetCellRotations();
-
     if ( rDoc.HasBackgroundDraw( nTab, aDrawingRectLogic ) )
     {
         pContentDev->SetMapMode(MapMode(MapUnit::MapPixel));
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index bd3687cd1cd3..064bb14ce1a1 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -214,6 +214,9 @@ ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
 
     bTabProtected = mpDoc->IsTabProtected( nTab );
     bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
+
+    // always needed, so call at the end of the constructor
+    SetCellRotations();
 }
 
 ScOutputData::~ScOutputData()
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index 096216210585..ab6db75799e3 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -1092,9 +1092,21 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 const bool bFirstRow(nRow == nFirstRow);
                 const bool bLastRow(nRow == nLastRow);
 
+                // handle rotation: If cell is rotated, handle lower/right edge inside
+                // this local geometry due to the created CoordinateSystem already representing
+                // the needed transformations.
+                const bool bRotated(rCell.IsRotated());
+
+                // Additionally avoid double-handling by supressing handling when self not roated,
+                // but above/left is rotated and thus already handled. Two directly connected
+                // rotated will paint/create both edges, they might be rotated differently.
+                const bool bSuppressAbove(!bRotated && nRow > nFirstRow && CELL(nCol, nRow - 1).IsRotated());
+                const bool bSupressLeft(!bRotated && nCol > nFirstCol && CELL(nCol - 1, nRow).IsRotated());
+
                 // create upper line for this Cell
-                if (!bOverlapY      // true for first line in merged cells or cells
-                    || bFirstRow)   // true for non_Calc usages of this tooling
+                if ((!bOverlapY         // true for first line in merged cells or cells
+                    || bFirstRow)       // true for non_Calc usages of this tooling
+                    && !bSuppressAbove) // true when above is not rotated, so edge is already handled (see bRotated)
                 {
                     // get CellStyle - method will take care to get the correct one, e.g.
                     // for merged cells (it uses ORIGCELL that works with topLeft's of these)
@@ -1107,7 +1119,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 }
 
                 // create lower line for this Cell
-                if (bLastRow)       // true for non_Calc usages of this tooling
+                if (bLastRow       // true for non_Calc usages of this tooling
+                    || bRotated)   // true if cell is rotated, handle lower edge in local geometry
                 {
                     const Style& rBottom(GetCellStyleBottom(nCol, nRow));
 
@@ -1118,8 +1131,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 }
 
                 // create left line for this Cell
-                if (!bOverlapX      // true for first column in merged cells or cells
-                    || bFirstCol)   // true for non_Calc usages of this tooling
+                if ((!bOverlapX         // true for first column in merged cells or cells
+                    || bFirstCol)       // true for non_Calc usages of this tooling
+                    && !bSupressLeft)   // true when left is not rotated, so edge is already handled (see bRotated)
                 {
                     const Style& rLeft(GetCellStyleLeft(nCol, nRow));
 
@@ -1130,7 +1144,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 }
 
                 // create right line for this Cell
-                if (bLastCol)       // true for non_Calc usages of this tooling
+                if (bLastCol        // true for non_Calc usages of this tooling
+                    || bRotated)    // true if cell is rotated, handle right edge in local geometry
                 {
                     const Style& rRight(GetCellStyleRight(nCol, nRow));
 
commit b28360c66bc856176ff84bc6c2516f710a7196ab
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Mon Jan 22 14:33:20 2018 +0100

    BorderlineFix: Avoid BorderLines to be too prolonged
    
    For MergedCells there was an effect that the BorderLines
    were painted too far in PrintPreview/Print/PDF visualization,
    found reason and changed. Checked (hopefully) all usages,
    looks good.
    
    Change-Id: I0acf8dcb20548a98533f3ab317ac72c0d0f0a947

diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index e135e371319c..b73531b06e47 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -290,7 +290,7 @@ public:
     long                GetHeight() const;
 
     /** Returns the output range of the cell (nCol,nRow).
-        Returns total output range of merged ranges. */
+        Returns total output range of merged ranges, if bExpandMerged is true. */
     basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const;
 
     // mirroring --------------------------------------------------------------
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ac47053155ec..096216210585 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -840,24 +840,44 @@ long Array::GetHeight() const
 
 basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const
 {
-    size_t nFirstCol = bExpandMerged ? mxImpl->GetMergedFirstCol( nCol, nRow ) : nCol;
-    size_t nFirstRow = bExpandMerged ? mxImpl->GetMergedFirstRow( nCol, nRow ) : nRow;
-    size_t nLastCol = bExpandMerged ? mxImpl->GetMergedLastCol( nCol, nRow ) : nCol;
-    size_t nLastRow = bExpandMerged ? mxImpl->GetMergedLastRow( nCol, nRow ) : nRow;
-    const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
-    const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
-    tools::Rectangle aRect(aPoint, aSize);
-
-    // adjust rectangle for partly visible merged cells
-    const Cell& rCell = CELL( nCol, nRow );
-    if( rCell.IsMerged() )
+    if(bExpandMerged)
     {
-        aRect.Left() -= rCell.mnAddLeft;
-        aRect.Right() += rCell.mnAddRight;
-        aRect.Top() -= rCell.mnAddTop;
-        aRect.Bottom() += rCell.mnAddBottom;
+        // get the Range of the fully expanded cell (if merged)
+        const size_t nFirstCol(mxImpl->GetMergedFirstCol( nCol, nRow ));
+        const size_t nFirstRow(mxImpl->GetMergedFirstRow( nCol, nRow ));
+        const size_t nLastCol(mxImpl->GetMergedLastCol( nCol, nRow ));
+        const size_t nLastRow(mxImpl->GetMergedLastRow( nCol, nRow ));
+        const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
+        const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
+        tools::Rectangle aRect(aPoint, aSize);
+
+        // adjust rectangle for partly visible merged cells
+        const Cell& rCell = CELL( nCol, nRow );
+
+        if( rCell.IsMerged() )
+        {
+            // not *sure* what exactly this is good for,
+            // it is just a hard set extension at merged cells,
+            // probably *should* be included in the above extended
+            // GetColPosition/GetColWidth already. This might be
+            // added due to GetColPosition/GetColWidth not working
+            // correcly over PageChanges (if used), but not sure.
+            aRect.Left() -= rCell.mnAddLeft;
+            aRect.Right() += rCell.mnAddRight;
+            aRect.Top() -= rCell.mnAddTop;
+            aRect.Bottom() += rCell.mnAddBottom;
+        }
+
+        return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
+    }
+    else
+    {
+        const Point aPoint( GetColPosition( nCol ), GetRowPosition( nRow ) );
+        const Size aSize( GetColWidth( nCol, nCol ) + 1, GetRowHeight( nRow, nRow ) + 1 );
+        const tools::Rectangle aRect(aPoint, aSize);
+
+        return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
     }
-    return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
 }
 
 // mirroring
@@ -1054,7 +1074,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     {
         for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
         {
-            // get Cell and CoordinateSystem (*only* for this Cell), check if used (not empty)
+            // get Cell and CoordinateSystem (*only* for this Cell, do *not* expand for
+            // merged cells (!)), check if used (non-empty vectors)
             const Cell& rCell(CELL(nCol, nRow));
             basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
             basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
@@ -1153,9 +1174,6 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(bContinue)
                     {
-                        const size_t _nLastCol(mxImpl->GetMergedLastCol(nCol, nRow));
-                        const size_t _nLastRow(mxImpl->GetMergedLastRow(nCol, nRow));
-
                         if(rTLBR.IsUsed())
                         {
                             /// top-left and bottom-right Style Tables
commit 8ed06d685bc99c61a36b8f1472883bf85e4b791a
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Jan 19 14:43:24 2018 +0100

    BorderlineFix: Corrected missing borders in print
    
    In Print/PDF/PrintPreview border lines were missing, this
    happened for merged cells. It has to do with access to the
    involved Styles and/or 'Clip' set (to avoid creating everything).
    Thus a 'mixed' usage of cell and merged-cell stuff was needed.
    As it turns out support for this is already there, need to use
    it.
    
    Change-Id: Ic16085b97eef5c79a4501279432f43491bca350e

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 2feaab5af8bf..9b532a2d0d29 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -143,10 +143,6 @@ private:
     /// 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();
 
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ecb3eaace1c6..ac47053155ec 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -1055,17 +1055,14 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
         for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
         {
             // get Cell and CoordinateSystem (*only* for this Cell), check if used (not empty)
-            const Cell& rCell = CELL(nCol, nRow);
+            const Cell& rCell(CELL(nCol, nRow));
             basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
             basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
             basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
 
             if(!aX.equalZero() && !aY.equalZero())
             {
-                // for getting correct Style(s) for merged Cells, we need the First(Col/Row)
-                // for access (see accessing Styles below)
-                const size_t _nFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
-                const size_t _nFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+                // get needed local values
                 basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
                 const bool bOverlapX(rCell.mbOverlapX);
                 const bool bOverlapY(rCell.mbOverlapY);
@@ -1078,7 +1075,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 if (!bOverlapY      // true for first line in merged cells or cells
                     || bFirstRow)   // true for non_Calc usages of this tooling
                 {
-                    const Style& rTop = GetCellStyleTop(_nFirstCol, _nFirstRow);
+                    // get CellStyle - method will take care to get the correct one, e.g.
+                    // for merged cells (it uses ORIGCELL that works with topLeft's of these)
+                    const Style& rTop(GetCellStyleTop(nCol, nRow));
 
                     if(rTop.IsUsed())
                     {
@@ -1089,7 +1088,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 // create lower line for this Cell
                 if (bLastRow)       // true for non_Calc usages of this tooling
                 {
-                    const Style& rBottom = GetCellStyleBottom(_nFirstCol, _nFirstRow);
+                    const Style& rBottom(GetCellStyleBottom(nCol, nRow));
 
                     if(rBottom.IsUsed())
                     {
@@ -1101,7 +1100,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 if (!bOverlapX      // true for first column in merged cells or cells
                     || bFirstCol)   // true for non_Calc usages of this tooling
                 {
-                    const Style& rLeft(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+                    const Style& rLeft(GetCellStyleLeft(nCol, nRow));
 
                     if(rLeft.IsUsed())
                     {
@@ -1112,7 +1111,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 // create right line for this Cell
                 if (bLastCol)       // true for non_Calc usages of this tooling
                 {
-                    const Style& rRight(GetCellStyleRight(_nFirstCol, _nFirstRow));
+                    const Style& rRight(GetCellStyleRight(nCol, nRow));
 
                     if(rRight.IsUsed())
                     {
@@ -1122,8 +1121,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                 // check for crossed lines, these need special treatment, especially
                 // for merged cells, see below
-                const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
-                const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
+                const Style& rTLBR(GetCellStyleTLBR(nCol, nRow));
+                const Style& rBLTR(GetCellStyleBLTR(nCol, nRow));
 
                 if(rTLBR.IsUsed() || rBLTR.IsUsed())
                 {
@@ -1131,8 +1130,11 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rCell.IsMerged())
                     {
-                        // first check if this merged cell was already handled
-                        const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nFirstCol, _nFirstRow));
+                        // first check if this merged cell was already handled. To do so,
+                        // calculate and use the index of the TopLeft cell
+                        const size_t _nMergedFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
+                        const size_t _nMergedFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+                        const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nMergedFirstCol, _nMergedFirstRow));
                         bContinue = (aMergedCells.end() == aMergedCells.find(nIndexOfMergedCell));
 
                         if(bContinue)
@@ -1140,7 +1142,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                             // not found, add now to mark as handled
                             aMergedCells.insert(nIndexOfMergedCell);
 
-                            // when merged, get extended coordinate system and dependent values
+                            // when merged, get extended coordinate system and derived values
+                            // for the full range of this merged cell
                             aCoordinateSystem = rCell.CreateCoordinateSystem(*this, nCol, nRow, true);
                             aX = basegfx::utils::getColumn(aCoordinateSystem, 0);
                             aY = basegfx::utils::getColumn(aCoordinateSystem, 1);
@@ -1157,8 +1160,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                         {
                             /// top-left and bottom-right Style Tables
                             /// Fill top-left Style Table
-                            const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
-                            const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+                            const Style& rTLFromRight(GetCellStyleTop(nCol, nRow));
+                            const Style& rTLFromBottom(GetCellStyleLeft(nCol, nRow));
                             StyleVectorTable aStart;
                             const basegfx::B2DVector aAxisA(aX + aY);
 
@@ -1167,8 +1170,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                             aStart.sort();
 
                             /// Fill bottom-right Style Table
-                            const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
-                            const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
+                            const Style& rBRFromBottom(GetCellStyleRight(nCol, nRow));
+                            const Style& rBRFromLeft(GetCellStyleBottom(nCol, nRow));
                             StyleVectorTable aEnd;
                             const basegfx::B2DVector aAxisB(-aX -aY);
 
@@ -1191,8 +1194,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                         {
                             /// bottom-left and top-right Style Tables
                             /// Fill bottom-left Style Table
-                            const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
-                            const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
+                            const Style& rBLFromTop(GetCellStyleLeft(nCol, nRow));
+                            const Style& rBLFromBottom(GetCellStyleBottom(nCol, nRow));
                             StyleVectorTable aStart;
                             const basegfx::B2DVector aAxisA(aX - aY);
 
@@ -1201,8 +1204,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                             aStart.sort();
 
                             /// Fill top-right Style Table
-                            const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
-                            const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
+                            const Style& rTRFromLeft(GetCellStyleTop(nCol, nRow));
+                            const Style& rTRFromBottom(GetCellStyleRight(nCol, nRow));
                             StyleVectorTable aEnd;
                             const basegfx::B2DVector aAxisB(aY - aX);
 
commit 71053a36f3f48904c254a1d277f42d6dcdc29b04
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Jan 18 17:07:43 2018 +0100

    BorderlineFix: Need to redesign Borderline paint for Calc
    
    To fix some errors, need to change svx::frame::Array conversion
    to Primitives, especially regarding handling of merged cells.
    These make problems in the currtent form where the full extended
    merged cell tries to be converted. This is bad for cropped stuff
    and also wrong for double-line stuff attaching to a merged cell.
    The solution is to handle cells single and merge created primitives
    which is more expensive but will work. This will involve special
    handling for X-Ed (crossed) and 'roated' Cells. Also need to be
    very careful since all this is used in the meantime for all
    visualizations of Tables in multiple apps/situations.
    
    Change-Id: If0652a3ba97a6f27dd5d782ea22b1514303f3710

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index ce7f09345a80..2feaab5af8bf 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -150,11 +150,6 @@ private:
     /// 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) { mpUsingCell = pCell; }
-
 public:
     /** Constructs an invisible frame style. */
     explicit Style();
@@ -203,9 +198,6 @@ public:
     /** Mirrors this style (exchanges primary and secondary), if it is a double frame style. */
     Style& MirrorSelf();
 
-    /** return the Cell using this style (if set) */
-    const Cell* GetUsingCell() const { return mpUsingCell; }
-
     bool operator==( const Style& rOther) const;
     bool operator<( const Style& rOther) const;
 };
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 2b06d29a41b2..e135e371319c 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -291,8 +291,7 @@ public:
 
     /** Returns the output range of the cell (nCol,nRow).
         Returns total output range of merged ranges. */
-    basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow ) const;
-    basegfx::B2DRange GetCellRange( size_t nCellIndex ) const;
+    basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const;
 
     // mirroring --------------------------------------------------------------
 
@@ -312,9 +311,6 @@ public:
     /** Draws the part of the array, that is inside the clipping range. */
     drawinglayer::primitive2d::Primitive2DContainer CreateB2DPrimitiveArray() const;
 
-    // fill the Cell::maCellIndex entries to allow referencing back from Cell to Array Col/Row coordinates
-    void AddCellIndices() const;
-
 private:
     std::unique_ptr<ArrayImpl>        mxImpl;
 };
diff --git a/sc/source/ui/miscdlgs/autofmt.cxx b/sc/source/ui/miscdlgs/autofmt.cxx
index a6ffdfe75389..f8f2dae645a6 100644
--- a/sc/source/ui/miscdlgs/autofmt.cxx
+++ b/sc/source/ui/miscdlgs/autofmt.cxx
@@ -250,7 +250,7 @@ void ScAutoFmtPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCo
 
         Size aStrSize;
         sal_uInt16 nFmtIndex = GetFormatIndex( nCol, nRow );
-        const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow ));
+        const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow, true ));
         Point aPos = Point(basegfx::fround(cellRange.getMinX()), basegfx::fround(cellRange.getMinY()));
         sal_uInt16 nRightX = 0;
         bool bJustify = pCurData->GetIncludeJustify();
@@ -374,7 +374,7 @@ void ScAutoFmtPreview::DrawBackground(vcl::RenderContext& rRenderContext)
                 rRenderContext.SetLineColor();
                 rRenderContext.SetFillColor( pItem->GetColor() );
 
-                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
                 rRenderContext.DrawRect(
                     tools::Rectangle(
                         basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index 1501fca0022d..269ac3e52e49 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -51,14 +51,12 @@ void Style::implEnsureImplStyle()
 }
 
 Style::Style() :
-    maImplStyle(),
-    mpUsingCell(nullptr)
+    maImplStyle()
 {
 }
 
 Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
-    maImplStyle(new implStyle()),
-    mpUsingCell(nullptr)
+    maImplStyle(new implStyle())
 {
     maImplStyle->mnType = nType;
     maImplStyle->mfPatternScale = fScale;
@@ -66,8 +64,7 @@ Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double
 }
 
 Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
-    maImplStyle(new implStyle()),
-    mpUsingCell(nullptr)
+    maImplStyle(new implStyle())
 {
     maImplStyle->mnType = nType;
     maImplStyle->mfPatternScale = fScale;
@@ -75,8 +72,7 @@ Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rCo
 }
 
 Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
-    maImplStyle(),
-    mpUsingCell(nullptr)
+    maImplStyle()
 {
     if(nullptr != pBorder)
     {
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index 560eefd775ce..ecb3eaace1c6 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -45,10 +45,8 @@ public:
     long                mnAddTop;
     long                mnAddBottom;
 
-    SvxRotateMode           meRotMode;
-    double                  mfOrientation;
-    basegfx::B2DHomMatrix   maCoordinateSystem;
-    size_t                  maCellIndex;
+    SvxRotateMode       meRotMode;
+    double              mfOrientation;
 
     bool                mbMergeOrig;
     bool                mbOverlapX;
@@ -57,12 +55,12 @@ public:
 public:
     explicit            Cell();
 
-    void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; maLeft.SetUsingCell(this); }
-    void SetStyleRight(const Style& rStyle) { maRight = rStyle; maRight.SetUsingCell(this); }
-    void SetStyleTop(const Style& rStyle) { maTop = rStyle; maTop.SetUsingCell(this); }
-    void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; maBottom.SetUsingCell(this); }
-    void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; maTLBR.SetUsingCell(this); }
-    void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; maBLTR.SetUsingCell(this); }
+    void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; }
+    void SetStyleRight(const Style& rStyle) { maRight = rStyle; }
+    void SetStyleTop(const Style& rStyle) { maTop = rStyle; }
+    void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; }
+    void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; }
+    void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; }
 
     const Style& GetStyleLeft() const { return maLeft; }
     const Style& GetStyleRight() const { return maRight; }
@@ -76,74 +74,54 @@ public:
 
     void                MirrorSelfX();
 
-    basegfx::B2DHomMatrix const & CreateCoordinateSystem(const Array& rArray) const;
-    size_t GetCellIndex(const Array& rArray) const;
+    basegfx::B2DHomMatrix CreateCoordinateSystem(const Array& rArray, size_t nCol, size_t nRow, bool bExpandMerged) const;
 };
 
 typedef std::vector< long >     LongVec;
 typedef std::vector< Cell >     CellVec;
 
-size_t Cell::GetCellIndex(const Array& rArray) const
+basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray, size_t nCol, size_t nRow, bool bExpandMerged) const
 {
-    if(static_cast<size_t>(-1) == maCellIndex)
-    {
-        rArray.AddCellIndices();
-    }
-
-    return maCellIndex;
-}
+    basegfx::B2DHomMatrix aRetval;
+    const basegfx::B2DRange aRange(rArray.GetCellRange(nCol, nRow, bExpandMerged));
 
-basegfx::B2DHomMatrix const & Cell::CreateCoordinateSystem(const Array& rArray) const
-{
-    if(!maCoordinateSystem.isIdentity())
+    if(!aRange.isEmpty())
     {
-        return maCoordinateSystem;
-    }
-
-    const size_t nCellIndex(GetCellIndex(rArray));
+        basegfx::B2DPoint aOrigin(aRange.getMinimum());
+        basegfx::B2DVector aX(aRange.getWidth(), 0.0);
+        basegfx::B2DVector aY(0.0, aRange.getHeight());
 
-    if(static_cast<size_t>(-1) != nCellIndex)
-    {
-        const basegfx::B2DRange aRange(rArray.GetCellRange(nCellIndex));
-
-        if(!aRange.isEmpty())
+        if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode)
         {
-            basegfx::B2DPoint aOrigin(aRange.getMinimum());
-            basegfx::B2DVector aX(aRange.getWidth(), 0.0);
-            basegfx::B2DVector aY(0.0, aRange.getHeight());
+            // when rotated, adapt values. Get Skew (cos/sin == 1/tan)
+            const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation)));
 
-            if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode)
+            switch (meRotMode)
             {
-                // when rotated, adapt values. Get Skew (cos/sin == 1/tan)
-                const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation)));
-
-                switch (meRotMode)
-                {
-                case SvxRotateMode::SVX_ROTATE_MODE_TOP:
-                    // shear Y-Axis
-                    aY.setX(-fSkew);
-                    break;
-                case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
-                    // shear origin half, Y full
-                    aOrigin.setX(aOrigin.getX() + (fSkew * 0.5));
-                    aY.setX(-fSkew);
-                    break;
-                case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
-                    // shear origin full, Y full
-                    aOrigin.setX(aOrigin.getX() + fSkew);
-                    aY.setX(-fSkew);
-                    break;
-                default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
-                    break;
-                }
+            case SvxRotateMode::SVX_ROTATE_MODE_TOP:
+                // shear Y-Axis
+                aY.setX(-fSkew);
+                break;
+            case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
+                // shear origin half, Y full
+                aOrigin.setX(aOrigin.getX() + (fSkew * 0.5));
+                aY.setX(-fSkew);
+                break;
+            case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
+                // shear origin full, Y full
+                aOrigin.setX(aOrigin.getX() + fSkew);
+                aY.setX(-fSkew);
+                break;
+            default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
+                break;
             }
-
-            // use column vectors as coordinate axes, homogen column for translation
-            const_cast<Cell*>(this)->maCoordinateSystem = basegfx::utils::createCoordinateSystemTransform(aOrigin, aX, aY);
         }
+
+        // use column vectors as coordinate axes, homogen column for translation
+        aRetval = basegfx::utils::createCoordinateSystemTransform(aOrigin, aX, aY);
     }
 
-    return maCoordinateSystem;
+    return aRetval;
 }
 
 Cell::Cell() :
@@ -153,8 +131,6 @@ Cell::Cell() :
     mnAddBottom( 0 ),
     meRotMode(SvxRotateMode::SVX_ROTATE_MODE_STANDARD ),
     mfOrientation( 0.0 ),
-    maCoordinateSystem(),
-    maCellIndex(static_cast<size_t>(-1)),
     mbMergeOrig( false ),
     mbOverlapX( false ),
     mbOverlapY( false )
@@ -168,8 +144,6 @@ void Cell::MirrorSelfX()
     maLeft.MirrorSelf();
     maRight.MirrorSelf();
     mfOrientation = -mfOrientation;
-    maCoordinateSystem.identity();
-    maCellIndex = static_cast<size_t>(-1);
 }
 
 
@@ -864,17 +838,12 @@ long Array::GetHeight() const
     return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
 }
 
-basegfx::B2DRange Array::GetCellRange( size_t nCellIndex ) const
-{
-    return GetCellRange(nCellIndex % GetColCount(), nCellIndex / GetColCount());
-}
-
-basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow ) const
+basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const
 {
-    size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
-    size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
-    size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
-    size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
+    size_t nFirstCol = bExpandMerged ? mxImpl->GetMergedFirstCol( nCol, nRow ) : nCol;
+    size_t nFirstRow = bExpandMerged ? mxImpl->GetMergedFirstRow( nCol, nRow ) : nRow;
+    size_t nLastCol = bExpandMerged ? mxImpl->GetMergedLastCol( nCol, nRow ) : nCol;
+    size_t nLastRow = bExpandMerged ? mxImpl->GetMergedLastRow( nCol, nRow ) : nRow;
     const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
     const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
     tools::Rectangle aRect(aPoint, aSize);
@@ -1023,45 +992,6 @@ void HelperCreateVerticalEntry(
     );
 }
 
-void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::primitive2d::Primitive2DContainer& rSequence, const Color* pForceColor)
-{
-    const Cell* pCell = rStyle.GetUsingCell();
-
-    if(nullptr != pCell)
-    {
-        const size_t nCellIndex(pCell->GetCellIndex(rArray));
-
-        if(static_cast<size_t>(-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(bL || bR || bT || bB)
-            {
-                const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(rArray));
-                const basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
-                const basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
-                const basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
-
-                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 HelperMergeInB2DPrimitiveArray(
     const drawinglayer::primitive2d::Primitive2DContainer& rSource,
     drawinglayer::primitive2d::Primitive2DContainer& rTarget)
@@ -1116,23 +1046,27 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nLastCol - nFirstCol + 1);
     drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
 
+    // remember for which merged cells crossed lines were already created. To
+    // do so, hold the size_t cell index in a set for fast check
+    std::set< size_t > aMergedCells;
+
     for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow)
     {
         for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
         {
+            // get Cell and CoordinateSystem (*only* for this Cell), check if used (not empty)
             const Cell& rCell = CELL(nCol, nRow);
-            const basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this));
-            const basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
-            const basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
+            basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
+            basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
+            basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
 
             if(!aX.equalZero() && !aY.equalZero())
             {
-                size_t _nFirstCol = mxImpl->GetMergedFirstCol(nCol, nRow);
-                size_t _nFirstRow = mxImpl->GetMergedFirstRow(nCol, nRow);
-                size_t _nLastCol = mxImpl->GetMergedLastCol(nCol, nRow);
-                size_t _nLastRow = mxImpl->GetMergedLastRow(nCol, nRow);
-                const basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
-
+                // for getting correct Style(s) for merged Cells, we need the First(Col/Row)
+                // for access (see accessing Styles below)
+                const size_t _nFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
+                const size_t _nFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+                basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
                 const bool bOverlapX(rCell.mbOverlapX);
                 const bool bOverlapY(rCell.mbOverlapY);
                 const bool bFirstCol(nCol == nFirstCol);
@@ -1140,116 +1074,152 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 const bool bFirstRow(nRow == nFirstRow);
                 const bool bLastRow(nRow == nLastRow);
 
-                if (!bOverlapX || bFirstRow)
+                // create upper line for this Cell
+                if (!bOverlapY      // true for first line in merged cells or cells
+                    || bFirstRow)   // true for non_Calc usages of this tooling
                 {
                     const Style& rTop = GetCellStyleTop(_nFirstCol, _nFirstRow);
 
                     if(rTop.IsUsed())
                     {
-                        HelperCreateEntry(*this, rTop, aHorizontalSequence, pForceColor);
+                        HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, aHorizontalSequence, true, pForceColor);
                     }
                 }
 
-                if (bLastRow)
+                // create lower line for this Cell
+                if (bLastRow)       // true for non_Calc usages of this tooling
                 {
                     const Style& rBottom = GetCellStyleBottom(_nFirstCol, _nFirstRow);
 
                     if(rBottom.IsUsed())
                     {
-                        HelperCreateEntry(*this, rBottom, aHorizontalSequence, pForceColor);
+                        HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, aHorizontalSequence, false, pForceColor);
                     }
                 }
 
-                if (!bOverlapY || bFirstCol)
+                // create left line for this Cell
+                if (!bOverlapX      // true for first column in merged cells or cells
+                    || bFirstCol)   // true for non_Calc usages of this tooling
                 {
                     const Style& rLeft(GetCellStyleLeft(_nFirstCol, _nFirstRow));
 
                     if(rLeft.IsUsed())
                     {
-                        HelperCreateEntry(*this, rLeft, aVerticalSequences[nCol - nFirstCol], pForceColor);
+                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], true, pForceColor);
                     }
                 }
 
-                if (bLastCol)
+                // create right line for this Cell
+                if (bLastCol)       // true for non_Calc usages of this tooling
                 {
                     const Style& rRight(GetCellStyleRight(_nFirstCol, _nFirstRow));
 
                     if(rRight.IsUsed())
                     {
-                        HelperCreateEntry(*this, rRight, aVerticalSequences[nCol - nFirstCol], pForceColor);
+                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], false, pForceColor);
                     }
                 }
 
-                if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) || (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
+                // check for crossed lines, these need special treatment, especially
+                // for merged cells, see below
+                const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
+                const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
+
+                if(rTLBR.IsUsed() || rBLTR.IsUsed())
                 {
-                    const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
-                    if(rTLBR.IsUsed())
+                    bool bContinue(true);
+
+                    if(rCell.IsMerged())
                     {
-                        /// top-left and bottom-right Style Tables
-                        /// Fill top-left Style Table
-                        const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
-                        const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
-                        StyleVectorTable aStart;
-                        const basegfx::B2DVector aAxisA(aX + aY);
-
-                        aStart.add(rTLFromRight, aAxisA, aX, false);
-                        aStart.add(rTLFromBottom, aAxisA, aY, false);
-                        aStart.sort();
-
-                        /// Fill bottom-right Style Table
-                        const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
-                        const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
-                        StyleVectorTable aEnd;
-                        const basegfx::B2DVector aAxisB(-aX -aY);
-
-                        aEnd.add(rBRFromBottom, aAxisB, -aY, true);
-                        aEnd.add(rBRFromLeft, aAxisB, -aX, true);
-                        aEnd.sort();
-
-                        CreateBorderPrimitives(
-                            aCrossSequence,
-                            aOrigin,
-                            aX + aY,
-                            rTLBR,
-                            aStart,
-                            aEnd,
-                            pForceColor
-                        );
+                        // first check if this merged cell was already handled
+                        const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nFirstCol, _nFirstRow));
+                        bContinue = (aMergedCells.end() == aMergedCells.find(nIndexOfMergedCell));
+
+                        if(bContinue)
+                        {
+                            // not found, add now to mark as handled
+                            aMergedCells.insert(nIndexOfMergedCell);
+
+                            // when merged, get extended coordinate system and dependent values
+                            aCoordinateSystem = rCell.CreateCoordinateSystem(*this, nCol, nRow, true);
+                            aX = basegfx::utils::getColumn(aCoordinateSystem, 0);
+                            aY = basegfx::utils::getColumn(aCoordinateSystem, 1);
+                            aOrigin = basegfx::utils::getColumn(aCoordinateSystem, 2);
+                        }
                     }
 
-                    const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
-                    if(rBLTR.IsUsed())
+                    if(bContinue)
                     {
-                        /// bottom-left and top-right Style Tables
-                        /// Fill bottom-left Style Table
-                        const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
-                        const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
-                        StyleVectorTable aStart;
-                        const basegfx::B2DVector aAxisA(aX - aY);
-
-                        aStart.add(rBLFromTop, aAxisA, -aY, true);
-                        aStart.add(rBLFromBottom, aAxisA, aX, false);
-                        aStart.sort();
-
-                        /// Fill top-right Style Table
-                        const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
-                        const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
-                        StyleVectorTable aEnd;
-                        const basegfx::B2DVector aAxisB(aY - aX);
-
-                        aEnd.add(rTRFromLeft, aAxisB, -aX, true);
-                        aEnd.add(rTRFromBottom, aAxisB, aY, false);
-                        aEnd.sort();
-
-                        CreateBorderPrimitives(
-                            aCrossSequence,
-                            aOrigin + aY,
-                            aX - aY,
-                            rBLTR,
-                            aStart,
-                            aEnd,
-                            pForceColor
-                        );
+                        const size_t _nLastCol(mxImpl->GetMergedLastCol(nCol, nRow));
+                        const size_t _nLastRow(mxImpl->GetMergedLastRow(nCol, nRow));
+
+                        if(rTLBR.IsUsed())
+                        {
+                            /// top-left and bottom-right Style Tables
+                            /// Fill top-left Style Table
+                            const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
+                            const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+                            StyleVectorTable aStart;
+                            const basegfx::B2DVector aAxisA(aX + aY);
+
+                            aStart.add(rTLFromRight, aAxisA, aX, false);
+                            aStart.add(rTLFromBottom, aAxisA, aY, false);
+                            aStart.sort();
+
+                            /// Fill bottom-right Style Table
+                            const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
+                            const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
+                            StyleVectorTable aEnd;
+                            const basegfx::B2DVector aAxisB(-aX -aY);
+
+                            aEnd.add(rBRFromBottom, aAxisB, -aY, true);
+                            aEnd.add(rBRFromLeft, aAxisB, -aX, true);
+                            aEnd.sort();
+
+                            CreateBorderPrimitives(
+                                aCrossSequence,
+                                aOrigin,
+                                aX + aY,
+                                rTLBR,
+                                aStart,
+                                aEnd,
+                                pForceColor
+                            );
+                        }
+
+                        if(rBLTR.IsUsed())
+                        {
+                            /// bottom-left and top-right Style Tables
+                            /// Fill bottom-left Style Table
+                            const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
+                            const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
+                            StyleVectorTable aStart;
+                            const basegfx::B2DVector aAxisA(aX - aY);
+
+                            aStart.add(rBLFromTop, aAxisA, -aY, true);
+                            aStart.add(rBLFromBottom, aAxisA, aX, false);
+                            aStart.sort();
+
+                            /// Fill top-right Style Table
+                            const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
+                            const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
+                            StyleVectorTable aEnd;
+                            const basegfx::B2DVector aAxisB(aY - aX);
+
+                            aEnd.add(rTRFromLeft, aAxisB, -aX, true);
+                            aEnd.add(rTRFromBottom, aAxisB, aY, false);
+                            aEnd.sort();
+
+                            CreateBorderPrimitives(
+                                aCrossSequence,
+                                aOrigin + aY,
+                                aX - aY,
+                                rBLTR,
+                                aStart,
+                                aEnd,
+                                pForceColor
+                            );
+                        }
                     }
                 }
             }
@@ -1259,6 +1229,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     // to stay compatible, create order as it was formally. Also try to
     // merge primitives as far as possible
     HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aCrossSequence);
+
     for(const auto& aVert : aVerticalSequences)
     {
         HelperMergeInB2DPrimitiveArray(aVert, aCrossSequence);
@@ -1279,19 +1250,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveArray()
     return aPrimitives;
 }
 
-void Array::AddCellIndices() const
-{
-    for (size_t a(0); a < mxImpl->maCells.size(); a++)
-    {
-        const_cast<Array*>(this)->mxImpl->maCells[a].maCellIndex = a;
-    }
-}
-
 #undef ORIGCELL
 #undef CELLACC
 #undef CELL
-
-
 #undef DBG_FRAME_CHECK_ROW_1
 #undef DBG_FRAME_CHECK_COL_1
 #undef DBG_FRAME_CHECK_COLROW
@@ -1299,7 +1260,6 @@ void Array::AddCellIndices() const
 #undef DBG_FRAME_CHECK_COL
 #undef DBG_FRAME_CHECK
 
-
 }
 }
 
diff --git a/svx/source/dialog/frmsel.cxx b/svx/source/dialog/frmsel.cxx
index d54e1b083e65..f65693d44b58 100644
--- a/svx/source/dialog/frmsel.cxx
+++ b/svx/source/dialog/frmsel.cxx
@@ -410,7 +410,7 @@ void FrameSelectorImpl::InitBorderGeometry()
     {
         for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
         {
-            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
             const tools::Rectangle aRect(
                 basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
                 basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()));
@@ -469,7 +469,7 @@ void FrameSelectorImpl::InitBorderGeometry()
             for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
             {
                 // the usable area between horizonal/vertical frame borders of current quadrant
-                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
                 const tools::Rectangle aRect(
                     basegfx::fround(aCellRange.getMinX()) + nClV + 1, basegfx::fround(aCellRange.getMinY()) + nClH + 1,
                     basegfx::fround(aCellRange.getMaxX()) - nClV + 1, basegfx::fround(aCellRange.getMaxY()) - nClH + 1);
diff --git a/sw/source/ui/table/tautofmt.cxx b/sw/source/ui/table/tautofmt.cxx
index 7a342f1ff83e..5336024736fa 100644
--- a/sw/source/ui/table/tautofmt.cxx
+++ b/sw/source/ui/table/tautofmt.cxx
@@ -716,7 +716,7 @@ MAKENUMSTR:
     SvtScriptedTextHelper aScriptedText(rRenderContext);
     Size aStrSize;
     sal_uInt8 nFormatIndex = GetFormatIndex( nCol, nRow );
-    const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+    const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
     const tools::Rectangle cellRect(
         basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
         basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()));
@@ -811,7 +811,7 @@ void AutoFormatPreview::DrawBackground(vcl::RenderContext& rRenderContext)
             rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
             rRenderContext.SetLineColor();
             rRenderContext.SetFillColor(aBrushItem.GetColor());
-            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
             rRenderContext.DrawRect(
                 tools::Rectangle(
                     basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),


More information about the Libreoffice-commits mailing list