[Libreoffice-commits] core.git: Branch 'feature/BorderlineFix' - 40 commits - editeng/source forms/source include/editeng include/sfx2 include/svx include/tools offapi/com offapi/UnoApi_offapi.mk oox/source reportdesign/source sc/Module_sc.mk sc/qa sc/source sc/UITest_calc_tests.mk sd/inc sd/qa sd/source sfx2/source sot/source svx/inc svx/Library_svxcore.mk svx/Library_svx.mk svx/source sw/source sysui/desktop test/source tools/source vcl/source writerfilter/source

Armin Le Grand Armin.Le.Grand at cib.de
Sun Jan 28 15:21:03 UTC 2018


Rebased ref, commits from common ancestor:
commit eea1657b8f0714ec7ab1d38b0b836b70de623513
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 e589d8d71a0c11bf3c982633b6da4ff181bd7fd0
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 2a83fd10ea9badefde3881aec09c12eaee600c0f
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 f9053e5df2d4c25330369495c068c1f0548f6534
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 16598c3a804f53f78a07b5aa2a5655473b44e28e
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 940d3ae14f1252f939b6067e40fb94da7e896ab4
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 2ed0bba487e03da94bcf648fecf5e11a1c69f8cc
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 1f14f2959a8829df0e5cb4d9009237c920748327
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 ea2e74c9156f852df1bd7b73cbeab14e7a73b34c
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()),
commit 9b5730f92967b6a8f4fce349bcd951f388b940df
Author: Tamas Bunth <tamas.bunth at collabora.co.uk>
Date:   Sun Jan 28 00:14:55 2018 +0100

    tdf#114736 no need to call AdjustLayout here
    
    Change-Id: Iae8c953155d46e53cffdf3483e3b4b95157719f6
    Reviewed-on: https://gerrit.libreoffice.org/48761
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tamás Bunth <btomi96 at gmail.com>

diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 88ba96a36ce4..10daf309737e 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -886,8 +886,6 @@ void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr,
         ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStrModifiable, nIndex, nLen,
                 0, nullptr);
 
-        // position, justify, etc. the layout
-        pLayoutCache->AdjustLayout( aLayoutArgs );
         pLayoutCache->DrawBase() = ImplLogicToDevicePixel( rStartPt );
 
         ImplDrawText( *pLayoutCache );
commit 968084838e980b4152d88b95570c16ebad9d9b16
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Sun Jan 28 13:07:40 2018 +0100

    tdf#115276: multiply quarter-points by 5 (not divide) to convert to twips
    
    Unit test will come in separate commit
    
    Change-Id: I4cd6983d708868883c766b239cb57752106a59bf
    Reviewed-on: https://gerrit.libreoffice.org/48780
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
index a704bbdf2ffa..726cb90acb37 100644
--- a/writerfilter/source/rtftok/rtfdispatchvalue.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
@@ -557,7 +557,8 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
         break;
         case RTF_EXPND:
         {
-            auto pValue = std::make_shared<RTFValue>(nParam / 5);
+            // Convert quarter-points to twentieths of a point
+            auto pValue = std::make_shared<RTFValue>(nParam * 5);
             m_aStates.top().aCharacterSprms.set(NS_ooxml::LN_EG_RPrBase_spacing, pValue);
         }
         break;
commit fdd41c995d1f719e92c6f083e780226114762f05
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Sat Jan 27 19:38:12 2018 +0000

    ofz#5747 short->sal_Int32 like in StgDataStrm
    
    Change-Id: I254c00b1142d7187beabe5d18532efec036de494
    Reviewed-on: https://gerrit.libreoffice.org/48751
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sot/source/sdstor/stgstrms.cxx b/sot/source/sdstor/stgstrms.cxx
index 00a1a53c4314..efa03cd14d20 100644
--- a/sot/source/sdstor/stgstrms.cxx
+++ b/sot/source/sdstor/stgstrms.cxx
@@ -1066,7 +1066,7 @@ sal_Int32 StgSmallStrm::Read( void* pBuf, sal_Int32 n )
     // small stream is likely to be < 64 KBytes.
     if( ( m_nPos + n ) > m_nSize )
         n = m_nSize - m_nPos;
-    short nDone = 0;
+    sal_Int32 nDone = 0;
     while( n )
     {
         short nBytes = m_nPageSize - m_nOffset;
@@ -1083,7 +1083,7 @@ sal_Int32 StgSmallStrm::Read( void* pBuf, sal_Int32 n )
                 break;
             // all reading through the stream
             short nRes = static_cast<short>(m_pData->Read( static_cast<sal_uInt8*>(pBuf) + nDone, nBytes ));
-            nDone = nDone + nRes;
+            nDone += nRes;
             m_nPos += nRes;
             n -= nRes;
             m_nOffset = m_nOffset + nRes;
@@ -1102,7 +1102,7 @@ sal_Int32 StgSmallStrm::Write( const void* pBuf, sal_Int32 n )
 {
     // you can safely assume that reads are not huge, since the
     // small stream is likely to be < 64 KBytes.
-    short nDone = 0;
+    sal_Int32 nDone = 0;
     if( ( m_nPos + n ) > m_nSize )
     {
         sal_Int32 nOld = m_nPos;
@@ -1126,7 +1126,7 @@ sal_Int32 StgSmallStrm::Write( const void* pBuf, sal_Int32 n )
             if( !m_pData->Pos2Page( nDataPos ) )
                 break;
             short nRes = static_cast<short>(m_pData->Write( static_cast<sal_uInt8 const *>(pBuf) + nDone, nBytes ));
-            nDone = nDone + nRes;
+            nDone += nRes;
             m_nPos += nRes;
             n -= nRes;
             m_nOffset = m_nOffset + nRes;
commit b74750a9d8bbbd290832d2750a3e0174fe983530
Author: Mark Hung <marklh9 at gmail.com>
Date:   Sat Jan 20 17:23:06 2018 +0800

    tdf#35301 offapi: add RubyPosition for filters.
    
    RubyPosition describes the position of the ruby text
    relative to the base text. ABOVE and BELOW were defined
    in ODF, while INTER_CHARACTER is originated from CSS
    to indicate the alignment used in traditional Chinese.
    For INTER_CHARACTER, the ruby text is aligned vertically
    on the right side of the base text, disregard of the
    writing mode is horizontal or vertical.
    
    Change-Id: I89224704c192adf9ebb94024d0f2b03f00880cf5
    Reviewed-on: https://gerrit.libreoffice.org/48326
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 785c79a1667d..5b7012ee7006 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -3718,6 +3718,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/text,\
 	ReferenceFieldSource \
 	RelOrientation \
 	RubyAdjust \
+	RubyPosition \
 	SectionFileLink \
 	SetVariableType \
 	SizeType \
diff --git a/offapi/com/sun/star/style/CharacterProperties.idl b/offapi/com/sun/star/style/CharacterProperties.idl
index 5d56f0febb7b..010dab9acb53 100644
--- a/offapi/com/sun/star/style/CharacterProperties.idl
+++ b/offapi/com/sun/star/style/CharacterProperties.idl
@@ -268,6 +268,8 @@ published service CharacterProperties
 
     /** This optional property determines whether the ruby text is printed
         above/left or below/right of the text.
+       <p>This property is replaced by RubyPosition.</p>
+        @deprecated
      */
     [optional, property] boolean RubyIsAbove;
 
@@ -452,6 +454,12 @@ published service CharacterProperties
     */
     [optional, property] sequence<com::sun::star::beans::PropertyValue> CharInteropGrabBag;
 
+    /** This optional property determines the position of the ruby .
+        @see com::sun::star::text::RubyPosition
+        @since LibreOffice 6.1
+     */
+    [optional, property] short RubyPosition;
+
 };
 
 }; }; }; };
diff --git a/offapi/com/sun/star/text/RubyPosition.idl b/offapi/com/sun/star/text/RubyPosition.idl
new file mode 100644
index 000000000000..39258e5f8a84
--- /dev/null
+++ b/offapi/com/sun/star/text/RubyPosition.idl
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#ifndef __com_sun_star_text_RubyPosition_idl__
+#define __com_sun_star_text_RubyPosition_idl__
+
+
+
+ module com {  module sun {  module star {  module text {
+
+
+/** These constants define the position of ruby text.
+    @since LibreOffice 6.1
+ */
+constants RubyPosition
+{
+    /** ruby text should be above or on the right side of base text.
+     */
+    const short ABOVE = 0;
+    /** ruby text should be below or on the left side of base text.
+     */
+    const short BELOW = 1;
+    /** Vertically aligned on right side of the base text in horizontal mode.
+        <P>This is the same as ABOVE in vertical writing mode.</P>
+     */
+    const short INTER_CHARACTER = 2;
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
commit 972cb3ea9949325d74b9d7d919765e22df0101d7
Author: Justin Luth <justin_luth at sil.org>
Date:   Thu Jan 18 18:49:07 2018 +0300

    mailconfig UI: default POP port 995 and toggle with IMAP ports
    
    SSL is now default, so change POP3's default to port 995.
    Also, suggest appropriate secure/insecure ports for
    IMAP and POP as the user switches between them.
    
    Change-Id: Ib930504956a222d0d6eb3cad969907751602c106
    Reviewed-on: https://gerrit.libreoffice.org/48212
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sw/source/ui/config/mailconfigpage.cxx b/sw/source/ui/config/mailconfigpage.cxx
index df0984ea5f72..c3928d35eccb 100644
--- a/sw/source/ui/config/mailconfigpage.cxx
+++ b/sw/source/ui/config/mailconfigpage.cxx
@@ -107,6 +107,7 @@ class SwAuthenticationSettingsDialog : public SfxModalDialog
     DECL_LINK(OKHdl_Impl, Button*, void);
     DECL_LINK( CheckBoxHdl_Impl, Button*, void);
     DECL_LINK(RadioButtonHdl_Impl, Button*, void);
+    DECL_LINK(InServerHdl_Impl, Button*, void);
 
 public:
     SwAuthenticationSettingsDialog(SwMailConfigPage* pParent, SwMailMergeConfigItem& rItem);
@@ -423,6 +424,9 @@ SwAuthenticationSettingsDialog::SwAuthenticationSettingsDialog(
     m_pSeparateAuthenticationRB->SetClickHdl( aRBLink );
     m_pSMTPAfterPOPRB->SetClickHdl( aRBLink );
     m_pOKPB->SetClickHdl( LINK( this, SwAuthenticationSettingsDialog, OKHdl_Impl));
+    Link<Button*,void> aInServerLink = LINK( this, SwAuthenticationSettingsDialog, InServerHdl_Impl );
+    m_pPOP3RB->SetClickHdl( aInServerLink );
+    m_pIMAPRB->SetClickHdl( aInServerLink );
 
     m_pAuthenticationCB->Check( rConfigItem.IsAuthentication() );
     if(rConfigItem.IsSMTPAfterPOP())
@@ -535,4 +539,11 @@ IMPL_LINK_NOARG(SwAuthenticationSettingsDialog, RadioButtonHdl_Impl, Button*, vo
     m_pInPasswordED->Enable(bNotSeparate);
 }
 
+IMPL_LINK_NOARG( SwAuthenticationSettingsDialog, InServerHdl_Impl, Button*, void)
+{
+    bool bPOP = m_pPOP3RB->IsChecked();
+    rConfigItem.SetInServerPOP(bPOP);
+    m_pPortNF->SetValue(rConfigItem.GetInServerPort());
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/dbui/mmconfigitem.cxx b/sw/source/uibase/dbui/mmconfigitem.cxx
index 92fbccf8381d..ee4645e1801d 100644
--- a/sw/source/uibase/dbui/mmconfigitem.cxx
+++ b/sw/source/uibase/dbui/mmconfigitem.cxx
@@ -62,6 +62,9 @@ const char cDataCommandType[]        = "DataSource/DataCommandType";
 #define SECURE_PORT     587
 #define DEFAULT_PORT    25
 #define POP_PORT        110
+#define POP_SECURE_PORT     995
+#define IMAP_PORT           143
+#define IMAP_SECURE_PORT    993
 
 struct DBAddressDataAssignment
 {
@@ -191,7 +194,7 @@ SwMailMergeConfigItem_Impl::SwMailMergeConfigItem_Impl() :
         m_bIsGreetingLineInMail(false),
         m_bIsIndividualGreetingLineInMail(false),
         m_bIsSMPTAfterPOP(false),
-        m_nInServerPort( POP_PORT ),
+        m_nInServerPort( POP_SECURE_PORT ),
         m_bInServerPOP( true ),
         m_nMailPort(0),
         m_bIsMailReplyTo(false),
@@ -1479,7 +1482,21 @@ void SwMailMergeConfigItem::SetInServerName(const OUString& rServer)
 
 sal_Int16           SwMailMergeConfigItem::GetInServerPort() const
 {
-    return m_pImpl->m_nInServerPort;
+    // provide appropriate TCP port as user toggles between POP/IMAP if current port is one of the defaults
+    switch (m_pImpl->m_nInServerPort)
+    {
+    case POP_SECURE_PORT:
+    case POP_PORT:
+    case IMAP_SECURE_PORT:
+    case IMAP_PORT:
+        if ( m_pImpl->m_bInServerPOP )
+            return m_pImpl->m_bIsSecureConnection ? POP_SECURE_PORT : POP_PORT;
+        else
+            return m_pImpl->m_bIsSecureConnection ? IMAP_SECURE_PORT : IMAP_PORT;
+        break;
+    default:
+        return m_pImpl->m_nInServerPort;
+    }
 }
 
 void SwMailMergeConfigItem::SetInServerPort(sal_Int16 nSet)
commit 69acbf1994a2fd8606b119e7716996fb103b75c8
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
Date:   Sun Jan 28 08:34:00 2018 +0100

    tdf#111786: PPTX export: Shape's line transparency is not exported
    
    Change-Id: Iab11906e6ed79e1e39bba1b07b50a25887517f3a
    Reviewed-on: https://gerrit.libreoffice.org/48763
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>

diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 5af5dce2d12f..1deec7c82f74 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -577,6 +577,7 @@ void DrawingML::WriteOutline( const Reference<XPropertySet>& rXPropSet )
 
     sal_uInt32 nLineWidth = 0;
     sal_uInt32 nColor = 0;
+    sal_Int32 nColorAlpha = MAX_PERCENT;
     bool bColorSet = false;
     const char* cap = nullptr;
     drawing::LineDash aLineDash;
@@ -656,6 +657,10 @@ void DrawingML::WriteOutline( const Reference<XPropertySet>& rXPropSet )
                 nColor = mAny.get<sal_uInt32>() & 0xffffff;
                 bColorSet = true;
             }
+            if ( GETA( LineTransparence ) )
+            {
+                nColorAlpha = MAX_PERCENT - (mAny.get<sal_Int16>() * PER_PERCENT);
+            }
             break;
     }
 
@@ -670,7 +675,7 @@ void DrawingML::WriteOutline( const Reference<XPropertySet>& rXPropSet )
         if( nColor != nOriginalColor )
         {
             // the user has set a different color for the line
-            WriteSolidFill( nColor );
+            WriteSolidFill( nColor, nColorAlpha );
         }
         else if( !sColorFillScheme.isEmpty() )
         {
@@ -687,7 +692,7 @@ void DrawingML::WriteOutline( const Reference<XPropertySet>& rXPropSet )
         }
         else
         {
-            WriteSolidFill( nColor );
+            WriteSolidFill( nColor, nColorAlpha );
         }
     }
 
diff --git a/sd/qa/unit/data/pptx/tdf111786.pptx b/sd/qa/unit/data/pptx/tdf111786.pptx
new file mode 100755
index 000000000000..5d8f62b24a40
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf111786.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index acb6256c0c40..b530790b038a 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -127,6 +127,7 @@ public:
     void testTdf68759();
     void testTdf90626();
     void testTdf107608();
+    void testTdf111786();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -179,6 +180,7 @@ public:
     CPPUNIT_TEST(testTdf68759);
     CPPUNIT_TEST(testTdf90626);
     CPPUNIT_TEST(testTdf107608);
+    CPPUNIT_TEST(testTdf111786);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1379,6 +1381,27 @@ void SdOOXMLExportTest2::testTdf107608()
     xDocShRef->DoClose();
 }
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list